from:https://www.cnblogs.com/maybe2030/p/4953039.html
局部敏感哈希(Locality Sensitive Hashing,LSH)算法是我在前一段時間找工作時接觸到的一種衡量文本相似度的算法。局部敏感哈希是近似最近鄰搜索算法中最流行的一種,它有堅實的理論依據並且在高維數據空間中表現優異。它的主要作用就是從海量的數據中挖掘出相似的數據,可以具體應用到文本相似度檢測、網頁搜索等領域。
1. 基本思想
局部敏感哈希的基本思想類似於一種空間域轉換思想,LSH算法基於一個假設,如果兩個文本在原有的數據空間是相似的,那么分別經過哈希函數轉換以后的它們也具有很高的相似度;相反,如果它們本身是不相似的,那么經過轉換后它們應仍不具有相似性。
哈希函數,大家一定都很熟悉,那么什么樣的哈希函數可以具有上述的功能呢,可以保持數據轉化前后的相似性?當然,答案就是局部敏感哈希。
2. 局部敏感哈希LSH
局部敏感哈希的最大特點就在於保持數據的相似性,我們通過一個反例來具體介紹一下。
假設一個哈希函數為Hash(x) = x%8,那么我們現在有三個數據分別為255、257和1023,我們知道255和257本身在數值上具有很小的差距,也就是說它們在三者中比較相似。我們將上述的三個數據通過Hash函數轉換:
Hash(255) = 255%8 = 7;
Hash(257) = 257%8 = 1;
Hash(1023) = 1023%8 = 7;
我們通過上述的轉換結果可以看出,本身很相似的255和257在轉換以后變得差距很大,而在數值上差很多的255和1023卻對應相同的轉換結果。從這個例子我們可以看出,上述的Hash函數從數值相似度角度來看,它不是一個局部敏感哈希,因為經過它轉換后的數據的相似性喪失了。
我們說局部敏感哈希要求能夠保持數據的相似性,那么很多人懷疑這樣的哈希函數是否真的存在。我們這樣去思考這樣一個極端的條件,假設一個局部敏感哈希函數具有10個不同的輸出值,而現在我們具有11個完全沒有相似度的數據,那么它們經過這個哈希函數必然至少存在兩個不相似的數據變為了相似數據。從這個假設中,我們應該意識到局部敏感哈希是相對的,而且我們所說的保持數據的相似度不是說保持100%的相似度,而是保持最大可能的相似度。
對於局部敏感哈希“保持最大可能的相似度”的這一點,我們也可以從數據降維的角度去考慮。數據對應的維度越高,信息量也就越大,相反,如果數據進行了降維,那么毫無疑問數據所反映的信息必然會有損失。哈希函數從本質上來看就是一直在扮演數據降維的角色。
3. 文檔相似度計算
我們通過利用LSH來實現文檔的相似度計算這個實例來介紹一下LSH的具體用法。
3.1 Shingling
假設現在有4個網頁,我們將它們分別進行Shingling(將待查詢的字符串集進行映射,映射到一個集合里,如字符串“abcdeeee", 映射到集合”(a,b,c,d,e)", 注意集合中元素是無重復的,這一步驟就叫做Shingling, 意即構建文檔中的短字符串集合,即shingle集合。),得到如下的特征矩陣:
其中“1”代表對應位置的Shingles在文檔中出現過,“0”則代表沒有出現過。
在衡量文檔的相似度中,我們有很多的方法去完成,比如利用歐式距離、編輯距離、余弦距離、Jaccard距離等來進行相似度的度量。在這里我們運用Jaccard相似度。接下來我們就要去找一種哈希函數,使得在hash后盡量還能保持這些文檔之間的Jaccard相似度,即:
我們的目標就是找到這樣一種哈希函數,如果原來文檔的Jaccard相似度高,那么它們的hash值相同的概率高,如果原來文檔的Jaccard相似度低,那么它們的hash值不相同的概率高,我們稱之為Min-hashing(最小哈希)。
3.2 Min-hashing
Min-hashing定義為:特征矩陣按行進行一個隨機的排列后,第一個列值為1的行的行號。舉例說明如下,假設之前的特征矩陣按行進行的一個隨機排列如下:
元素 |
S1 |
S2 |
S3 |
S4 |
他 |
0 |
0 |
1 |
0 |
成功 |
0 |
0 |
1 |
1 |
我 |
1 |
0 |
0 |
0 |
減肥 |
1 |
0 |
1 |
1 |
要 |
0 |
1 |
0 |
1 |
最小哈希值:h(S1)=3,h(S2)=5,h(S3)=1,h(S4)=2.
為什么定義最小hash?事實上,兩列的最小hash值就是這兩列的Jaccard相似度的一個估計,換句話說,兩列最小hash值同等的概率與其相似度相等,即P(h(Si)=h(Sj)) = sim(Si,Sj)。為什么會相等?我們考慮Si和Sj這兩列,它們所在的行的所有可能結果可以分成如下三類:
(1)A類:兩列的值都為1;
(2)B類:其中一列的值為0,另一列的值為1;
(3)C類:兩列的值都為0.
特征矩陣相當稀疏,導致大部分的行都屬於C類,但只有A、B類行的決定sim(Si,Sj),假定A類行有a個,B類行有b個,那么sim(si,sj)=a/(a+b)。現在我們只需要證明對矩陣行進行隨機排列,兩個的最小hash值相等的概率P(h(Si)=h(Sj))=a/(a+b),如果我們把C類行都刪掉,那么第一行不是A類行就是B類行,如果第一行是A類行那么h(Si)=h(Sj),因此P(h(Si)=h(Sj))=P(刪掉C類行后,第一行為A類)=A類行的數目/所有行的數目=a/(a+b),這就是最小hash的神奇之處。
Min-hashing的具體做法可以根據如下進行表述:
返回到我們的實例,我們首先生成一堆隨機置換,把特征矩陣的每一行進行置換,然后hash function就定義為把一個列C hash成一個這樣的值:就是在置換后的列C上,第一個值為1的行的行號。如下圖所示:

