Faiss索引类型怎么选择
是否需要精确的结果?
是,那就得用Flat
唯一保证百分百准确性的是IndexFlatL2(L2距离)和IndexFlatIP(内积距离). 可以用来做其他索引的baseline,不支持压缩, 不支持add_with_ids, 如果需要可以包一层IDMap, 用 “IDMap,Flat” 不需要训练 不用指定参数
支持GPU加速
内存是否紧张
faiss的索引全部存在RAM中,速度和内存是tradeoff
如果一点都不care内存,就用 HNSWx
如果你有很多内存,或者数据集很小,HNSW是最好的选择,非常快而且准。x的取值在4到64之间,它是指每个向量的连接数量,x值越大 结果越准确,耗费内存越多。efSearch参数用来平衡速度和准确性,内存占用量 d * 4 + x * 2 * 4 一个向量
HNSW也不支持add_with_ids, 所以如果需要 也是加IDMap. HNSW不需要训练,不支持从索引中删除向量,不支持gpu加速。
如果内存不是要多少有多少,就用 …Flat
“…”前面三个点表示聚类操作,聚类后 Flat索引仅仅把数据组织到对应的bucket中去,它并不压缩数据,索引占用的内存跟原始的数据集大小相当. 速度和准确性的tradeoff是通过设置nprobe参数,即搜索的时候,搜多少个聚类。如果等于nlist,将会等同于bruteforce
支持gpu加速,前提是选的聚类方式也要支持gpu
如果很在意内存 就用 PCARx,…,SQ8
这个包括两个操作,一个是PCA,降维到x, 一个是PQ 也就是乘积量化 把每个向量元素压缩到一个byte,所以总起来一个向量 x个byte
不支持gpu加速
如果非常非常在意内存 就用 OPQx_y,…,PQx
PQx表示压缩向量到x个bytes的乘积量化编码,通常x<=64, 对较大编码 SQ通常差不多准,并且还更快,OPQ是个线性变换帮助压缩
y值的要求
y是x的倍数
y <= d,d是输入数据的维数
y <= 4*x
支持gpu
数据量有多大
这个问题用来确定上面那个三个点 … 数据被聚类到多个bucket里,搜索的时候,只有一部分bucket(nprobe参数)会被搜,聚类是在一堆有代表性的数据样本上做的。
怎么去选训练聚类时候用的样本数据量呢?
如果向量数小于100万,用 “…,IVFx,…”
x的取值范围4sqrt(N)到16sqrt(N), N是索引向量总数。训练聚类的时候则需要30x到256x这么多样本,当然越多越好.
如果向量总数在100万到1000万间, 用”…,IVF65536_HNSW32,…”
IVF和HNSW组合起来,HNSW用来做聚类分配, 需要3065536到25665536的样本训练。
如果向量总数在1000万到一亿间,用”…,IVF262144_HNSW32,…”
跟上面一样,65536换成262144 训练会很慢
如果向量总数在1亿到10亿间, 用”…,IVF1048576_HNSW32,…”
跟上面一样,65536换成1048576 训练会非常慢