向量检索原理

算法一般会使用embedding抽象出一个N维向量来作为一个物品的特征表示,通过计算N维特征向量的相似度来实现图搜图、文搜图等功能。向量检索的主要功能就是根据输入向量和指定的距离算法,检索出距离最近的Topk向量,学术上也成维最近邻搜索ANN。

大部分ANN算法的核心是对整个数据集聚类成几个子集,查询时只对查询向量在指定几个子集中检索,避免全局遍历。以下是常见ANN算法:

1、KD树(不常用)

二叉树,构建时会不断选择向量上方差最大(方差大说明区分度好)的维度,根据该维度上的中位数进行二分,中位数的向量建立根节点,小于中位数的划分到左子树,大于的划分到右子树,直到集合中只剩一个向量。

查询时,查询向量Q根据上面的逻辑从根节点遍历到叶子结点,把遍历的节点依次入栈,然后与叶子节点计算当前距离作为最近距离D,通过栈中的节点向上回溯。回溯时以Q为圆心,当前最近距离D为半径作圆(高维下为球),如果圆圈与根节点的超平面相交,那么递归遍历根节点和他的子节点,如果遇到比D小的节点,更新最近距离。

时间复杂度:回溯时如果与所有节点的超平面都没相交,那么时间复杂度logn;最坏情况下都相交了时间复杂度n,相当于遍历。

2、局部敏感哈希(不常用)

LSH的核心思想是: 假设两个向量比较相似(距离比较近),那么经过局部敏感hash之后,新空间的来年各个向量(哈希值)也会接近。

我们会指定一个基向量,聚类时计算每个向量和基向量的距离dist(a,b),并对距离进行分桶。查询时查询向量Q首先计算与基向量距离落在哪个分桶,然后遍历该分桶下的数据找到topk最近距离的向量。

缺点:

● 内用占用过大,存储原始的向量数据,不适合大规模向量检索。

● 准确率低,且不稳定:分桶w较大时每个分桶的数据少,导致召回率低;分桶数少时每个分桶数据量大,耗时增加,最坏情况一个分桶相当于整体遍历。而且又是topk向量分布在相邻分桶。

Multiprobe LSH改进:使用多个hash函数,类似于布隆过滤器,尽量随机;遍历时不止遍历命中的分桶也遍历相邻分桶。

大规模向量检索问题

问题1:数量大遍历时间长 -> 如何减小搜索空间:聚类,如上2种;

问题2:重内存轻CPU。 1亿个 256维的向量库,占用内存: 1^9 * 256 * 4 B(每个float 4字节) = 100G。一个大内存机器只能同时进行几个向量的检索,cpu远没打满 ->如何压缩向量,减小存储空间。

3、乘积量化 PQ

使用聚类ID来表达向量。训练阶段:对向量分段,每段分别进行kmeans聚类,每段用聚类ID代替,重新表示向量。假设向量维度D=64,设参数分段个数M=8,聚类类别数目K=256,那么每个向量被分成8段,每段取值(聚类ID)0-255。编码前后向量大小为64 * 4B -> 8 * 1B,降低了32倍。

查询时:将查询向量Q分成M段,每段分别和该段的所有聚类中心计算距离,得到K*M维的距离表,如左下角。

遍历样本库中的所有向量,根据距离表分别计算每段上与Q的距离D3,1/D2,2/D256,3...,计算距离和,返回Topk个距离最近的样本。

● 非对称距离计算:

距离计算方式有对称距离计算SDC和非对称距离计算ADC,q(x), q(y)是向量x,y编码后的向量,对称距离计算:离线计算出样本库中所有编码向量的距离表,实际计算x,y距离时直接查表即可,速度非常快但是放大了误差。非对称距离计算,使用x和编码后的y向量计算距离,增加了一些计算开销,但是误差更小更准确,通常采用。

IVF-PQ

PQ只是对向量进行量化编码,查询时仍然需要遍历所有样本向量计算距离,倒排的思路是聚类后用聚类中心和该类簇中的所有样本建立倒排拉链,查询时只在查询向量所在的类簇中遍历,相当于划分了子空间。

训练阶段:对所有样本进行粗粒度kmeans聚类,然后对每个样本以及对应的聚类中心建立倒排链,

对倒排链中的向量,先减去聚类中心然后进行PQ量化编码;

查询阶段:计算查询向量Q所对应的聚类中心C,计算残差Q-C并进行PQ量化,编码成短向量Q1。使用ADC计算Q1和倒排中所有向量的距离,筛选出Topk样本。

时间复杂度:

假设编码后维度为M维(M分段),样本总数N,聚类个数K

PQ时间复杂度 MN,IVF-PQ时间复杂度 MN/K

4、HNSW

NSW(Navigable Small World)全称"可导航小世界"。基于图构建索引,假设查找最近的m个点,训练阶段:构建图,从全量样本中取出一个向量q插入到图中,计算与q最近的m个点并与之相连,直到样本库中所有点插入到图中。查询阶段:从指定起始点A开始,从相邻点(未访问过的)中选择m个距离查询向量Q最近的点加入到结果集中,所有相邻点加入候选队列,从候选中选择距离Q最近的点B,继续选择它最近m个相邻点,如果新发现的相邻点距离比原有结果集的更小,替换结果集中的点,重复上述过程,直到候选集中点都被访问过。

HNSW使用一种层次化的图结构,类似于跳表的分层,最上层的节点最稀疏,越往下节点越稠密,检索时先从最高层的图层开始,快速定位到目标点的大致位置,转移到下一层对应点继续开始搜索,每往下一层都减小搜索范围,最终在最低层找到最近邻点。

5、算法优缺点:

IVF:基于倒排索引,使用聚类方法对聚类中心和类簇中的向量建立索引,查询时只在目标向量所在倒排链中检索,提高了检索速度。但是需要存储原始向量数据,内存空间占用大。

IVF-PQ:在IVF基础上倒排中存储量化编码后的向量,减小了内存占用,但是量化过程引入了误差,大大降低了召回率,对召回率要求低的场景可使用。

IVF-PQ-Refine:在IVF-PQ基础上在SSD上存储了未压缩的向量,首先通过IVF-PQ召回更大的候选集,然后从SSd上获取对应的原始向量计算距离,筛选Topk向量。

6、向量检索平台

目标:

基于faiss的索引增量更新功能,

向量索引分片功能,离线索引更新在线服务可感知

建库任务耗CPU中,使用专门建库集群,

相关推荐
祖坟冒青烟几秒前
Qt 的构建系统
c++
uyeonashi37 分钟前
【C++】刷题强训(day14)--乒乓球匡、组队竞赛、删除相邻数字的最大分数
开发语言·c++·算法·哈希算法
妈妈说名字太长显傻2 小时前
【C++】string类
开发语言·c++
丢丢丢丢丢丢~2 小时前
c++创建每日文件夹,放入每日日志
开发语言·c++
華華3552 小时前
读程序题...
开发语言·c++·算法
斯普信专业组2 小时前
Elasticsearch高性能实践
大数据·elasticsearch·搜索引擎
一行玩python3 小时前
Xerces-C,一个成熟的 C++ XML 解析库!
xml·c语言·开发语言·c++
Octopus20774 小时前
【C++】AVL树
开发语言·c++·笔记·学习
荒古前4 小时前
小发现,如何高级的顺序输出,逆序输出整数的每一位(栈,队列)
数据结构·c++·算法