【4】facebook大数据搜索库faiss使用——Faiss索引介绍

一曲冷凌霜 提交于 2020-05-07 21:37:12

基础索引如下所示:

  • 精确索引(IndexFlatL2): 主要参数d;占用字节4d;是否穷尽式搜索:是;
  • 内积精确检索(IndexFlatIP):d;4d;是;
  • 级联式图搜索(IndexHNSWFlat):d,M; 4d+8M; 否;
  • 倒置文件与精确后检验(IndexIVFFlat):quantizer,d,nlists,metric; 4d;否
  • 局部感应哈希(iNDEXlsh): d,nbits; nbits/8; 是
  • 标量量化(IndexScalarQuantizer):d; d; 是
  • PQ(IndexPQ): d, M, nbits; M(nbits=8); 是
  • 倒排文件+标量量化(IndexIVFScalarQuantizer):quantizer, d, nlists, qtype; d或d/2; 否
  • IVFADC粗量化+PQ+残差(IndexIVFPQ):quantizer,d, nlists, M, nbits; M+4或M+8;否
  • IVFADC+R即为IVFADC+基于code的rerank(IndexIVFPQR):quantizer,d, nlists, M, nbits, M_refine, nbits_refine; M+M_refine+4或M+M_refine+8; 否

单元捕获方法

常用的一种加速检索过程,但以一定找到最近邻为代价的方法是是使用例如k-means的分割技术,对应的算法有时称之为 单元捕获方法<cell-probe methods>。 我们使用一种基于多捕获的分割方法:

  • 特征空间分割为ncells单元。
  • 数据集向量根据哈希函数赋值到其中的一个单元,存储在ncells个倒置列表的倒置文件系统中(在k-means中,查询向量会赋值到离它最近的中心点)。
  • 查询时,选择nprobe个倒置列表;
  • 查询向量和每个列表中的每个库向量比较。

通过上述方法,只有部分数据库向量与查询向量比较:初步估计,这个比例大约是nprobe/ncells,但是需要注意的是,这个估计通常是偏低的,因为各个倒置列表并不是等长的。当给定查询向量的最近邻所在单元未被选中时,就会查询失败。 Faiss C++对应的index是IndexIVFFlat。构造函数将index作为参数,用于倒置列表的赋值,查询操作在这个index中进行,返回倒置列表中向量ID。

使用带有Flat Index单元捕获方法作为粗分类量化器

通常,我们使用Flat Index作为粗分类量化器。IndexIVF的训练方法给这些flat index添加中心点。nprobe在查询时确定(对于衡量速度和精确度很有用)。 注意:n表示索引的点数,选择这个中心点数的常用方法:赋值到中心点的花费 和 当解析倒置列表时需要计算的距离次数。中心点的数目大致为:ncentroids=C*sqrt(n). 注意 IndexIVFKmeansIndexIVFSphericalKmeans不是对象,而是返回IndexIVFFlat对象的函数。 警告:分割方法容易遭遇维度诅咒,对于及其高维的数据,要得到好的召回率需要很大数目的probe值。

和LSH的关系

最有名的单元捕获方法就是E2LSH,但是这个方法和它的演变方法有两个缺点:

  1. 需要很多哈希函数获得较好的结果,导致占用内存很多;
  2. 哈希函数不适用于输入数据,容易导致次优选择。

二值code

在C++,一个LSH index声明:

IndexLSH* index = new faiss::IndexLSH(d, nbits);

其中d是输入向量维度,nbits是每个存储向量的比特位数目。 而python的(改进的)LSH index构建和检索如下:

n_bits = 2*d
lsh = faiss.IndexLSH(d, n_bits)
lsh.tracin(x_train)
lsh.add(x_vase)
D, I = lsh.search(x_query, k)

注意: 该算法使用的不是vanilla-LSH,而是更好的选择。

基于量化的方法

在C++,基于量化的index由关键字PQ定义。其中n_bits必须等于8,12或者16.维度d必须是m的倍数。

倒置文件系统与PQ

倒置文件系统+PQ可能对于大规模检索最有用。通常如下使用:

coarse_quantizer = faiss.IndexFlatL2(d)
index = faiss.IndexIVFPQ(coarse_quantizer, d, ncentroids, code_size, 8)
index.nprobe = 5

可以查看IndexIVFFlat那章设置ncentroids,code_size通常是2^4~2^64。和IndexPQ一样,d是m的倍数。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!