最近邻搜索:Product Quantization for Nearest Neighbor Search

最近邻搜索在搜索领域是常用给的算法,拿我们的1:N的人脸识别举例,假如我们底库中有200百万照片的特征向量(这个数字已经算小的了),每个特征向量是512维,如果用线性搜索的话,那么我们要进行200*512百万次的加法,乘法。这个随着底库的增加,算法复杂度是逐渐增加的。在实际的应用场景中,显然这个是不可以的。很直观的一个想法就是,我们能不能类似于二分查找那样,每就算一次就排除一部分呢。第二个想法就是512维的特征向量能不能类似于pca那样,进行压缩降维呢?本篇文章为近似最近邻搜索提供了一种新方法:将高维数据量化划分为一些独立的低维子空间的Cartesian乘积,称之为PQ法。文章先形式化地描述了最近邻问题,并解释了对一个高维向量进行PQ,在内存使用量和Assignment复杂度上都比k-means优秀。然而在query时不能忍受遍历所有dataset的方式,提出coarse k-means划分成子集,再进行PQ法。最后作者将这种方法与HE、FLANN进行了比较,击败HE,和FLANN各有千秋。

向量量化(vector quantization)

在介绍PQ算法前,先简要介绍vector quantization。在信息论里,quantization是一个被充分研究的概念。Vector quantization定义了一个量化器quantizer,即一个映射函数q  ,它将一个D  维向量x   转换码本cookbook中的一个向量,这个码本的大小用k  表示。如果看到这里大家一定对这个概念感觉到一头雾水,简单说就是一个原始向量,我将其映射到一个新的向量,新的向量的维数和原始向量的维数一样。如果仅仅是这样的话,那我这个映射函数也没法定义啊,你总要给我一个目标函数吧,不然我怎么知道去映射啊。如果希望量化器达到最优,那么需要量化器满足Lloyd最优化条件。而这个最优量化器,恰巧就能对应到机器学习领域最常用的kmeans聚类算法。说白了就是量化后的向量和原始的向量的均方差最小,用论文中的公式表达如下:

PQ算法

有了vector quantization算法的铺垫,就好理解PQ算法。其实PQ算法可以理解为是对vector quantization做了一次分治,首先把原始的向量空间分解为m个低维向量空间的笛卡尔积,并对分解得到的低维向量空间分别做量化,那如何对低维向量空间做量化呢?恰巧又正是用kmeans算法。所以换句话描述就是,把原始D  维向量(比如D=128  )分成m  组(比如m=4  ),每组就是D ∗ =D/m  维的子向量(比如D∗ =D/m=128/4=32  ),各自用kmeans算法学习到一个码本,然后这些码本的笛卡尔积就是原始D  维向量对应的码本。用q j 表示第j 组子向量,用Cj 表示其对应学习到的码本,那么原始D  维向量对应的码本就是C =C1 ×C2 ×…×Cm   。用k∗表示子向量的聚类中心点数或者说码本大小,那么原始D维向量对应的聚类中心点数或者说码本大小就是k =(k∗) m   。可以看到m=1  或者m=D  是PQ算法的2种极端情况,对m=1  ,PQ算法就回退到vector quantization,对m=D  ,PQ算法相当于对原始向量的每一维都用kmeans算出码本。作者通过实验给出了最优的选择条件:

k∗ =256  和m=8

计算距离

上面的操作仅仅是相当于将原始的向量进行了聚类,通过分组的方式将原始的达到聚类降维的目的。在查询的时候,我怎么计算距离呢。论文中给出了两种计算距离的方式,首先计算查询向量和每一组聚类中心的距离,存储起来。这样后期再查找的时候通过查询就可以了。并且作者也证明了这样计算得出的距离是原始距离的一个近似。

计算流程

算法优化

上面的PQ算法只能达到将向量压缩的操作,但是在搜索的时候还是需要遍历所有的基向量,虽然计算每个向量的时候只是查表的操作,但是速度还没到达最优。是否可以借助倒排索引的方法呢,进一步的优化。所以作者就想出了二步法的优化方法。

这里借用了“分桶”的思路,先对所有原始数据做k-means,因为k值很低(实验中有10,000数据,256个centroids),所以称之为coarse k-means,然后在query时,multiple assignment到一些centroids,接着对残留(residual)再做PQ,流程如下图。

建立索引

1.coarse quantizer。 
对数据库中的所有特征采用K-means聚类,得到粗糙量化的类中心,比如聚类成1024类,并记录每个类的样本数和各个样本所属的类别。这个类中心的个数就是inverted list的个数。把所有类中心保存到一张表中,叫coarse_cluster表,表中每项是d维。

2.product quantizer 
计算y的余量,r(y)=y-q(y),用y减去y的粗糙量化的结果得到r(y)。r(y)维数与y一样,然后对所有r(y)的特征分成m组,采用乘积量化,每组内仍然使用k-means聚类,这时结果是一个m维数的向量,这就是上篇文章中提到的内容。把所有的乘积量化结果保存到一个表中,叫pq_centroids表,表中每项是m维。

3.append to inverted list 
前面的操作中记录下y在coarse_cluster表的索引i,在pq_centroids表中的索引j,那么插入inverted list时,把(id,j)插入到第i个倒排索引Li中,id是y的标识符,比如文件名。list的长度就是属于第i类的样本y的数目。

基于IVFADC的搜索

主要包括四个操作: 
1.粗糙量化 
对查询图像x的特征进行粗糙量化,即采用KNN方法将x分到某个类或某几个类,分到几个类的话叫做multiple assignment。过程同对数据集中的y分类差不多。 
2.计算余量 
计算x的余量r(x)。 
3.计算d(x,y) 
对r(x)分组,计算每组中r(x)的特征子集到pq_centroids的距离。根据ADC的技巧,计算x与y的距离可以用计算x与q(y)的距离,而q(y)就是pq_centroids表中的某项,因此已经得到了x到y的近似距离。 
3.最大堆排序 
堆中每个元素代表数据库中y与x的距离,堆顶元素的距离最大,只要是比堆顶元素小的元素,代替堆顶元素,调整堆,直到判断完所有的y。

算法和人脸识别结合

可以将pq算法应用到我们的项目中,首先利用pq算法选出topk的备选集,然后再备选集中计算准确的距离,找出最接近的。

 

下面的链接是我关于常用的搜索算法,主要包含三类 基于hash的方法,基于内积向量化,基于图的方法

https://download.csdn.net/download/horizonheart/10920746

 

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值