記得以前有人問過我,網頁去重演算法有哪些,我不假思索的說出了余弦向量相似度匹配,但如果是數十億級別的網頁去重呢?這下糟糕了,因為每兩個網頁都需要計算一次向量內積,查重效率太低了!我當時就想:論查詢效率肯定是要考慮hash演算法,相同字串的hashcode肯定相同,不同字串的hashcode卻是大不相同,這也不符合要求啊,會不會存在一種演算法能夠使相似字串的code值也相同或相似呢,於是就找到了google的網頁去重演算法-simhash。我們在使用simhash演算法前需要根據文件量級選擇simhash碼的位數,一般可選32位或者64位。
1主要概念
海明距離:在資訊編碼中,兩個合法**對應位上編碼不同的位數稱為碼距,又稱海明距離。
注:比如合法**長度為8,那麼00111100與11110000的海明距離是4,10101111與01101111的海明距離是2,11110000與11110000的海明距離是0.
2演算法流程
1)分詞
將文件分詞,然後為每個詞分配權重(比如可以用tf-idf演算法計算權重,但這裡需要變換一下演算法,將tf-idf值以單調遞增函式對映到乙個整數值),舉個例子:我(3)是(2)中國人(5),我(3)熱愛(4)我(3)的(1)祖國(5)。括號中是權重,權重越高表示這個詞在文件中越重要。接下來需要去掉tf-idf值過低的,這樣會把「的」這種虛詞過濾掉。
2)計算hash
計算每個詞的hash值,比如「我」——01001000,「是」——10110011,「中國人」——11001100,「熱愛」——10101010,「祖國」——01011000
3)加權
將詞乘以對應的權值,0用-1代替乘以對應權值,這樣,「我」—— -33-3-33-3-3-3,「是」—— 2-222-2-222,「中國人」—— 55-5-555-5-5,「熱愛」—— 4-44-44-44-4,「祖國」—— -55-555-5-5-5
4)合併
把單詞序列從前到後按位累加,上面累加的結果是3,7,-7,-5,15,-9,-7,-15
5)降維
把第4)步的結果變為0-1串,方法是大於0的—>1,小於0的->0,所以結果是11001000,這樣每篇文件會得到乙個id
6)比較海明距離
將第5)步得到的結果與已有的每一篇文件的id做異或運算,然後求運算結果中1的個數(似曾相識燕歸來啊!),得到海明距離。通常對於長文件來說,海明距離小於3的會被認為是一篇文件。對於微博等短文本來說,海明距離可以設定的較大,比如10以內的會被認為是同一篇文件。
3演算法優缺點
優點:1)演算法高效,非常適用於大規模網頁去重
2)演算法非常容易使用在mapreduce等分布式計算中
3)對於每篇文件來說,演算法消耗空間非常小
缺點:1)對於長文件和短文件同時存在的情況,只依靠演算法本身尚不能完美解決網頁去重的問題
2)對於兩篇看似完全不相關的文件來說,其海明距離甚至有可能為0,但出現這種情況的概率極小
文字去重之SimHash演算法
說到文字相似性計算,大家首先想到的應該是使用向量空間模型vsm vector space model 使用vsm計算相似度,先對文字進行分詞,然後建立文字向量,把相似度的計算轉換成某種特徵向量距離的計算,比如余弦角 歐式距離 jaccard相似係數等。這種方法存在很大乙個問題 需要對文字兩兩進行相似...
文字去重之SimHash演算法
說到文字相似性計算,大家首先想到的應該是使用向量空間模型vsm vector space model 使用vsm計算相似度,先對文字進行分詞,然後建立文字向量,把相似度的計算轉換成某種特徵向量距離的計算,比如余弦角 歐式距離 jaccard相似係數等。這種方法存在很大乙個問題 需要對文字兩兩進行相似...
集合去重,高效演算法
我們最常用的兩個集合去重的方法是removeall,但是當兩個集合達到上萬之後就已經很慢了,上百萬之後,處理速度更是令人難以忍受,處理時間超過10分鐘以上,測試 如下 public class test for int i 500000 i 1500000 i system.out.println ...