我们在多个代表实际应用的典型数据集上,对向量编解码器(vector codec)进行了对比评测。
所有测试的步骤都一样:我们通过index_factory生成一个编解码器,然后用100万个具有代表性的向量进行训练。接着,我们对以下三点进行评估:
- 重构误差(reconstruction error):在另一组100万个独立的向量上,先编码、再解码,计算平均L2距离(非平方)。注意部分编解码器(比如ITQ)无法合理进行重构。
- 对称相似度搜索准确率(symmetric similarity search accuracy):即“1-最近邻召回率@1”。在1万个向量上,先进行编码/解码处理,再在之前那100万个也已编码/解码的向量中做最近邻搜索。反映了编解码器对向量区分能力的破坏程度。对于二值编码器,我们用汉明距离评测。
- 非对称相似度搜索准确率(asymmetric similarity search accuracy):和上面类似,但查询向量不进行编码。模拟临时查询向量和已编码数据库向量对比的实际场景。
评测结果以表格(按码长升序排列)和对称检索准确率的曲线图方式展示。所选择的编解码器覆盖了主流的基线算法。优化调整可能还能进一步提升部分方法的性能。
本组实验尚未包含现阶段内存效率最佳的“加法量化(Additive quantization)”方案。请参考additive quantizers wiki获取相关结果。
SIFT1M
SIFT1M数据集为学术界经典案例:包含100万个128维SIFT向量。每个向量以字节(byte)形式存储,因此编码长度超过128字节没有意义。
以下表格展示了最有代表性的一组实验数据:
| 编解码器(factory key) | 码长 code size | 编解码器大小 codec size | 重构误差 recons error | 对称准确率@1 sym recall @ 1 | 非对称准确率@1 asym recall @ 1 | 解码耗时(秒) decode time |
|---|---|---|---|---|---|---|
| ITQ64,LSH | 8 | 48.7 k | - | 0.051 | - | - |
| OPQ8_48,PQ8 | 8 | 72.2 k | 308.2 | 0.141 | 0.220 | 0.23 |
| PCAR24,ZnLattice1x54_6 | 8 | 77.3 k | 364 | 0.101 | 0.145 | 0.20 |
| OPQ8_48,PQ8x10 | 10 | 216 k | 301.5 | 0.215 | 0.302 | 0.25 |
| OPQ8_48,PQ8x12 | 12 | 792 k | 297.1 | 0.282 | 0.353 | 0.27 |
| Pad128,ITQ128,LSH | 16 | 129 k | - | 0.129 | - | - |
| OPQ16_64,PQ16 | 16 | 96.2 k | 138.8 | 0.307 | 0.412 | 0.23 |
| OPQ16_64,PQ16x10 | 20 | 288 k | 125.9 | 0.428 | 0.504 | 0.28 |
| OPQ16_64,PQ16x12 | 24 | 1.03 M | 118.7 | 0.523 | 0.567 | 0.34 |
| Pad256,ITQ256,LSH | 32 | 514 k | - | 0.223 | - | - |
| PCAR64,SQ4 | 32 | 97.9 k | 121.2 | 0.481 | 0.540 | 0.22 |
| PCAR96,ZnLattice4x54_6 | 32 | 114 k | 98.18 | 0.468 | 0.572 | 0.60 |
| OPQ32_128,IVF16384,PQ32 | 34 | 8.19 M | 61.86 | 0.612 | 0.666 | 0.14 |
| OPQ32_128,PQ32x10 | 40 | 576 k | 56.2 | 0.649 | 0.718 | 0.57 |
| OPQ32_128,Residual2x14,PQ32x10 | 44 | 8.56 M | 45.34 | 0.727 | 0.764 | 0.11 |
| OPQ32_128,Residual2x14,PQ32x12 | 52 | 10.1 M | 36.2 | 0.789 | 0.809 | 0.11 |
| OPQ32_128,Residual2x14,PQ32x14 | 60 | 16.1 M | 29.55 | 0.835 | 0.850 | 0.14 |
| SQ4 | 64 | 1,105 | 42.19 | 0.740 | 0.780 | 0.03 |
| OPQ64_256,PQ64x10 | 80 | 1.13 M | 17.32 | 0.878 | 0.896 | 1.04 |
| SQ6 | 96 | 1,105 | 9.904 | 0.928 | 0.942 | 0.06 |
| OPQ64_256,PQ64x12 | 96 | 4.13 M | 10.12 | 0.922 | 0.933 | 1.25 |
| PCAR128,SQ8 | 128 | 131 k | 3.201 | 0.968 | 0.977 | 0.38 |
| SQ8 | 128 | 1,105 | 2.468 | 0.976 | 0.979 | 0.04 |
| SQfp16 | 256 | 81 | 0 | 0.992 | 0.992 | 0.03 |
如果表格中为“nan”,表示在该算法下该项目不适用(比如ITQ无法合理重构)。解码耗时单位为解码100万个向量所需秒数(48线程)。
主要观察点:
ITQ64,LSH是极为传统的二值哈希方法,所有配置下均被产品量化(Product Quantizer, PQ)及标量量化(Scalar Quantizer, SQ)方法超越。- PQ相关方法(及其结合有旋转预处理的OPQ变体)在相似度检索中表现突出。不过OPQ需要在编解码器中额外存储旋转矩阵,因此会增大模型体积。
- 对于同一PQ类型(例如PQ16),提升每个量化器(quantizer)位数通常能在码长增加不大的情况下大幅提高准确率。
- 残差编码(Residual codec)比PQ稍好,但编码速度慢,且训练数据需求更大。
SQ8理论应有100%准确,但受到量化误差(quantization artifact)影响而未达到。- OPQ和PCA矩阵对于大规模数据集占用空间较大。尤其PCA矩阵会存两份(原始特征值也保留)。对输入维度为d的PCA,可从编解码器体积中减去
d*d*4字节。 - 格点量化(lattice quantizer)优于ITQ,但不及标量量化,部分原因可能是参数未针对短向量进一步优化。
Resnet50
该数据集为resnet50网络平均池化层输出的2048维向量,来源见low-shot-with-diffusion。
| 编解码器(factory key) | 码长 code size | 编解码器大小 codec size | 重构误差 recons error | 对称准确率@1 sym recall @ 1 | 非对称准确率@1 asym recall @ 1 | 编码耗时(秒) encode time | 解码耗时(秒) decode time |
|---|---|---|---|---|---|---|---|
| ITQ64,LSH | 8 | 536 k | - | 0.028 | - | 42.41 | - |
| OPQ8_48,PQ8 | 8 | 432 k | 11.14 | 0.049 | 0.086 | 18.95 | 1.91 |
| PCAR24,ZnLattice1x54_6 | 8 | 16.2 M | 12.67 | 0.045 | 0.060 | 18.93 | 1.21 |
| OPQ8_48,PQ8x10 | 10 | 576 k | 10.89 | 0.082 | 0.129 | 23.43 | 1.95 |
| OPQ24_96,PQ12 | 12 | 864 k | 10.29 | 0.071 | 0.129 | 14.53 | 0.94 |
| OPQ8_48,PQ8x12 | 12 | 1.13 M | 10.8 | 0.124 | 0.171 | 40.86 | 0.79 |
| Pad128,ITQ128,LSH | 16 | 1.07 M | - | 0.069 | - | 41.59 | - |
| RR128,LSHt | 16 | 1.00 M | - | 0.056 | - | 18.27 | - |
| OPQ16_64,PQ16 | 16 | 576 k | 10.14 | 0.161 | 0.214 | 13.93 | 0.89 |
| OPQ16_64,PQ16x10 | 20 | 768 k | 9.904 | 0.235 | 0.278 | 15.74 | 0.86 |
| OPQ16_64,PQ16x12 | 24 | 1.5 M | 9.779 | 0.284 | 0.316 | 21.72 | 0.92 |
| OPQ16_64,PQ16x14 | 28 | 4.5 M | 9.717 | 0.318 | 0.342 | 45.72 | 0.92 |
| Pad256,ITQ256,LSH | 32 | 2.26 M | - | 0.125 | - | 43.74 | - |
| PCAR96,ZnLattice4x54_6 | 32 | 16.8 M | 8.84 | 0.361 | 0.408 | 22.24 | 1.20 |
| PCAR64,SQ4 | 32 | 16.5 M | 9.96 | 0.255 | 0.291 | 14.65 | 0.84 |
| OPQ32_128,IVF16384,PQ32 | 34 | 9.13 M | 7.783 | 0.419 | 0.486 | 23.32 | 0.86 |
| OPQ32_128,PQ32x10 | 40 | 1.5 M | 7.773 | 0.440 | 0.496 | 29.70 | 1.37 |
| OPQ32_128,Residual2x14,PQ32x10 | 44 | 9.5 M | 7.571 | 0.527 | 0.569 | 46.01 | 1.00 |
| OPQ32_128,PQ32x12 | 48 | 3 M | 7.566 | 0.516 | 0.554 | 32.23 | 1.22 |
| OPQ32_128,Residual2x14,PQ32x12 | 52 | 11 M | 7.472 | 0.582 | 0.609 | 57.47 | 0.91 |
| OPQ32_128,Residual2x14,PQ32x14 | 60 | 17 M | 7.415 | 0.603 | 0.615 | 95.27 | 0.71 |
| OPQ64_256,PQ64 | 64 | 2.25 M | 5.801 | 0.540 | 0.609 | 17.50 | 1.47 |
| PCAR128,SQ4 | 64 | 17 M | 7.763 | 0.457 | 0.515 | 14.18 | 1.03 |
| OPQ64_256,PQ64x10 | 80 | 3 M | 5.367 | 0.630 | 0.691 | 28.46 | 1.87 |
| OPQ64_256,PQ64x12 | 96 | 6 M | 5.134 | 0.716 | 0.756 | 47.76 | 1.93 |
| OPQ128_512,PQ128 | 128 | 4.5 M | 4.159 | 0.713 | 0.752 | 19.18 | 4.18 |
| PCAR128,SQ8 | 128 | 17 M | 7.404 | 0.642 | 0.647 | 15.39 | 1.03 |
| PCAR384,ZnLattice16x54_6 | 128 | 19 M | 4.688 | 0.679 | 0.737 | 19.05 | 2.75 |
| OPQ128_512,PQ128x10 | 160 | 6 M | 3.769 | 0.781 | 0.811 | 29.75 | 3.30 |
| OPQ128_512,PQ128x12 | 192 | 12 M | 3.564 | 0.829 | 0.851 | 76.59 | 4.11 |
| OPQ128_512,PQ128x14 | 224 | 36 M | 3.428 | 0.854 | 0.873 | 309.20 | 9.02 |
| PCAR256,SQ8 | 256 | 18 M | 4.861 | 0.846 | 0.850 | 38.03 | 1.40 |
| PCAR1024,Residual2x14,PQ256 | 260 | 89 M | 3.6 | 0.709 | 0.769 | 60.21 | 4.64 |
| PCAR1024,Residual2x14,PQ256x12 | 388 | 104 M | 2.529 | 0.863 | 0.890 | 181.39 | 4.76 |
| PCAR512,SQ8 | 512 | 20 M | 3.233 | 0.919 | 0.921 | 18.14 | 4.00 |
| PCAR1024,PQ512x12 | 768 | 40 M | 2.01 | 0.953 | 0.955 | 192.48 | 13.30 |
| SQ4 | 1024 | 16.1 k | 3.534 | 0.725 | 0.760 | 50.48 | 0.57 |
| SQ8 | 2048 | 16.1 k | 0.2162 | 0.980 | 0.982 | 16.80 | 0.58 |
| SQfp16 | 4096 | 81 | 0.004493 | 0.994 | 0.994 | 15.67 | 0.53 |
主要观察点:
- ITQ在高维情况下一样表现不佳
- 对于高维场景,PQ系列光是模型体积就达到100MB以上,编码开销也很高
- 标量量化(SQ)在高维情况下非常有吸引力,因为无需存储庞大模型
- 残差编码(Residual codec)精度略高于SQ
- 格点量化(lattice quantizer)在低码长(up to 32 bits)时能媲美OPQ系列,训练耗时低但编码解码非常慢
重构误差曲线
如下图为重构误差比较。可以看到召回率和重构误差高度相关:误差越低检索效果越好。
句子嵌入(Sentence Embeddings)
本数据集来源于LASER toolkit,包含1024维的德语句子向量。
| 编解码器(factory key) | 码长 code size | 编解码器大小 codec size | 重构误差 recons error | 对称准确率@1 sym recall @ 1 | 非对称准确率@1 asym recall @ 1 | 编码耗时(秒) encode time | 解码耗时(秒) decode time |
|---|---|---|---|---|---|---|---|
| ITQ64,LSH | 8 | 276 k | - | 0.025 | - | 43.36 | - |
| OPQ8_48,PQ8 | 8 | 240 k | 0.04436 | 0.034 | 0.062 | 9.93 | 1.82 |
| PCAR24,ZnLattice1x54_6 | 8 | 4.1 M | 0.04515 | 0.030 | 0.038 | 9.56 | 1.75 |
| OPQ8_48,PQ8x10 | 10 | 384 k | 0.04405 | 0.052 | 0.080 | 13.59 | 0.47 |
| OPQ24_96,PQ12 | 12 | 480 k | 0.04337 | 0.054 | 0.101 | 7.58 | 0.63 |
| OPQ8_48,PQ8x12 | 12 | 960 k | 0.04384 | 0.070 | 0.090 | 33.32 | 0.47 |
| Pad128,ITQ128,LSH | 16 | 580 k | - | 0.063 | - | 32.96 | - |
| OPQ16_64,PQ16 | 16 | 320 k | 0.04318 | 0.098 | 0.127 | 13.10 | 0.52 |
| OPQ16_64,PQ16x10 | 20 | 512 k | 0.04292 | 0.126 | 0.143 | 10.93 | 0.65 |
| OPQ16_64,PQ16x12 | 24 | 1.25 M | 0.04278 | 0.141 | 0.157 | 15.56 | 0.66 |
| OPQ24_96,PQ24 | 24 | 480 k | 0.04203 | 0.155 | 0.202 | 40.63 | 0.59 |
| OPQ16_64,PQ16x14 | 28 | 4.25 M | 0.0427 | 0.151 | 0.160 | 102.27 | 0.59 |
| Pad256,ITQ256,LSH | 32 | 1.25 M | - | 0.121 | - | 33.70 | - |
| OPQ32_128,PQ32 | 32 | 640 k | 0.04111 | 0.206 | 0.255 | 18.77 | 0.83 |
| PCAR64,SQ4 | 32 | 4.26 M | 0.04323 | 0.090 | 0.116 | 16.19 | 0.51 |
编解码器基准测试结果(下)
以下表格汇总了多种编码器(编解码器,Codec)在不同参数设置下的基准测试结果。每一行都代表一种组合的配置或量化方式,下方为详细参数解释。
| 方法(编码器组合) | 维度 | 训练样本数 | 误码率 | Top-1 精度 | Top-5 精度 | 编码速度 (ms/样本) | 查询速度 (ms/样本) |
|---|---|---|---|---|---|---|---|
| PCAR96,ZnLattice4x54_6 | 32 | 4.38 M | 0.04168 | 0.201 | 0.222 | 8.69 | 0.81 |
| OPQ32_128,IVF16384,PQ32 | 34 | 8.63 M | 0.04079 | 0.242 | 0.275 | 82.16 | 0.42 |
| OPQ32_128,PQ32x10 | 40 | 1 M | 0.04071 | 0.258 | 0.288 | 22.44 | 0.79 |
| OPQ32_128,Residual2x14,PQ32x10 | 44 | 9 M | 0.04055 | 0.289 | 0.305 | 34.87 | 0.41 |
| OPQ32_128,PQ32x12 | 48 | 2.5 M | 0.04052 | 0.292 | 0.307 | 91.29 | 0.89 |
| OPQ32_128,Residual2x14,PQ32x14 | 60 | 16.5 M | 0.04038 | 0.315 | 0.322 | 94.09 | 0.41 |
| OPQ64_256,PQ64 | 64 | 1.25 M | 0.03845 | 0.363 | 0.421 | 12.66 | 1.44 |
| PCAR128,SQ4 | 64 | 4.51 M | 0.04125 | 0.189 | 0.230 | 13.19 | 0.71 |
| PCAR64,SQ8 | 64 | 4.26 M | 0.04260 | 0.166 | 0.165 | 17.95 | 0.54 |
| OPQ64_256,PQ64x10 | 80 | 2 M | 0.03791 | 0.435 | 0.469 | 111.14 | 1.75 |
| OPQ64_256,PQ64x12 | 96 | 5 M | 0.03767 | 0.473 | 0.498 | 213.54 | 1.64 |
| OPQ128_512,PQ128 | 128 | 2.5 M | 0.03550 | 0.534 | 0.599 | 16.70 | 3.06 |
| PCAR384,ZnLattice16x54_6 | 128 | 5.51 M | 0.03623 | 0.554 | 0.596 | 10.71 | 1.80 |
| OPQ128_512,PQ128x10 | 160 | 4 M | 0.03497 | 0.630 | 0.668 | 25.14 | 3.18 |
| OPQ128_512,PQ128x12 | 192 | 10 M | 0.03467 | 0.680 | 0.713 | 68.92 | 3.09 |
| OPQ128_512,PQ128x14 | 224 | 34 M | 0.03452 | 0.711 | 0.729 | 338.22 | 7.07 |
| PCAR1024,PQ256 | 256 | 9.01 M | 0.01069 | 0.646 | 0.700 | 122.88 | 7.62 |
| PCAR256,SQ8 | 256 | 5.01 M | 0.03747 | 0.528 | 0.528 | 10.69 | 1.08 |
| PCAR768,ZnLattice32x54_6 | 256 | 7.01 M | 0.03314 | 0.724 | 0.780 | 12.76 | 3.42 |
| PCAR1024,Residual2x14,PQ256x12 | 388 | 88 M | 0.004612 | 0.839 | 0.867 | 208.75 | 3.67 |
| PCAR1024,PQ512 | 512 | 9.01 M | 0.003313 | 0.881 | 0.901 | 33.06 | 8.53 |
| PCAR512,SQ8 | 512 | 6.01 M | 0.03431 | 0.768 | 0.768 | 11.32 | 2.00 |
| PCAR1024,PQ512x12 | 768 | 24 M | 0.001003 | 0.965 | 0.970 | 227.62 | 13.56 |
| SQ6 | 768 | 8273 | 0.003924 | 0.843 | 0.872 | 22.25 | 0.47 |
| SQ8 | 1024 | 8273 | 0.0009623 | 0.955 | 0.965 | 18.18 | 0.27 |
| SQfp16 | 2048 | 81 | 1.041e-05 | 0.999 | 0.999 | 37.52 | 0.28 |
字段解释
- 方法(编码器组合):指本行使用的特征变换/量化/编码组合。例如:OPQ32_128(正交乘积量化)、IVF16384(倒排文件,16384簇)、PQ32(32维乘积量化)、Residual2x14(残差编码),等。
- 维度:数据经变换或编码后的特征维数。
- 训练样本数:训练量化器时用到的数据量。
- 误码率:量化重构数据和原数据的均方误差,越低表明编码质量越高。
- Top-1/Top-5 精度:在最近邻检索中,正确结果分列 Top-1 和前五(Top-5)返回的准确率。
- 编码速度(ms/样本):将一个样本转为量化编码所需的毫秒数。
- 查询速度(ms/样本):用编码向量做一次检索的平均耗时(毫秒)。
不同表项中,"OPQ" 表示正交乘积量化(Orthogonal Product Quantization),"PQ" 表示乘积量化(Product Quantization),"SQ" 表示缩减量化(Scalar Quantization),"ZnLattice" 表示点阵量化(Lattice Quantization);"Residual" 指多级残差编码;"PCAR" 则是主成分分析降维(Principal Component Analysis, PCA)。
基准测试结果观察
- 虽然本数据集的维度低于 ResNet50 嵌入(embedding),但原始检索效果却更低,因此该场景的索引和压缩更加具有挑战性。
- 残差类编解码器的编码时间消耗较大,在大规模场景下可能成为瓶颈。
- 点阵量化(Lattice Quantization,ZnLattice)在本场景下表现非常出色,准确率基本优于相同维度下的传统乘积量化方法,有一定优势。
针对此类低维特征和实际数据规模,综合考虑 Top-1/Top-5 精度、误码率和编码速度,在选型时推荐优先尝试 ZnLattice 及 OPQ+PQ 等组合。
相关代码与结果可复现性
- 基准测试的主代码:bench_standalone_codec.py
- 批量运行脚本(推荐集群运行):run_on_cluster.bash
- 所有结果图表由 该 Jupyter Notebook 生成
注意事项
部分复杂组合(如残差量化、多级 PQ)的编码速度较慢,仅适合对压缩精度有极高要求的应用场景。大规模生产环境建议权衡速度与精度后使用。
如需进一步了解各类量化器的工作原理或使用方式,请查阅相关章节或参考上述代码示例。