文字去重之SimHash演算法

2021-06-08 07:54:10 字數 1919 閱讀 2135

說到文字相似性計算,大家首先想到的應該是使用向量空間模型vsm(vector space model)。使用vsm計算相似度,先對文字進行分詞,然後建立文字向量,把相似度的計算轉換成某種特徵向量距離的計算,比如余弦角、歐式距離、jaccard相似係數等。這種方法存在很大乙個問題:需要對文字兩兩進行相似度比較,無法擴充套件到海量文字的處理。想想像google這種全網搜尋引擎,收錄了上百億的網頁,爬蟲每天爬取的網頁數都是百萬千萬級別的。為了防止重複收錄網頁,爬蟲需要對網頁進行判重處理。如果採用vsm方法,計算量是相當可觀的。

這裡介紹的simhash演算法很好的解決了vsm方法的缺陷,該方法最初由google提出,用於網頁去重。

在介紹simhash前,先大概說下傳統的hash演算法。我們知道,衡量乙個hash演算法好壞的乙個指標是隨機性。也被稱作簡單一致雜湊假設:每個關鍵字都等可能地雜湊到m個槽位中的任何乙個中去,並與其他的關鍵字已被雜湊到哪乙個槽位中無關。說白了,就是讓雜湊的分布盡量均勻,哪怕內容發生很小的變化,hash值也會發生很大的變化。因此,根據傳統的hash值無法得知被雜湊內容的相似程度。

下面正式談談simhash演算法。它的神奇之處就在 

於它的簽名值除了提供原始內容是否相等的資訊外,還能額外提供不相等的原始內容的差異程度的資訊。simhash的思想非常簡單,如圖所示:

演算法描述如下:

輸入為乙個n維向量v,比如文字的特徵向量,每個特徵具有一定權重。輸出是乙個c位的二進位制簽名s。

1)初始化乙個c維向量q為0,c位的二進位制簽名s為0。

2)對向量v中的每乙個特徵,使用傳統的hash演算法計算出乙個c位的雜湊值h。對1<=i<=c,

如果h的第i位為1,則q的第i個元素加上該特徵的權重;

否則,q的第i個元素減去該特徵的權重。

3)如果q的第i個元素大於0,則s的第i位為1;否則為0;

4)返回簽名s。

對每篇文件根據simhash算出簽名後,再計算兩個簽名的海明距離(兩個二進位制異或後1的個數)即可。根據經驗值,對64位的simhash,海明距離在3以內的可以認為相似度比較高。

讀到這裡,你也許有乙個疑惑:simhash到底是怎樣解決vsm需要兩兩比較的缺陷呢?請繼續往下看。

假設對64位的simhash,我們要找海明距離在3以內的所有簽名。我們可以把64位的二進位制簽名均分成4塊,每塊16位。根據鴿巢原理(也成抽屜原理,見組合數學),如果兩個簽名的海明距離在3以內,它們必有一塊完全相同。你也許很興奮,說的這些你都懂。但是請不要忘了,我們事先是不知道具體是哪一塊完全相同,因此我們需要窮舉,對,你沒看錯,是窮舉。但是這裡的窮舉也就是4次而已。我們把上面分成的4塊中的每乙個塊分別作為前16位來進行查詢。什麼意思呢?請看圖:

通過這幅圖,不知道你看明白沒有,反正我還沒有明白。下面讓咱們一起進一步探索。

舉個簡單的例子,對於8位的二進位制簽名 

0110

0011,咱們分別把每一塊拿出來,在所有的8位二進位制簽名中查詢前兩位分別是01,10,00,11的簽名。也許你要說,那不同樣需要兩兩比較嗎?對,常規意義下卻是如此。但是咱們可以做索引啊!按照前兩位進行索引,比如00111111和00101010放在乙個簇中,10111111和10101010放在乙個簇中。這下應該明白了吧。

如果庫中有2^34個(大概10億)簽名,那麼匹配上每個塊的結果最多有2^(34-16)=262144個候選結果,四個塊返回的總結果數為4* 262144(大概100萬)。原本需要比較10億次,經過索引,大概就只需要處理100萬次了。由此可見,確實大大減少了計算量。

更進一步的,如果將剩餘48位再做4個chunk的劃分,根據抽屜原理,又會有1個chunk是完全一致的,這可以進一步加速fingerprint的相似度計算,如下圖所示:

文字去重之SimHash演算法

說到文字相似性計算,大家首先想到的應該是使用向量空間模型vsm vector space model 使用vsm計算相似度,先對文字進行分詞,然後建立文字向量,把相似度的計算轉換成某種特徵向量距離的計算,比如余弦角 歐式距離 jaccard相似係數等。這種方法存在很大乙個問題 需要對文字兩兩進行相似...

使用SimHash進行海量文字去重

閱讀目錄 在之前的兩篇博文分別介紹了常用的hash方法 data structure algorithm hash那點事兒 以及區域性敏感hash演算法 algorithm 區域性敏感雜湊演算法 locality sensitive hashing 本文介紹的simhash是一種區域性敏感hash,...

基於simhash的短文本去重

usr bin env python coding utf 8 利用simhash進行文字去重 from simhash import simhash,simhashindex import jieba import codecs import datetime import os class du...