來源:http://my.oschina.net/pathenon/blog/65210
1.概述
跟SimHash一樣,MinHash也是
LSH的一種,可以用來快速估算兩個集合的相似度。MinHash由Andrei Broder提出,最初用於在搜索引擎中檢測重復網頁。它也可以應用於大規模聚類問題。
2.Jaccard index
在介紹MinHash之前,我們先介紹下Jaccard index。
也就是說,集合A,B的Jaccard系數等於A,B中共同擁有的元素數與A,B總共擁有的元素數的比例。很顯然,Jaccard系數值區間為[0,1]。
3.MinHash
先定義幾個符號術語:
h(x): 把x映射成一個整數的哈希函數。
h
min(S):集合S中的元素經過h(x)哈希后,具有最小哈希值的元素。
那么對集合A、B,hmin(A) = hmin(B)成立的條件是A ∪ B 中具有最小哈希值的元素也在 ∩ B中。這里
有一個假設,h(x)是一個良好的哈希函數,它具有很好的均勻性,能夠把不同元素映射成不同的整數。
所以有,Pr[hmin(A) = hmin(B)] = J(A,B),即集合A和B的相似度為集合A、B經過hash后最小哈希值相
等的概率。
有了上面的結論,我們便可以根據MinHash來計算兩個集合的相似度了。一般有兩種方法:
第一種:使用多個hash函數
為了計算集合A、B具有最小哈希值的概率,我們可以選擇一定數量的hash函數,比如K個。然后用這K個hash函數分別對集合A、B求哈希值,對
每個集合都得到K個最小值。比如Min(A)k={a1,a2,...,ak},Min(B)k={b1,b2,...,bk}。
那么,集合A、B的相似度為|Min(A)k ∩ Min(B)k| / |Min(A)k ∪ Min(B)k|,及Min(A)k和Min(B)k中相同元素個數與總的元素個數的比例。
第二種:使用單個hash函數
第一種方法有一個很明顯的缺陷,那就是計算復雜度高。使用單個hash函數是怎么解決這個問題的呢?請看:
前面我們定義過 h
min(S)為集合S中具有最小哈希值的一個元素,那么我們也可以定義h
mink(S)為集合S中具有最小哈希值的K個元素。這樣一來,
我們就只需要對每個集合求一次哈希,然后取最小的K個元素。計算兩個集合A、B的相似度,就是集合A中最小的K個元素與集合B中最小的K個元素
的交集個數與並集個數的比例。
看完上面的,你應該大概清楚MinHash是怎么回事了。但是,MinHash的好處到底在哪里呢?計算兩篇文檔的相似度,就直接統計相同的詞數和總的
次數,然后就Jaccard index不就可以了嗎?對,如果僅僅對兩篇文檔計算相似度而言,MinHash沒有什么優勢,反而把問題復雜化了。但是如果有海量的文檔需要求相似度,比如在推薦系統
中計算物品的相似度,如果兩兩計算相似度,計算量過於龐大。下面我們看看MinHash是怎么解決問題的。
比如 元素集合{a,b,c,d,e},其中s1={a,d},s2={c},s3={b,d,e},s4={a,c,d} 那么這四個集合的矩陣表示為:
如果要對某一個集合做MinHash,則可以從上面矩陣的任意一個行排列中選取一個,然后MinHash值是排列中第一個1的行號。
例如,對上述矩陣,我們選取排列 beadc,那么對應的矩陣為
那么, h(S1) = a,同樣可以得到h(S2) = c, h(S3) = b, h(S4) = a。
如果只對其中一個行排列做MinHash,不用說,計算相似度當然是不可靠的。因此,我們要選擇多個行排列來計算MinHash,最后根據Jaccard index公式 來計算相似度。但是求排列本身的復雜度比較高,特別是針對很大的矩陣來說。因此,我們可以設計一個隨機哈希函數去模擬排列,能夠把行號0~n隨機映射到0~n上。比如H(0)=100,H(1)=3...。當然,沖突是不可避免的,沖突后可以二次散列。並且如果選取的隨機哈希函數夠均勻,並且當n較大時,沖突發生的概率還是比較低的。
說到這里,只是討論了用MinHash對海量文檔求相似度的具體過程,但是它到底是怎么減少復雜度的呢?
比如有n個文檔,每個文檔的維度為m,我們可以選取其中k個排列求MinHash,由於每個對每個排列而言,MinHash把一篇文檔映射成一個整數,所以對k個排列計算MinHash就得到k個整數。那么所求的MinHash矩陣為n*k維,而原矩陣為n*m維。n>>m時,計算量就降了下來。
4.參考文獻