網頁去重之Simhash算法


Simhash算法是Google應用在網頁去重中的一個常用算法,在開始講解Simhash之前,首先需要了解: 什么是網頁去重?為什么要進行網頁去重?如何進行網頁去重,其基本框架是什么?
 
網頁去重,顧名思義,就是過濾掉重復的網頁。統計結果表明,近似重復網頁的數量占網頁總數量的比例較高,即互聯網上有很多的頁面內容是完全一樣的或是近似一樣的(這個不難理解,比如對於某一事件的新聞報道,很多是大同小異的;再比如說文章的轉載等等)。基於這一實際情況,所以要進行網頁去重。
 
那么如何進行網頁去重呢?這就用到了Simhash算法。
去重算法的任務是對海量數據進行處理,通用的網頁去重的基本框架如下:
  • 對於給定的文檔,首先通過一定的特征抽取手段,從文檔中抽取出一系列能夠表征文檔主體內容的特征集合。這一步的關鍵點在於,盡可能保留文檔的重要信息,拋棄無關緊要的信息。如何判定哪些信息是重要的,哪些是不重要的,屬於特征提取相關算法的研究重點。
  • 將文檔轉換為特征集合后,由於搜索引擎所處理的網頁數量數以億計,為了能夠提高計算速度,很多算法會在特征集合的基礎上,對信息進一步壓縮,采用信息指紋相關算法,將特征集合壓縮為新的數據集合(即生成文檔指紋),其包含的元素數量遠遠小於特征集合數量。
  • 把文檔壓縮為文檔指紋后,即可通過相似性計算來判斷哪些網頁是近似重復頁面。
概括的說,就是: (1)特征詞提取 --> (2)生成文檔指紋 --> (3)相似性計算 
 
流程圖如下圖所示
  
接下來,我們具體來說說Simhash算法的原理。主要是特征詞提取和生成文檔指紋這兩部分。
  1. 從文檔中提取一組能表征文章的特征詞,並計算權重,得到pair<特征詞xxx,權重w>;(這一部分,詳見 TF-IDF算法之關鍵詞提取
  2. 利用hash函數(這個hash函數利用開源實現),將每個特征詞映射成為固定長度(比如說64位)的二進制數,即哈希值,得到pair<哈希值,權重>;
  3. 利用權重w 對步驟2產生的二進制序列進行改寫,即把權重信息融入二進制序列中,變成一個實數向量。假設步驟2中得到的是<100110, 0.57>,那么經過改寫變成了實數向量(0.57,-0.57, -0.57, 0.57, 0.57, -0.57);
  4. 每個特征詞都做了步驟3的改寫后,對一篇文檔中的所有特征詞的實數向量進行累加(即對應位置相加),從而獲得一個代表整個文檔的實數向量。假設最后得到的實數向量是(13, 108, -22, -5, -32, 55)。
  5. 將步驟4得到的實數向量規范化,即將實數向量轉換為二進制序列,轉換規則為正數變為1,負數變為0。即(13, 108, -22, -5, -32, 55) --> 110001。最終得到的這個二進制序列就是本文檔的文檔指紋。
 
流程示意圖如下:
 
計算得到每一篇文檔的文檔指紋后,我們就要對文檔集合中的所有文檔進行相似性計算,把雷同的文檔過濾掉。那么,怎么進行文檔相似性的計算呢?
 
對於文檔A,B,其內容的相似性可以通過A,B對應的文檔指紋的相似性程度來體現。即,內容越相似,二進制序列對應位置相同的位數就越多。而兩個二進制序列之間的差異被稱為“海明距離”,海明距離越小,表示兩篇文檔越相似。一般認為,當海明距離<=3時,兩篇文檔就被視為雷同。至此,問題就轉移至——如何求海明距離?
 
假設文檔A的文檔指紋是100110,文檔B的文檔指紋是100011,顯然,有兩個位置上的數不一樣,即海明距離為2。那么,文檔A,B的海明距離具體該如何計算呢?
A:100110
B:100011
^     000101  --> 海明距離為2
通過上面的計算,我們可以知道,求海明距離,實際上是先對兩個二進制序列進行 異或運算(假設運算結果是ret),再對二進制序列ret求其1的個數。至此,問題又轉移至——如何求一個二進制序列中"1"的個數?
 
關於” 如何求一個二進制序列中"1"的個數“這個問題,在此稍作講解,這是一個經典而又巧妙的基礎算法題。
 
在分析這種算法前,我們先來看看把一個數減1會發生什么神奇的事情?
如果一個整數不等於0,那么該整數的二進制表示中至少有一位是1。
情況1:假設這個數的二進制表示的最右邊一位是1,那么經過減1操作后,最后一位變成了0而其他位不變,也就是最后一位相當於做了取反操作,由1變成0;
比如,一個二進制數1001,減1后,得到1000。
情況2:假設這個數的二進制表示的最后一位是0,而它的最右邊的‘1’ 位於第m位,那么經過減1操作后, 第m位由1變成0,而第m位之后的位取反,第m位之前的位保持不變。比如,一個二進制數1100,減1后,得到1011。
 
在前面兩種情況中,我們發現,把一個整數減去1,都是把它最右邊的1變成0(假設最右邊的 ‘1’ 位於第m位),而第m位右邊若還有0的話,把0變成1,第m位左邊的位保持不變。接下來,我們把一個整數和它減去1的結果做與運算。如:
a    = 1100
a-1 = 1011
ret = a & (a-1) = 1000
可見,把一個整數a減去1,再和原整數a做與運算,會把該整數a最右邊的一個1變成0,那么,一個整數的二進制序列中有多少個1就可以通過這種方式算出來!
 
以下是代碼:

int numOf_1(int n) {
  int cnt = 0;
  while(n) {
    ++cnt;
    n = n & (n-1);
  }
  return cnt;
}

至此,Simhash算法就算全部講完了。
 
【總結】
1、網頁去重的基本框架 (1)特征詞提取 --> (2)生成文檔指紋 --> (3)相似性計算 
2、Simhash算法,將一篇文檔轉換成二進制序列來表示
3、文檔相似性計算-->計算兩篇文檔的海明距離-->計算二進制序列中"1"的個數
 

參考:
1. 《這就是搜索引擎》 張俊林著
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM