Charikar的simhash演算法對檢測數萬億的儲存層級的相似網頁是非常實用的。作為指紋技術的simhash具有相似文檔的指紋代寫論文
只存在很小位元的不同特性。在detecting near-duplicates for
webcrawling一文中驗證了,對於8B的網頁,64位的指紋和k=3是合適的。Simhash是一種降維技術,可以將高維向量映射為位元較小的指紋。它在網頁中的應用過程如下:首先將文檔轉化為特徵碼的集合,每個特徵碼附有一個權值。特徵碼的產生採用IR技術,比如分詞、大小寫轉換、停止詞去除。一個附有權值的特徵碼的集合構成一個高維向量,通過simhash可以將這個高維向量轉化為f位的指紋,f的值很小,比如64[3]。
給出一個從文檔中提取的帶有權值的特徵碼集合,通過simhash產生f位指紋的過程如下:首先產生一個f維的向量V,每一維都初始化為0。將每個特徵碼雜湊為f位的雜湊值。這些f位的雜湊值可以將V的f個元素增加或減少它所對應的權值大小的值。過程如下:如果雜湊值的第i位對應的值是1,就將V的第i個元素增加它所對應的權值大小的值;如果雜湊值的第i位為0,就將V的第i個元素減去它對應的權值大小的值。當所有的特徵碼都這樣處理完,V中有的元素為正,有的
為負。這些元素的符號決定了最終指紋的相應位元上的值[4~5]。
那給出一個剛抓取的網頁的64位的指紋,如何快速發現有哪些指紋和它最多相差3位呢?假設有8B的64位的指紋,我們要在微秒級的時間裡判斷其中是否有和要查詢的指紋F最多有3位不同,首先探討兩種簡單但並不切合實際的方法。第一種,為所有儲存的指紋建立一張排序表,給定要查詢的指紋F,檢索該表尋找和F的海明距離最大是K的指紋F′。因要檢索的次數太大而不切合實際,如果是64位的指紋,K的值為3,那麼需要C(64,3)=41664次。另一個改進的方法是預先計算出和所有F′的海明距離最大是K的指紋。這種方法的預先計算量也因太大而不切實際:是表中指紋數的41664倍之多。
設想一個2d由f位隨機指紋組成的排序表,其中最高的d位幾乎相當於一個計數器,因為對很少有這d位重複的,另一方面,低f-d位幾乎是隨機的。
選擇一個d′,使得|d′-d|的值很小,因為表是有序的,一次檢測就能夠找出所有和F′在最高的d′位相同的指紋,因為|d′-d|的值很小,所有符合要求的指紋數目也比較小,對於其中的每一個符合要求的指紋,我們可以輕易的判斷出它是否和F最多有K位不同(這些不同很自然的限定在低f-d′位)。上面介紹的方法幫我們定位和F有K位不同的指紋,多有不同的位被限定在低
f-d′位中。這對大部分情況來說是合適的,為了覆蓋所有的情況,需要建立一小部分附加的表。
我們建t個表:T1,T2,……Tt。每一個表都有兩個相關的量:一個整數pi和一個f位指紋上的排列πi。Ti是對每一個指紋應用排列πi後形成的有序表。給定一個指紋F和整數值K,我們並行的檢索這些表:
第一步:找出Ti中所有排列後最高Pi位是和πi(F)的最高Pi位相同的指紋。第二步:對所有第一步中尋找出的排列後的指紋,
查看它是否和πi(F)最多有K位不同。舉例如下:假設f=64,k=3,那麼近似網頁的指紋最多有3位不同。假設我們有8B=234的已有指紋,即
d=34。我們有不同的設計,每種設計有不同的排列集和PI值。
20個表:把64位分成6塊,分別是11,11,11,11,10和10
位。共有C(6,3)=20種方法從6塊中選擇3塊。對於每種選擇,排列π使得選出的塊中的位成為最高位(有幾種這樣的排列,我們統一的隨機播放其中一種)。Pi的值就是選出的塊中的位元的總和。因此Pi=31,32,或者33。平均每次檢測返回最多234~31個排列後的指紋。16個表:把64位分成
4塊,每塊有16位,共有C(4,1)=4種方法從4塊中選擇一塊,對於每種選擇,我們把這48位再分割成4塊,每塊有12位。共有C(4,1)=4種選擇方法。對錶的排列使得選出的塊中的位成為最高位。Pi的值是28。平均每次檢測返回最多234-28個排列後的指紋。