向量搜索简介
ØFaiss: 索引库 - 库
ØMilvus 服务引擎 – 工程,实现了一些自己的算法。
ØNSG – 阿里,基于已建好的knn模型做优化,减掉一些临近点。
ØScann: google,一枝独秀。
ØAnnoy: 树模型
ØHNSW: 紧密图
ØVearch: 京东服务引擎 – 基于faiss,实现了工程化。
Ø
注:性能和效果对比:http://ann-benchmarks.com/

Faiss常见概念
Ø评价指标:效果(召回率)、性能、内存占用。
Ø查询向量:用户的查询向量。
Ø样本向量:用于训练模型的向量样本集合(训练时是根据中心点个数选取部分做训练)。
Ø中心向量: 通过样本向量聚类产生,也可以理解为生成的模型(中心向量不一定是在样本向量中,通过求平均得到)。
ØFlat: 暴力搜索(搜索时,所有向量都参与计算)
ØIp: INNER PRODUCT (向量內积)
ØIVF: 倒排
ØPQ: Product Quantizer(乘积量化,后面详细介绍)
Ø残差:
Ø 残差向量:query 向量和中心点的差,称为残差向量
Ø 残差空间:残差向量构成的空间。
Ø 空间转换: query向量减去对应中心点,把query向量映射到残差空间。
Ø 残差空间点的分布更秘,误差更小。


HNSW原理
Ø第0层中包含图中所有节点
Ø向上节点数依次减少,遵循指数衰减概率分布。
Ø建图时新加入的节点由指数衰减概率函数得出,该点最高投影到第几层,从最高的投影层向下的层中该点均存在该点。
Ø搜索时从上向下依次查询。

train
Ø聚类
Ø先有中心点:随机生成中心点(从样本集中选取,初始的样本点,会影响模型效果,可以多次更换初始中心点,获取做好的聚类效果),
Ø更新中心点:根据当前中心点,每次取平均,生成新的中心点(优化中心点,有些中心点周围没有值,有些值比较多,把值多的拆分为2个)。
ØHnsw add中心点
Ø建立连接:在IndexHNSW::add函数中完成,实际建连接在Hnsw_add_vertices中。
Ø中心点选择: 最终选择哪些中心点add 到hnws中建立图索引,还是看哪个中心点聚类的效果更新(标准: 所有训练向量和对应的中心点的距离和最小)。

search
Ø查询query向量在hnsw中对应的中心点。
Øgreedy_update_nearest从所有层中查询距离query最近的中心点。从最高层开始,在每一层查找最邻近的点。根据第0层最邻近的点,查找nprobe个临近点(后面详解)
Øsearch_from_candidates(性能好): 查询候选集对应的临近点,把临近点添加到候选集,再从候选集中选出距离query最小的中心点,重复这个过程,如果新的中心点没有临近点或者查询的临近点个数>efSearch(默认值16)退出。
Øsearch_from_candidate_unbounded(效果好): 查询过程和search_from_candidates 相识,只是不再做efSearch的判定了(当所有临近点对应的向量没有更相近时推出)。

IVFPQ原理
乘积量化(Product Quantization)
Ø量化 : 指的就是将一个空间划分为多个区域,然后为每个区域编码标识
Ø乘积:指的是高维空间由多个低纬空间表示。
Ø优点:可以用较少的训练集,表示较大的训练集;内存占用少。
举例
Ø假设1024维度的向量;分4段,每段256维,比如A,B,C,D,每段256维
Ø如果有200个中心点(和维度无关),则每个子空间都对应200个中心点,一共可以表示200*200*200*200个中心点。
train
Ø入口函数IndexIVFPQ::train_residual (idx_t n, const float *x)Ø参与训练的向量集合,和中心点个数有关,不是全集(每个中心点对应256个向量)。ØHow 预先计算距离(后面详解)。

add
Ø在一级量化器中查询对应的中心点。
Ø把向量转换为残差向量。
Ø把残差向量划分为几个子空间(PQ)。
Ø在每个子空间查找对应的中心点,得到中心点对应的idx。
Ø所有子空间的idx,构成向量对应残差空间中心点的编码(code)
ØKey:对应的一级量化器的idx,id:向量的id,code:二级量化器中的idx。


search
Ø查询一级量化器对应中心点的idx及distance(每个向量查询nprobe个)。
遍历query向量查询到的nprobe个中心点对应的倒排链,选出topK。


IVFPQ 距离计算详解
Ø残差:
Øquery 向量和中心点的差,相减之后把query向量映射到残差空间。
Øwhy 残差空间点的分布更秘,误差更小。
Ø 距离计算详解
During IVFPQ search with by_residual, we compute
d = || x - y_C - y_R ||^2
x:query向量 y_c:一级量化器中心点,y_r:残差空间的中心点
d = || x - y_C ||^2 + || y_R ||^2 + 2 * (y_C|y_R) - 2 * (x|y_R)
x - y_C: 对应残差, (x - y_C) - y_R 残差距离
注: IndexIVFPQ.cpp中有详细的说明
优化
ØFaiss 可以同时查询N 个query ,每个query 都查询nprobe?
Ø是的,每个query一级量化器都返回nprobe个中心点
ØFaiss 查询优化问题
ØIndexIVF存在几种模式 parallel_mode = 0 或1, max_codes 代表扫描倒排链表时,遍历的最大向量数,只有模式为1时才生效。
Ønprobe是Faiss查询聚类中心的个数,一般值越小,查询效率越高
Ø faiss内存申请和释放问题
Ø可以用共享内存的方式,解决建库时全内存,单机建库数据量受限问题
Ø建库和检索时,内存复用。
Ø针对hnsw优化
Ø采用search_bounded_queue这种模式,只有为1,下面的设置才生效.
Ø开启do_dis_check
Ø调整efSearch的值
Ø调整建索引时,每个节点的临近点数。
向量搜索技术概览
本文介绍了多种向量搜索技术,包括Faiss、Milvus、NSG等,并详细解析了HNSW和IVFPQ的工作原理。涵盖索引构建、查询流程、优化技巧等内容。
882

被折叠的 条评论
为什么被折叠?



