首页/AI/RAG 与向量库速查/乘积量化(PQ)压缩向量
Embedding 与检索50 条

乘积量化(PQ)压缩向量

PQ 把 d 维向量切成 m 段子向量,每段用各自的码本量化:用 m 字节左右的编码替代原始浮点数组,内存可降一个数量级,代价是距离近似误差。

RAG 与向量库速查AI更新于 2026-10-13

乘积量化(PQ)是什么

PQ 把 d 维向量切成 m 段子向量,每段用一个独立码本量化:一段只保留它最接近的质心编号,一条向量最终用 m 个字节左右的编码代替 4·d 字节的浮点数组,内存降一个数量级。检索时按子空间查表累加近似距离,速度也更快。代价是距离只是近似值,压缩比越高误差越大,通常搭配 IVF 做粗排、再用原始向量对候选做重排来补偿精度。

基本信息

参数 m子空间个数,d 必须能被 m 整除
参数 nbits每段码本位数,常取 8(256 个质心)
存储每条向量约 m 字节,替代 4·d 字节
依赖训练码本需要用样本训练,训练不足则精度损失明显
常见组合IVF 粗排 + PQ 压缩 + 原始向量重排

典型使用场景

  • 内存受限的大规模索引:千万级向量无法全部以浮点驻留
  • 离线近邻分析:去重、聚类、近似推荐的候选生成阶段
  • 冷热分层:热数据保留原始向量,冷数据用 PQ 编码存放
  • 实验对照:同一份数据比较 PQ 压缩前后的召回损失与内存占用
  • 成本优化:按预算反推可接受的 m 与 nbits 组合

FAISS IVFPQ 示例

FAISS IVFPQ 示例
import faiss, numpy as np

d = 768
quantizer = faiss.IndexFlatL2(d)
index = faiss.IndexIVFPQ(quantizer, d, 1024, 96, 8)   # nlist=1024, m=96, nbits=8
index.train(np.random.rand(200000, d).astype('float32'))   # 必须先训练
index.add(np.random.rand(2000000, d).astype('float32'))
index.nprobe = 32                                     # 查询时扫描的聚类数
D, I = index.search(np.random.rand(1, d).astype('float32'), 10)

参数取舍

参数增大减小
m精度更高,编码更长内存更省,误差变大
nbits码本更细,精度上升码本变小,误差明显
nprobe召回上升、延迟上升更快但可能漏掉候选
训练样本量码本更贴合数据分布训练不足导致精度骤降

上线前的验证步骤

  • 先量基线:用精确索引记录 Recall@10,作为压缩后的对照基准
  • 逐档压缩:从低压缩比开始试,记录内存占用与召回损失的关系曲线
  • 加重排补偿:对前若干候选取原始向量重算距离,观察召回是否回到可接受区间
  • 固化配置:把 m、nbits、nprobe 写入部署配置并纳入回归评测
训练样本必须来自真实数据分布:拿随机向量或少量样本训练出来的码本,在真实查询上会表现出明显的召回下降,且这种下降很难从监控指标上看出来。

易错点

  • m 不能整除维度时构建失败,改 m 或对齐模型输出维度
  • 高压缩比下近邻距离失真,需配合重排或提高 nprobe 弥补召回
  • 跳过训练直接 add,索引报错或行为不可预期
  • 用随机样本训练码本,真实数据上的召回远低于实验值
  • 压缩后仍按精确距离做阈值判断,分数口径已变,无答案判定出现系统性偏差

数据来源与参考

  • Jégou et al., Product Quantization for Nearest Neighbor Search (IEEE TPAMI 2011)
  • FAISS wiki(IVF + PQ 与量化)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌