पाठ 11 / 28

संपीड़न: Scalar और Product Quantisation

Vectors छोटे करें ताकि ज़्यादा memory में समाएँ।

प्रति vector कम bytes, छोटी सटीकता क़ीमत

बड़े पैमाने पर memory मुख्य लागत है, इसलिए vectors अक्सर संपीड़ित होते हैं। Scalar quantisation हर संख्या को 32 की जगह 8 bits (int8) या 16 bits में रखता है: 4 या 2 गुना छोटा, आम तौर पर बहुत छोटी सटीकता हानि के साथ। Product quantisation (PQ) vector को उप-vectors में बाँटकर हर एक को छोटे सीखे codebook की निकटतम प्रविष्टि की id से बदलता है, इसलिए 256-byte का vector 8 bytes (32 गुना छोटा) बन सकता है, बड़ी पर अक्सर स्वीकार्य सटीकता हानि के साथ। संपीड़ित खोज approximate है, इसलिए उम्मीदवार खोजने में इसे उपयोग करें और चाहें तो शीर्ष परिणामों को मूल पूर्ण-परिशुद्धता vectors से दोबारा score करें। अपने डेटा पर खोया recall हमेशा मापें।

Product quantisation, चलाकर

मैंने यह Python virtual environment में numpy 2.5.3, scikit-learn 1.9.1 और faiss-cpu 1.15.1 के साथ चलाया, निश्चित random seeds के साथ ताकि संख्याएँ दोहराई जाएँ। 64-आयामी float32 vector 256 bytes लेता है; PQ index प्रति vector 8 bytes रखता है (32 गुना छोटा), और इस आसान परीक्षण में 100 थोड़े बदले queries में से हर एक को अपना मूल vector फिर भी top-1 मिला। असली डेटा और कठिन queries ज़्यादा खोते हैं।

import numpy as np, faiss
rng = np.random.default_rng(0)
d, n = 64, 20000
xb = rng.normal(size=(n, d)).astype("float32"); xq = xb[:100] + 0.05 * rng.normal(size=(100, d)).astype("float32")

flat = faiss.IndexFlatL2(d); flat.add(xb)
_, truth = flat.search(xq, 1)
pq = faiss.IndexPQ(d, 8, 8); pq.train(xb); pq.add(xb)                # 8 sub-vectors, 8 bits each = 8 bytes per vector
_, found = pq.search(xq, 1)
print("float32 bytes per vector :", d * 4)
print("PQ bytes per vector      :", 8)
print("compression              :", d * 4 // 8, "x")
print("top-1 still correct      :", float(np.mean(found[:, 0] == truth[:, 0])))

Output:

float32 bytes per vector : 256
PQ bytes per vector      : 8
compression              : 32 x
top-1 still correct      : 1.0

Scalar (int8) quantisation, चलाकर

मैंने यह Python virtual environment में numpy 2.5.3, scikit-learn 1.9.1 और faiss-cpu 1.15.1 के साथ चलाया, निश्चित random seeds के साथ ताकि संख्याएँ दोहराई जाएँ। 128-आयामी vectors को int8 में रखने से 512 bytes घटकर 128 रह जाते हैं, प्रति मान सबसे बड़ी त्रुटि 0.0016 है, और सटीक शीर्ष-10 के सारे परिणाम अब भी मिलते हैं।

import numpy as np
rng = np.random.default_rng(0)
X = rng.normal(size=(5000, 128)).astype("float32")
X /= np.linalg.norm(X, axis=1, keepdims=True)
q = X[0] + 0.1 * rng.normal(size=128).astype("float32"); q /= np.linalg.norm(q)

scale = 127 / np.abs(X).max()
Xi = np.round(X * scale).astype(np.int8)                      # 1 byte per number instead of 4
Xd = Xi.astype("float32") / scale
exact = np.argsort(-(X @ q))[:10]
approx = np.argsort(-(Xd @ q))[:10]
print("bytes per vector: float32 =", X.shape[1] * 4, "| int8 =", Xi.shape[1])
print("max absolute error per value:", round(float(np.abs(X - Xd).max()), 4))
print("top-10 overlap with exact:", len(set(exact) & set(approx)), "/ 10")

Output:

bytes per vector: float32 = 512 | int8 = 128
max absolute error per value: 0.0016
top-10 overlap with exact: 10 / 10

शीर्ष परिणाम दोबारा score करें

संपीड़ित vectors से 100 उम्मीदवार खोजें, फिर पूर्ण-परिशुद्धता vectors से उन्हें दोबारा rank करके सटीकता लौटाएँ।

त्वरित जाँच: Quantisation क्या बदले में देती है?

  • कुछ नहीं
  • अधिक सटीकता के बदले memory
  • गति के बदले सुरक्षा
  • बहुत कम memory के बदले थोड़ी सटीकता
Answer

बहुत कम memory के बदले थोड़ी सटीकता — प्रति संख्या कम bits का अर्थ छोटे vectors पर कुछ rounding त्रुटि।