1. 程式人生 > >海量資料去重之SimHash演算法簡介和應用

海量資料去重之SimHash演算法簡介和應用

SimHash是什麼

SimHash是Google在2007年發表的論文《Detecting Near-Duplicates for Web Crawling 》中提到的一種指紋生成演算法或者叫指紋提取演算法,被Google廣泛應用在億級的網頁去重的Job中,作為locality sensitive hash(區域性敏感雜湊)的一種,其主要思想是降維,什麼是降維? 舉個通俗點的例子,一篇若干數量的文字內容,經過simhash降維後,可能僅僅得到一個長度為32或64位的二進位制由01組成的字串,這一點非常相似我們的身份證,試想一下,如果你要在中國13億+的茫茫人海中尋找一個人,如果你不知道這個人的身份證,你可能要提供姓名 ,住址, 身高,體重,性別,等等維度的因素來確定是否為某個人,從這個例子已經能看出來,如果有一個一維的核心條件身份證,那麼查詢則是非常快速的,如果沒有一維的身份證條件,可能綜合其他幾個非核心的維度,也能確定一個人,但是這種查詢則就比較慢了,而通過我們的SimHash演算法,則就像是給每個人生成了一個身份證,使複雜的事物,能夠通過降維來簡化。

SimHash的工作原理

SimHash演算法工作流程圖:

解釋下上圖:
(1)準備一篇文字
(2)過濾清洗,提取n個特徵關鍵詞,這步一般用分詞的方法實現,關於分詞,比較常用的有IK,mmseg4j,ansj
(3)特徵加權,這一步如果有自己針對某個行業的定義的語料庫時候可以使用,沒有的話,就用分詞後的詞頻即可
(4)對關鍵詞進行hash降維01組成的簽名(上述是6位)
(5)然後向量加權,對於每一個6位的簽名的每一位,如果是1,hash和權重正相乘,如果為0,則hash和權重負相乘,至此就能得到每個特徵值的向量。
(6)合併所有的特徵向量相加,得到一個最終的向量,然後降維,對於最終的向量的每一位如果大於0則為1,否則為0,這樣就能得到最終的simhash的指紋簽名
一個例子如下:

SimHash的應用
通過上面的步驟,我們可以利用SimHash演算法為每一個網頁生成一個向量指紋,那麼問題來了,如何判斷2篇文字的相似性?
這裡面主要應用到是海明距離。

(1)什麼是海明距離
兩個碼字的對應位元取值不同的位元數稱為這兩個碼字的海明距離。在一個有效編碼集中,任意兩個碼字的海明距離的最小值稱為該編碼集的海明距離。舉例如下:10101和00110從第一位開始依次有第一位、第四、第五位不同,則海明距離為3。

(2)海明距離的幾何意義
n位的碼字可以用n維空間的超立方體的一個頂點來表示。兩個碼字之間的海明距離就是超立方體兩個頂點之間的一條邊,而且是這兩個頂點之間的最短距離。

(3)海明距離的應用場景
用於編碼的檢錯和糾錯 

經過SimHash演算法提取來的指紋(Simhash對長文字500字+比較適用,短文字可能偏差較大,具體需要根據實際場景測試),最後使用海明距離,求相似,在google的論文給出的資料中,64位的簽名,在海明距離為3的情況下,可認為兩篇文件是相似的或者是重複的,當然這個值只是參考值,針對自己的應用可能又不同的測試取值

到這裡相似度問題基本解決,但是按這個思路,在海量資料幾百億的數量下,效率問題還是沒有解決的,因為資料是不斷新增進來的,不可能每來一條資料,都要和全庫的資料做一次比較,按照這種思路,處理速度會越來越慢,線性增長。

針對這個問題在Google的論文中也提出了對應的思路,根據鴿巢原理(也稱抽屜原理):

桌上有十個蘋果,要把這十個蘋果放到九個抽屜裡,無論怎樣放,我們會發現至少會有一個抽屜裡面至少放兩個蘋果。這一現象就是我們所說的“抽屜原理”。 抽屜原理的一般含義為:“如果每個抽屜代表一個集合,每一個蘋果就可以代表一個元素,假如有n+1個元素放到n個集合中去,其中必定有一個集合裡至少有兩個元素。” 抽屜原理有時也被稱為鴿巢原理。它是組合數學中一個重要的原理。[1] 

道理很簡單,但在把這應用到現實問題中,可是能發揮巨大作用的,這也就是數學的奧妙之處。

針對海量資料的去重效率,我們可以將64位指紋,切分為4份16位的資料塊,根據抽屜原理在海明距離為3的情況,如果兩個文件相似,那麼它必有一個塊的資料是相等的,如圖:

然後將4份資料通過K-V資料庫或倒排索引儲存起來K為16位截斷指紋,V為K相等時剩餘的48位指紋集合,查詢時候,精確匹配這個指紋的4個16位截斷,如圖所示:

如此,假設樣本庫,有2^34條資料(171億資料),假設資料均勻分佈,則每個16位(16個01數字隨機組成的組合為2^16個)倒排返回的最大數量為
2^34/2^16=2^(34-16)=262144個候選結果,4個16位截斷索引,總的結果為:4*262144=1048576,約為100多萬,通過
這樣一來的降維處理,原來需要比較171億次,現在只需要比較100萬次即可得到結果,這樣以來大大提升了計算效率。


參考文章:
http://www.lanceyan.com/tech/arch/simhash_hamming_distance_similarity.html
http://taop.marchtea.com/06.03.html
http://yanyiwu.com/work/2014/01/30/simhash-shi-xian-xiang-jie.html
http://www.cnblogs.com/colorfulkoala/archive/2012/07/29/2614382.html
http://en.wikipedia.org/wiki/Locality_sensitive_hashing
http://grunt1223.iteye.com/blog/964564