最近鄰搜索之乘積量化(Product Quantizer)


===================================================
http://blog.csdn.net/CHIERYU/article/details/50321473
===================================================

簡介

Product Quantizer是由Herv´e J´egou等人2011年在IEEEE上發表的論文《Product Quantization for Nearest Neighbor Search》中提出來的。它的提出是爲了在內存和效率之間求得一個平衡,既保證圖像索引結構需要的內存足夠,又使得檢索質量和速度比較好。對於任何基於固定維數特徵的事物,它可以應用到其索引結構的建立及檢索上。它屬於ANN(approximate nearest neighbor)算法。與它相關的算法有E2LSH(Euclidean Locality-Sensitive Hashing), KD-trees,K-means。

主要思想

Product Quantizer翻譯過來是乘積量化,從字面理解大概包括了兩個過程特徵的分組量化過程和類別的笛卡爾積過程。假設有一個數據集,那麼K-means的做法就是給定類別數目K,目標函數是所有樣本到類中心的距離和最小,迭代計算優化目標函數,得到K個類中心和每個樣本所屬的類別。目標函數不變,乘積量化的做法是:
(1)數據集爲K個類別,每個樣本以一個vector的形式表示,維數爲d,將vector的各個分量分成m組。
(2)將所有vector的某組分量作爲數據集,採用k-means算法得到這裏寫圖片描述個類中心,運行m次k-means算法,則每組都有這裏寫圖片描述個類中心,記這這裏寫圖片描述個類中心爲一個集合。
(3)將上述得到的m個集合做笛卡爾積,就得到整個數據集的類中心了。

下圖輔助理解。
這裏寫圖片描述
其實只要聯繫歐式空間中點的笛卡爾積就很好理解了。

舉個栗子

這裏寫圖片描述

注:例子中示意圖引用自Jae-Pil Heo的論文《Distance Encoded Product Quantization》


=================================================================================

from:  http://blog.csdn.net/swartz2015/article/details/50859666

=================================================================================

圖像搜索首先需要提取圖像的特徵信息。由於全局信息具有不穩定性和敏感性,魯棒性較差。所以現在一般都提取圖像的局部信息,如SIFT,SUFT等。這樣,一副圖像就可以用許多特徵點組成。每個特徵點用一個向量表示,對於SIFT,SUFT,這個向量是128維的。在提取出特徵向量之後。因爲一般每幅圖像都可以提取幾百上千個特徵點,爲了方便圖像匹配,一般還需要將這些特徵向量聚合成一個向量,方便比較。當然,也不是所有的算法都需要將特徵向量進行聚合。

      

       因此可以看到圖像匹配的本質就是比較向量的相似程度。現在主要是通過比較向量的歐式距離來比較他們的相似程度。比較過程就是對於一個輸入向量,在數據庫中找到與其在歐式空間上距離最近的向量。因此,樸素的算法是對數據庫中的特徵向量進行遍歷。因爲要找到最鄰近的匹配值,起碼都要把所有的向量比較一遍。但有兩個問題,一個是數據庫中一般含有的特徵向量數目非常多,起碼都是千萬級別的。因此遍歷一遍會花很多時間;其次,計算向量之間的歐氏距離也是一個花銷非常大的過程。

      爲了解決最鄰近算法的這些問題,現在提出了近似最鄰近算法(approximate nearest neighbor-ANN)。ANN算法目的不是尋找最鄰近向量,而是近似最鄰近向量。

     ANN算法的核心思想是先建立codebook,,然後將特徵向量量化到code word上。最後通過比較對應的code word的距離即可。可以認爲被量化到同一個code word上的特徵是近似最鄰近的。因此前面的距離算法到這裏就編程了量化算法。但是量化算法也有一些缺點,就是存在量化誤差-可能會把歐式空間中相鄰的特徵量化到不同的code word上。畢竟量化過程會丟失特徵向量的某些特徵。爲了彌補這些誤差,各種算法都提出了一些優化措施。

     本文主要是介紹量化算法中的一種叫做product quantization。目前有許多很有名的ANN算法,product quantization是其中比較好的算法。相關詳細信息可以參考論文:Jegou, Herve, Matthijs Douze, and Cordelia Schmid. "Product quantization for nearest neighbor search." Pattern Analysis and Machine Intelligence, IEEE Transactions on 33.1 (2011): 117-128


      1.背景知識

    首先介紹一下向量量化的一些背景知識。向量量化的目標是爲了減少空間結構的複雜度。因爲經過量化,任何空間中的點都可以用有限的幾個code word來表示。假設存在量化函數q,和詞彙 C,則對於空間中的任何一個向量x都有

     


      其中i=1,2,...,k。即codebook中code word的數目。

      所以一個code word中所包含的特徵向量集合(vi)可以用下式表示

                                                                         

     因此量化過程直觀上的理解就是對特徵空間進行分割。爲了對量化進行評價,我們引入均方誤差(Mean Squared Error):

                                                        

     式中的p(X)表示X的分佈函數。因此對於特定的x,p(x)表示X落在該點的概率。

       可以看到MSE(q)是通過計算空間中所有點到其量化點的距離的期望值對量化函數q進行評價。可以很直觀地看出,對於所有的q,MSE(q)的值越小,說明此量化函數的量化誤差越小,量化效果越好。

       既然量化函數是可以進行量化評價的,那麼肯定就存在一個量化函數,對於一些特定的點可以訓練得到最小的MSE。亦即存在最優的量化函數。下面利用Lloyd optimality conditions定義量化函數的最優化條件。

                                                                        

                                                                                    

         式一是對量化函數的描述,表示向量x一定要量化到離他最近的code word上面。

         式二是對code word的定義。可以看出這是一個需要反覆修正的訓練過程。

         可以把滿足以上兩個最優化條件的量化算法稱爲Lloyd 量化器。我們熟知的k-means算法就是一個Lloyd量化器。它是一個接近最優化的量化算法,難怪如此深入人心。

         爲了後面的討論,再定義均方失真函數

                                                                    

       式子中,pi(x)表示x被量化到ci上面的概率分佈。


       2.Product Quantizer


       本節詳細介紹product  quantization。

          product  quantization是一種常用的編碼方法。它允許將一個向量的各個部分進行分開量化。

                                                                                                            


          如圖,將一個向量分成m等份進行分開量化。這樣,每個量化函數都相對簡單,因爲它只需要處理維數比較少的子向量即可。算法還分別爲每個子量化器分配了一個codebook,假設爲量化器qi,分配的codebook是ci。則原向量最終的量化空間將是這些codebook的笛卡爾乘積

                                                                                 

        假設每個子量化器都有k*個code word,則對於原向量,可選的codeword一共有

                                                                                           

        product quantization的優勢在於,通過對將較小的幾個code book連接形成一個規模足夠大的codebook。而且對於小的codebook,訓練複雜度相對直接訓練大的codebook是低的多的。所以根據這個原理,直接存儲C個codebook是沒必要的,且相反會降低最終的量化速率。因此在存儲的時候,我們採用的是分別存儲m個大小爲k*的codebook的方式。

        所以剩下的問題就是如何確定參數k* 和 m了。k*和m是通過MSE函數爲指標確定的,MSE函數值越小越好。因爲現在量化是分步進行,最後再將量化結果整合,因此需要重新定義MSE函數

                                                                       

      下圖是論文中描繪的MSE函數值與(k*,m)的函數關係圖

                                              

       其中code length可由m,k*計算得到 :codelength = m*log2(k*)。

         通過圖可以看出,對於一個 codelength,m越小,k*越大,則MSE的值會越小。比如當m=1時,算法就進化爲滿足最優化條件的k-means算法。只是由於k-means算法對高維複雜度比較高,因此不予以考慮。所以m和k*的選取是一個trade off的問題。


       3.利用product quantization進行檢索

       正如前面說的一樣,檢索本質上是一個比較歐式距離的問題。因此現在主要看看如何通過量化後的code word 對向量進行efficient的比較。

                                        

       如圖所示,計算待查詢向量和數據庫中的向量的距離有兩種方法。一種是,先將待查詢向量進行量化,然後計算對應的量化子和數據庫中的量化子的距離(SDC);另一種是不需要對待查詢向量進行量化,而直接計算它和數據庫中的量化子的距離(ADC)。兩種方法可分別用下面兩個式子說明

                                                     

                                                      

      可以看到SDC相對於ADC,只有一個優點,就是不需要在內存中存儲query vector,因爲它已經被量化到codeword上了,直接用這個code word表示它就可以,而code code本省是存在內存中的。所以下面只考慮ADC算法。

        但是需要注意的是,這裏進行距離計算時還是需要遍歷數據庫中的m*(k*)個code book的。只是相對來說,這個值要小的多。下面着重分析一下ADC算法的距離誤差。(PS:這個分析方法具有普遍性,並不是只適合於分析product  quantizer)      

      4.誤差分析

      首先定義平均距離方差指標(Mean Squared Distance Error) - MSDE

                                                     

       根據三角不等式

                                                  

       於是有

                                                                 

       因此由MSDE函數定義可得到下面的不等式

                                                      

       式中的MSE(q)是前面已定義的。

         由以上不等式表明,我們的量化方法誤差上界是MSE(q),而我們的quantizer是用k-means算法進行學習的,因此可以保證MSE(q)滿足進行雖有條件。這樣,我們的最終算法的誤差控制是比較好的。

         但是不管怎麼樣,用量化值進行距離計算總是免不了偏差的。如下圖,分別比較了實際的距離和ADC,SDC的距離之間的函數關係

                                           

      可以看到整體來說,量化距離和實際距離是呈正相關關係的,但是誤差也是不可避免的。同時也可以看到,量化距離一般比實際距離的值要偏小一些,並且SDC算法的偏差相對ADC的偏差更大。原論文對偏差做了一定的修正。在這裏就不贅述了。因爲在實際應用中,可以不進行校正。不過從上圖也可以看出用ADC算法會更加好一些。下面我們直接看一下檢索過程。

                                         

       爲了快速檢索,不例外地這裏用到了倒排索引結構(inverted index)。上圖可以進行說明,在實際檢索中分兩個步驟:1.用數據庫中特徵建立索引結構(圖的上部分); 2.對輸入的待檢測特徵進行檢索(圖的下部分)。從圖中可以看到。在建立索引時,先用k-means算法對數據庫特徵進行粗量化,得到K'個索引項;粗量化之後,由於會存在較大的量化誤差。爲了保存這個信息,這裏計算query vector和粗量化的code word之間的residual vecto-r。這裏的residual vector就是將使用本文所講的product quantization 算法進行量化,最後將量化後得到的quantiza-tion code 存儲在該索引項對應的列表項中,同時列表項中還存儲中圖片的identifier。這樣一個向量y就可以用下面的向量近似:

                                                                   

     因此d(x,y)可以用下面的近似算法進行計算:

                                                     

     將計算任務分配到product quantization的各個subquantizers中可得到下式

                                                   

      需要注意的是,x項是粗量化的code word,因此是precomputed,因此該式子第一部分是可以離線計算的。不過這裏得存儲粗量化所有的code word的sub vector到所有的product quantization的code word 的距離,也是非常耗內存的。爲了減少量化誤差,論文中還應用了multiple assignment的方法,就是將一個特徵映射到多個索引上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章