Faiss是Facebook开源的向量召回引擎,用于寻找与某个向量最相似的N个向量。
1. 简介
向量量化(Vector Quantization)
所谓向量量化,就是将原来无限的空间 映射到一个有限的向量集合.
当然这里的映射函数也不是随便指定的,需要满足误差最小的原则,一种方法是将优化函数设置为最小平方误差:
正好就是k-means方法的目标函数!因此我们可以用k-means作为寻找最佳codebook的方法。
假设我们将原来2000W个向量映射到大小为20W的集合中(平均每个中心点代表100个向量)。
乘积量化PQ(Product Quantization)
很多时候我们向量不同部分之间的分布是不同的,将向量分成 m
个不同的部分,对每个部分进行向量量化。这样每部分的中心向量数 k 会很小,可以减少时间复杂度。
可以划分为m组向量,得到每组的cookbook,最终连乘。
在没有Quantization的场景下,距离计算是直接对两个点计算 ,但在Quantization的场景下,不需要直接计算x和y的距离,而是通过中心点进行计算。
SDC
SDC(Symmetric Distance Computation): 两个向量之间的距离以两个向量所在的中心点距离来度量。误差小于等于x到中心点的距离+y到中心点的距离。
ADC
ADC(Asymmetric Distance Computation):x与y之间的距离以x与y所在的中心点距离来度量。用到三角形性质:两边之差小于第三边,所以误差一定小于等于y与中心点之间的距离
索引结构
直接计算的时间主要耗费在与所有的中心向量进行对比上了。一种很自然的方法就是先找到一个大概的候选中心节点,避免与大量根本不可能的是最近邻的点进行计算。
粗糙量化(coarse quantization)+残差量化
核心思想:层次化量化,这个也是Faiss中PQ索引的实现方式。其中粗糙量化使用聚类量化,用划分到的粗糙聚类簇的中心向量来粗粒度量化该向量,该结果存在较大的误差;接着对残差结果进行细粒度乘积量化。这样的话,误差就小了。
参考: