simHash介紹及python實現

2021-09-25 05:03:50 字數 3994 閱讀 4720

simhash演算法是googlemoses charikear於2023年發布的一篇**《detecting near-duplicates for web crawling》中提出的, 專門用來解決億萬級別的網頁去重任務。

simhash是區域性敏感雜湊(locality sensitve hash)的一種,其主要思想是降維,將高維的特徵向量對映成低維的特徵向量,再通過比較兩個特徵向量的漢明距離(hamming distance)來確定文章之間的相似性。

什麼是區域性敏感呢?假設a,b具有一定的相似性,在hash之後,仍能保持這種相似性,就稱之為區域性敏感hash

漢明距離

hamming distance,又稱漢明距離,在資訊理論中,等長的兩個字串之間的漢明距離就是兩個字串對應位置的不同字元的個數。即將乙個字串變換成另外乙個字串所需要替換的字元個數,可使用異或操作。

例如: 1011與1001之間的漢明距離是1。

simhash演算法總共分為5個流程: 分詞、has、加權、合併、降維。

分詞對待處理文件進行中文分詞,得到有效的特徵及其權重。可以使用tf-idf方法獲取一篇文章權重最高的前topk個詞(feature)和權重(weight)。即可使用jieba.analyse.extract_tags()來實現

hash

對獲取的詞(feature),進行普通的雜湊操作,計算hash值,這樣就得到乙個長度為n位的二進位制,得到(hash:weight)的集合。

加權

在獲取的hash值的基礎上,根據對應的weight值進行加權,即w=hash*weight。即hash為1則和weight正相乘,為0則和weight負相乘。例如乙個詞經過hash後得到(010111:5)經過步驟(3)之後可以得到列表[-5,5,-5,5,5,5]。

合併

將上述得到的各個向量的加權結果進行求和,變成只有乙個序列串。如[-5,5,-5,5,5,5]、[-3,-3,-3,3,-3,3]、[1,-1,-1,1,1,1]進行列向累加得到[-7,1,-9,9,3,9],這樣,我們對乙個文件得到,乙個長度為64的列表。

降維

對於得到的n-bit簽名的累加結果的每個值進行判斷,大於0則置為1, 否則置為0,從而得到該語句的simhash值。例如,[-7,1,-9,9,3,9]得到 010111,這樣,我們就得到乙個文件的 simhash值。

最後根據不同語句的simhash值的漢明距離來判斷相似度。

根據經驗值,對64位的 simhash值,海明距離在3以內的可認為相似度比較高。

使用python實現simhash演算法,具體如下:

# -*- coding:utf-8 -*-

import jieba

import jieba.analyse

import numpy as np

class

simhash

(object):

defsimhash

(self, content)

: seg = jieba.cut(content)

# jieba.analyse.set_stop_words('stopword.txt')

keywords = jieba.analyse.extract_tags(

"|".join(seg)

, topk=

10, withweight=

true

) keylist =

for feature, weight in keywords:

print

('weight: {}'

.format

(weight)

)# weight = math.ceil(weight)

weight =

int(weight)

binstr = self.string_hash(feature)

temp=

for c in binstr:

if(c ==

'1')

:else

:-weight)

listsum = np.

sum(np.array(keylist)

, axis =0)

if(keylist ==

):return

'00'

simhash =

''for i in listsum:

if(i>0)

: simhash = simhash +

'1'else

: simhash = simhash +

'0'return simhash

defstring_hash

(self, source)

:if source =="":

return

0else

: x =

ord(source[0]

)<<

7 m =

1000003

mask =2**

128-

1for c in source:

x =((x*m)

^ord

(c))

& mask

x ^=len

(source)

if x ==-1

: x =-2

x =bin(x)

.replace(

'0b',''

).zfill(64)

[-64:

]# print('strint_hash: %s, %s'%(source, x))

return

str(x)

defgetdistance

(self, hashstr1, hashstr2)

:'''

計算兩個simhash的漢明距離

'''length =

0for index, char in

enumerate

(hashstr1)

:if char == hashstr2[index]

:continue

else

: length +=

1return length

if __name__ ==

'__main__'

: simhash = simhash(

) s1 = simhash.simhash(

'我想洗**'

) s2 = simhash.simhash(

'可以洗一張**嗎'

) dis = simhash.getdistance(s1, s2)

print

('dis: {}'

.format

(dis)

)

對於短小的文字,計算相似度並不十分準確,更適用於較長的文字。

參考資料

simhash演算法及原理簡介 - lengye7的部落格 - csdn部落格

**simhash及其python實現 - madujin的部落格 - csdn部落格

simhash原理及使用

simhash是一種區域性敏感hash。那什麼叫區域性敏感呢,假定兩個字串具有一定的相似性,在hash之後,仍然能保持這種相似性,就稱之為區域性敏感hash。普通的hash是不具有這種屬性的。simhash被google用來在海量文字中去重。演算法過程大概如下 對每個feature weight p...

unittest基本原理及介紹(python篇)

unittest是python自帶的測試框架,還有乙個框架是 pytest,這裡簡單介紹下unittest模組的簡單應用 unittest是python的標準測試庫,相比於其他測試框架是python目前使用最廣的測試框架。test fixture,test case,test suite,test ...

simhash 介紹以及應用場景

simhash 演算法是一種區域性敏感的雜湊演算法,能實現相似文字內容的去重。資訊摘要演算法 如果兩者原始內容只相差乙個位元組,所產生的簽名也很有可能差別很大。simhash 演算法 如果原始內容只相差乙個位元組,所產生的簽名差別非常小。simhash值的對比 通過兩者的 simhash 值的二進位...