Appearance
IVFPQ
IVFPQ全称为「Inverted File System with Product Quantization 」,IVFPQ = IVF + PQ,由「倒排文件系统」和「乘积量化」两种技术协同合作实现FAISS极致的查询性能,这种方法既减少了需要搜索的向量数量(通过IVF),又减少了查询向量和子空间中每个向量的距离计算复杂度(通过PQ两阶段的「预结算阶段」和「查表阶段」)。
IVFPQ图例:
[向量空间]
|
|--- [IVF区域1] -- 质心1
| |--- [PQ编码向量1]
| |--- [PQ编码向量2]
| ...
|
|--- [IVF区域2] -- 质心2
| |--- [PQ编码向量1]
| |--- [PQ编码向量2]
| ...
...
具体例子: 假设我们有100万个向量,使用1000个区域:
- 传统方法:需要计算100万次距离。
- IVFPQ方法:
- 找到10个最近的桶(假设每个桶平均有1000个向量)。
- 只需对这10,000个向量使用PQ方法计算距离即可。
- 这将搜索空间减少了99%,同时PQ还能进一步加速距离计算。
倒排文件系统 (IVF)
IVF的核心思想是将向量空间(m条向量组成的超大型向量空间)划分为k个小区域(N条向量组成的小型向量子空间,N一般远小于m),每个区域有一个中心点(称为质心),作为一种粗粒度的索引。
- 索引构建阶段:
- 使用K-means等聚类算法生成一定数量的质心。
- 将每个待索引向量分配到与其在向量空间中「距离」最近的质心所对应的子空间中。 索引构建阶段的伪代码:
对于每个向量 x:
找到最近的质心 i
将 x 添加到子空间 i 中
- 搜索阶段:
- 对于查询向量q,找到最近的t个质心(通常t远小于k)。
- 只在这T个区域中进行精确搜索,使用PQ方法计算距离,这大大减少了搜索空间。 搜索阶段的伪代码:
1. 找到距离 q 最近的 t 个质心
2. 对于这 t 个区域中的每个向量:
使用PQ方法计算与 q 的近似距离
3. 返回最相似的top-k个结果
乘积量化 (PQ)
PQ的核心思想是将高维向量分解为多个子向量,然后对每个子向量空间进行独立量化。
我们以一个1024维的向量举例:
- 向量分解: 一个1024维的向量可以被分解为8个128维的子向量。
[1024维向量] = [128维子向量1] + [128维子向量2] + ... + [128维子向量8]
- 子空间量化: 对于每个128维子空间,我们创建一个包含256个聚类中心的「codebook」,每个子向量都用其最近的聚类中心来表示。
[128维子向量] → [8位编码] (表示256个聚类中心中的一个)
- 压缩存储: 原始的1024维浮点向量(假设每个维度用4字节表示)需要4096字节存储。使用PQ后,我们只需要存储8个8位的编码(总空8个子向量,每个子向量用子空间的8位编码的聚类中心表示),总共8字节。
4096字节 → 8字节 (压缩率为512:1)
- 距离计算:
- 4.1. 预计算表: 对于查询向量q,我们预先计算它的每个子向量与对应codebook中所有聚类中心的距离。
距离表[i][j] = distance(q的第i个子向量, 第i个codebook的第j个中心),其中 i = [0, 7],j = [0,255]
- 4.2. 近似距离计算: 对于精搜区域中的向量x,其和查询向量q的距离可以通过查表并求和得到。
approximate_distance(q, x) = sum(距离表[i][x的第i个子向量的编码] for i in range(8)),其中 i = [0, 7],x的第i个子向量的编码 = [0,255]
- 计算复杂度分析:
- 原始方法:常规欧氏距离计算
距离 = sqrt((q[0] - x[0])^2 + (q[1] - x[1])^2 + ... + (q[1023] - x[1023])^2)
对于每个向量,这需要1024次减法,1024次平方,1023次加法和1次开方操作。
- PQ方法: 对于查询向量q,我们预先计算它的每个子向量与对应codebook中所有聚类中心的距离(一次性计算)。
对于i从0到7:
对于j从0到255:
距离表[i][j] = distance(q的第i个子向量, 第i个codebook的第j个聚类中心)
对于数据库中的向量x,它在索引阶段已经被表示为8个编码 [c1, c2, ..., c8],其中ci = [1, 256]。于是,近似距离计算变为:
近似距离 = 距离表[0][c1] + 距离表[1][c2] + ... + 距离表[7][c8]
这只需要8次查表操作和7次加法。 6. PQ过程图示:
Query Vector : [q1|q2|q3|...|q8]
| | | |
v v v v
Distance Lookup Table : [T1|T2|T3|...|T8]
| | | |
v v v v
Indexed Vectors : [c1|c2|c3|...|c8] (ci是子空间中某个聚类中心的编码)
Approximate Distance = T1[c1] + T2[c2] + T3[c3] + ... + T8[c8]
- 具体例子: 假设我们有,查询向量q = [1.2, 3.4, 5.6, 7.8],我们将4维向量分成2个2维子向量,Codebook 1 = {[1, 3], [2, 4]},Codebook 2 = {[5, 7], [6, 8]}。
- 预计算步骤:
距离表[0][0] = distance([1.2, 3.4], [1, 3]) = 0.447
距离表[0][1] = distance([1.2, 3.4], [2, 4]) = 1.131
距离表[1][0] = distance([5.6, 7.8], [5, 7]) = 0.894
距离表[1][1] = distance([5.6, 7.8], [6, 8]) = 0.447
- 如果数据库中有一个向量x被编码为[0, 1],意味着:1)x的前两维最接近[1, 3];2)x的后两维最接近[6, 8]。
- 计算x与q的近似距离:
近似距离 = 距离表[0][0] + 距离表[1][1] = 0.447 + 0.447 = 0.894
这个过程只需要2次查表和1次加法,而不是原来的4次减法,4次平方,3次加法和1次开方。
总结
IVF在IVFPQ中提供了一个粗粒度的过滤机制,显著减少了需要详细比较的向量数量。它与PQ的高效距离计算相结合,使得在大规模数据集上进行「近似最近邻搜索(Approximate Nearest Neighbor Search,简称ANN)」变得非常高效。这种方法牺牲了一些精度,换来了显著的速度提升,特别适合处理大规模高维数据。
HNSW
HNSW全称为「Hierarchical Navigable Small World」,是Faiss中另一种高效的高纬向量索引方法,特别适用于海量高维向量的近似最近邻搜索。
HNSW建立了一个多层图结构,每一层都是一个近似的"小世界"图:
[顶层] (稀疏连接)
|
v
[中间层] (中等连接)
|
v
[底层] (密集连接)
每个节点代表一个向量,节点间的边表示相似性连接。
- 图的构建过程: 从底层开始,逐层向上构建:
1. 插入新节点
2. 在当前层找到最近邻的节点
3. 与其建立连接
4. 概率性地决定是否将节点提升到上一层
示意图:
[L2] o---o
\ /
[L1] o-o-o
|/ \|
[L0] o-o-o-o-o
- 图的搜索过程: 从顶层开始,逐层向下搜索:
1. 在当前层找到最近的节点
2. 向下一层移动,以上一层找到的节点为起点
3. 重复上述过程直到达到底层
4. 在底层进行细粒度搜索
示意图:
[L2] o---●
\ /
[L1] o-●-o
|/ \|
[L0] o-●-●-●-o
(● 表示搜索路径)
- 关键特性
- 多层结构
- 顶层: 长距离连接,快速定位大致区域。
- 底层: 短距离连接,精确定位最近邻。
- 小世界性质
- 每个节点都有一些远距离连接,保证了搜索的高效性。
- 可导航性
- 通过贪婪搜索就能快速找到近似最近邻。
IVFPQ vs HNSW
- IVFPQ (Inverted File System with Product Quantization)
角色:
- 大规模向量检索的主要方法之一
- 适合需要高压缩率的场景
优势:
- 极高的压缩率,可以显著减少内存使用
- 适合非常大的数据集(数百万到数十亿规模)
- 查询速度很快,尤其是在GPU上
劣势:
- 相比HNSW,召回率可能略低
- 需要较多的参数调优
适用场景:
- 超大规模数据集
- 内存受限的环境
- 对查询速度和内存使用有平衡要求的应用
- HNSW (Hierarchical Navigable Small World)
角色:
- 高性能、高精度的近似最近邻搜索方法
- 适合需要高召回率的场景
优势:
- 非常高的查询速度
- 高召回率,接近暴力搜索的精度
- 支持动态插入
- 对数据分布不敏感
劣势:
- 内存消耗较大,不适合超大规模数据集
- 构建索引时间可能较长
适用场景:
- 中等规模数据集(百万级别)
- 需要高召回率的应用
- 对查询延迟要求极高的场景
- 在Faiss中的使用
IVFPQ:
- 通常用于
IndexIVFPQ
类 - 适合GPU加速
- 可以与其他技术如IMI (Inverted Multi-Index) 结合使用
HNSW:
- 通常用于
IndexHNSW
类 - 主要在CPU上使用
- 可以与其他量化方法(如PQ)结合,形成如
IndexHNSWPQ
- 选择建议
数据规模:
- 数十亿级别 → IVFPQ
- 百万级别 → HNSW 或 IVFPQ 都可以,取决于其他需求
内存限制:
- 严格 → IVFPQ
- 宽松 → HNSW
召回率要求:
- 极高 → HNSW
- 平衡 → IVFPQ
查询速度要求:
- 极快 → HNSW
- 快速但可以牺牲一些精度 → IVFPQ