一文盡覽近似最近鄰搜尋中的雜湊與量化方法

微軟研究院AI頭條發表於2019-01-11

編者按:最近鄰搜尋演算法能夠幫助人們在海量資料中快速搜尋到有效內容,但是想要將其應用於實際,則需要解決如何縮短搜尋時間的問題。本文將為大家介紹兩種減少搜尋時間的方法。基於雜湊的近似最近鄰搜尋的方法通過設計和優化雜湊函式,減少計算的次數,從而縮短搜尋時間。基於量化的近似最近鄰搜尋方法則通過聚類把向量集聚成若干類,每類裡面的向量用對應的類中心來近似。

我們每個人每天都在享受各種線上服務(在線搜尋、新聞推薦等)所帶來的種種便利。這些服務的背後隱藏著龐大的、需要計算機實時處理的資料。例如,在影象搜尋領域,面對給定的一幅查詢影象,系統要從龐大的資料庫裡(比如包含百萬、千萬甚至上億影象)快速找出相似的影象;而在新聞推薦中,計算機也需要根據使用者畫像,從大量的新聞中找到最相關的新聞推薦給使用者。

想要從海量資料中快速找到有效資料離不開最近鄰搜尋演算法最近鄰搜尋計算機視覺機器學習、多媒體搜尋、計算幾何等領域裡非常基礎、也是非常重要的問題。

我們先看看最近鄰搜尋的定義。給定一個查詢目標q,最近鄰搜尋的目的是從一個龐大的參考(搜尋)集合X=\{x_1,x_2,…,x_N\}裡面,找到距離q最近的目標:

一文盡覽近似最近鄰搜尋中的雜湊與量化方法

這裡面,集合元素x和查詢目標q可以是向量、集合或者其它形式,dist(.,.)是相應的距離。在文字相關的應用裡,距離的定義基於Jaccard相似度:sim(A,B)=(A∩B)/(A∪B);在計算機視覺、多媒體、機器學習及計算幾何等領域裡,研究及使用最為廣泛的是歐氏距離度量:dist(x,q)=\|x-q\|_2,這一類問題是本文關注的重點。除此以外,基於內積相似度sim(x,q)=q^⊤ v的最近鄰搜尋也有不少研究。

假設向量的維數是d,搜尋集裡含有N個向量,那麼線性掃描整個搜尋集的時間複雜度是O(dN)。在搜尋集小的情況下,計算量還能接受。但是在實際應用裡面,搜尋集通常非常大,搜尋時間非常長,像kd-tree等一些優化方法並沒有提高高維空間裡的搜尋效率,效率甚至比線性掃描還要低,導致準確最近鄰搜尋難以直接用於實際問題。所以,近似最近鄰搜尋在研究和應用領域都受到廣泛的關注。顧名思義,近似最近鄰搜尋找到的向量不要求一定是準確的最近鄰,只要求距離準確的最近鄰很近就可以了。

目前,近似最近鄰縮短搜尋時間有兩類基本方案:第一類是縮短距離計算的時間時間複雜度變為O(d'N),例如將維數d從1000降到10,搜尋時間縮短到1/100;第二類是減少距離計算的次數時間複雜度變為O(dN’),例如將計算次數從1,000,000到1000,搜尋時間縮短到1/1000。本文主要介紹第一類方案。

縮短距離計算時間的方法主要分為兩種:第一種是雜湊或者二值編碼的方法;第二種是量化的方法。

基於雜湊的近似最近鄰搜尋的方法

雜湊的方法是通過雜湊函式把向量x變換成二值碼(海明碼)b(例如0101110101011100),然後將距離dist(x_1,x_2)近似成二值碼距離(海明距離)dist(b_1,b_2)。二值碼距離可以通過popcount快速計算。這個方向的研究主要集中在雜湊函式的設計及其優化,下面介紹幾種典型的雜湊方法。

雜湊方法起源於Piotr Indyk等人提出的Locality-Sensitive Hashing(LSH)方法,即用隨機投影的方法,把向量變成二值碼。如果要生成32位二值碼,LSH隨機產生32個投影向量,\{w_1,w_2,…,w_32\},每個投影向量生成一個二值碼,相應的雜湊函式可以選為:b_k = δ[w_k^⊤ x ≥ 0]。最初LSH用於倒排表的方法來快速搜尋最近鄰,後來更多地用來產生隨機二值碼來近似距離,被認為二值碼方法的基線演算法。

但是,由於隨機二值碼方法沒有利用搜尋集裡的資料來建立雜湊函式,所以搜尋效果不夠理想。後來有大量的研究集中在利用搜尋集學習更好的雜湊函式,其中,Yair Weiss等人在NIPS 2008上提出的譜雜湊方法(Spectral Hashing)是較早的工作之一,這種方法的出發點是希望海明距離大的兩個資料點在原空間裡的相似度要小,目標函式為最小化海明距離和原空間相似度的乘積,最後轉化為解特徵值或特徵函式的問題。Brian Kulis等人提出的二值化重建嵌入(Binary Reconstructive Embedding)方法的目標是最小化距離重建誤差,就是希望海明距離與原空間裡的歐氏距離儘量接近。後續的工作還包括Jun Wang等人提出的Semi-Supervised Hashing,以及Wei Liu等人提出的Hashing with Graphs等。

搜尋問題可以看成排序問題:距離查詢點近的向量排在前面,遠的向量排在後面。從這個出發,有些工作設計了保序的目標函式,使得根據在二值空間的序跟原空間裡的序儘量一致。Mohammad Norouzi等人提出的三元組損失函式是一種最簡單的保序函式:如果一個點q與點p_1的距離比q到p_2點的距離小,那麼在二值空間裡,點q和點p_1相應的海明距離比q和p_2的海明距離也要小。也有些工作設計更高階的保序目標函式,比如Jianfeng Wang等人提出的order-preserving hashing。

不同於保相似度、保距離或者保序,Yunchao Gong等人提出的迭代量化的方法(Iterative Quantization,ITQ)的出發點是把二值編碼當成原向量的近似,利用歐氏距離旋轉不變性的性質,建立了最小化二值編碼重建旋轉原向量誤差的目標函式,尋找最優的旋轉變換和二值編碼。儘管直觀看上去重建向量的方法比保相似、保距離或者保序的方法簡單,近似得更強,但ITQ實際效果還是很不錯,原因是保相似、保距離或者保序需要建立二元或者多元關係,計算複雜度很大,從而需要各種近似,使得最後的效果不如預期。

一文盡覽近似最近鄰搜尋中的雜湊與量化方法圖1: 雜湊和量化對比的二維案例。左:量化的距離更加豐富;右:量化需要的位元數目少

基於量化的近似最近鄰搜尋方法

一文盡覽近似最近鄰搜尋中的雜湊與量化方法

圖2: 比較乘積量化、優化的乘積量化以及合成量化的二維案例。左:乘積量化;中:優化的乘積量化;右:合成量化。

向量量化是通過聚類把向量集聚成若干類,每類裡面的向量用對應的類中心來近似。這樣子,每個向量只需要用其對應的聚類中心的索引ID來表示,其與查詢向量間的距離用其對應的聚類中心與查詢向量間的距離來近似。向量量化帶來了兩項優勢:

(1)向量需要的儲存空間變少了,只需儲存對應的聚類中心的ID;

(2)計算時間減少了,只需要通過聚類中心的索引ID來查詢預先計算好的聚類中心與查詢向量的距離表格。

然而,直接用k-means演算法並不能帶來明顯的效果:如果聚類中心數目太少,向量近似效果不佳;而如果聚類中心數目太多,距離表格計算時間又太長。因此,研究人員利用Cartesian量化用來解決此問題。Cartesian量化的聚類中心C是建立在幾個小的聚類中心集合\{C_1,C_2,…,C_P\}的基礎上:C=C_1×C_2×…×C_P\\,其好處在於通過幾個小的聚類中心集合,可以得到非常多的聚類中心,甚至多於搜尋的向量集合大小,從而向量近似效果可以得到保證。進一步通過引進一些限制或者策略來保證距離計算可以通過快速查詢距離表格來實現,以降低計算時間。下面介紹三種主要的方法。

乘積量化

乘積量化(Product Quantization)把向量分成若干個子向量,然後對每個子向量集合分別聚類。具體來講,向量x分成子向量\{x_1,x_2,…,x_P\}: x=[x_1^⊤ x_2^⊤…x_P^⊤ ]^⊤。然後對每個子向量的集合\{x_p1,x_p2,…,x_pN\}進行聚類, 得到K(為了方便,每個集合都生成相同數量的聚類中心)個聚類中心:C_p =\{c_p1,c_p2,…,c_pK \}。最終,乘積量化得到K^P聚類中心\{[c_(1k_1)^⊤,c_(2k_2)^⊤,…,c_(Pk_P)^⊤ ]^⊤;k_1∈\{0,1,…,K\},k_2∈\{0,1,…,K\},…,k_P=\{0,1,…,K\}\}。在最近鄰搜尋中,乘積量化每個向量x由其P個子向量對應的聚類中心的ID來表達:(k_1,k_2,…,k_P)。查詢向量q與參考向量x距離有對稱和非對稱兩種近似方法。

對稱的方法:線下計算P個大小K×K的距離表格,每個表格D_p儲存對應的聚類中心兩兩之間的距離D_p (i,j)= dist(c_pi,c_pj)。查詢向量分成P個子向量,每個子向量找到對應的聚類中心,查詢向量由聚類中心的ID來表示:((k_1) ̃,(k_2) ̃,…,(k_P) ̃)。這樣子,距離近似為dist(p,x)≈∑_(p=1)^P D_p ((k_p) ̃,k_p)。

非對稱的方法:線上預先計算一個大小P×K距離表格,把查詢向量q分成P個子向量,q_1,q_2,…,q_P,然後計算這P個子向量與P組聚類中心的距離,D(p,j)=dist(q_p,c_pj)。這樣,距離近似為dist(p,x)≈∑_(p=1)^P D(p,k_p)。很顯然,後者距離近似的更為準確,但是需要額外距離表格的計算,在搜尋資料庫非常大的情況下,額外距離表格計算的時間可以忽略不計。

乘積量化需要把向量分成P個子向量,由於各個子向量的分佈的不一樣,每個子向量的量化效能不平衡,會導致距離近似不夠理想。由Mohammad Norouzi等人提出的Cartesian k-means方法以及由Tiezheng Ge等人提出的優化的乘積量化方法首先旋轉向量,然後在旋轉後的空間裡進行乘積量化。這裡面旋轉的目的是旋轉後的每個子向量的量化效能儘量平衡。旋轉具有不改變歐氏距離的性質,這是可以把旋轉引進來的原因。

合成量化

合成量化(Composite Quantization)的基本思想是用P個同樣維度的向量\{c_(1k_1), c_(2k_2), …, c_(Pk_P)\}的和來近似向量x:x≈x ̅=∑_(p=1)^P c_(pk_p),其中,c_(pk_p)來自於第p個字典\{c_p1,c_p2,…,c_pK\}。相應的,每個向量x由P個向量的ID來表達:(k_1,k_2,…,k_P)。其帶來的好處是向量近似誤差更小。但是,需要重建向量,然後算距離,因此距離計算複雜度很大。合成量化根據下面的距離計算展開形式來設計加快距離計算的方法:

一文盡覽近似最近鄰搜尋中的雜湊與量化方法

上面的等式右邊:第二項只決定於查詢向量q,對某個具體的查詢向量,這一項不影響距離排序;第一項,由查詢向量和字典的元素的距離構成,接受到一個查詢向量時,可以預先計算查詢向量與每個字典裡的每個元素之間的距離形成距離表格,然後查詢向量與搜尋資料庫裡的每個向量的距離,可以通過查錶快速地找到P個距離,然後求和得到,這部分的距離計算複雜度為O(P),通常P會遠小於向量的維度d,所以這部分計算速度提高了;第三項,

一文盡覽近似最近鄰搜尋中的雜湊與量化方法

也可以通過查表的方法做,但是計算複雜度依然很大,所以近正交合成量化在優化字典的時候引進一限制條件,讓這一項變成常數ε,從而這一項可以不用計算了。所以近正交的合成量化的優化目標是最小化量化誤差,同時加入常數項限制:

一文盡覽近似最近鄰搜尋中的雜湊與量化方法

合成量化從理論的角度分析得出:加入這個限制條件,實際上是在最小化量化誤差和距離計算時間之和的上界。同時也指出了,乘積量化及其變種是合成量化的特例,從而合成量化的結果更好些。

合成量化一文,提出了近正交的合成量化的一種變體:對第三項用一個位元組進行編碼,減少字典的數量,比如用P-1個字典(每個字典包含256個元素,可以一個位元組編碼每個元素),實驗發現在字典數目較多的情況下,這個變體的效能跟近正交合成量化結果差不多,位元組數目較少的情況下,效能差些。

瞭解合成量化的更多內容,請查閱:

加和量化

類似合成量化的方法,Artem Babenko等人提出的加和量化(Additive Quantization)從下面的距離展開形式來實現距離的快速計算:

一文盡覽近似最近鄰搜尋中的雜湊與量化方法

等式右邊第一項只跟查詢向量有關,不用計算;第二項可以通過查錶快速計算;第三項用1個位元組來近似。但是實驗顯示,加和量化的結果比合成量化略差。

我們在合成量化一文中也考慮到下面的歐氏距離轉化成內積的形式,

一文盡覽近似最近鄰搜尋中的雜湊與量化方法

合成量化或者加和量化可以用來量化一文盡覽近似最近鄰搜尋中的雜湊與量化方法,然後計算複雜度可以降到O(P)。但是,直接這樣做的效果並不理想,原因在於,向量x和其模的取值範圍不一樣,導致量化效能不是很理想。

為了更好地推動基於雜湊與量化的近似最近鄰搜尋這一方面的工作,我們在A Survey on Learning to Hash一文中梳理了該領域在2017年以前的工作,並把tex原始碼放在了https://github.com/welleast/Learning2Hash,邀請大家一起進一步完善該綜述,特別是新增基於深度學習的雜湊和量化方面的工作,有感興趣的研究人員也可以通過留言跟我聯絡。

Jingdong Wang, Ting Zhang, Jingkuan Song, Nicu Sebe, Heng Tao Shen. A Survey on Learning to Hash. IEEE Trans. Pattern Anal. Mach. Intell. 40(4): 769-790 (2018).

https://arxiv.org/pdf/1606.00185.pdf

另外,我們在GitHub上開源了基於近鄰圖的最近鄰搜尋演算法,希望可以共同推動相關領域的發展。

GitHub主頁:https://github.com/Microsoft/SPTAG

瞭解更多基於近鄰圖的最近鄰搜尋演算法,請查閱:

相關文章