Simhash簡介:
Simhash–顧名思義,通過hash值比較相似度,通過兩個字符串得出來的hash值,進行異或操作,然後得到相差的個數,數字越大則差異越大。
Simhash流程:
計算文本hash值的步驟:
1、用分詞工具(jieba、NLPIR、哈工大分詞器等)對字符串進行分詞、去除停用詞,英文除外;
seg = jieba.cut(str)
2、分詞後篩選關鍵詞,計算關鍵詞的權重;
keyword = jieba.analyse.extract_tags('|'.join(seg), topK=20, withWeight=True, allowPOS=())
3、把關鍵詞的特徵提取出來;
for i in feature:
if i == '1':
temp.append(weight)
else:
temp.append(-weight)
4、將該文本的整體關鍵詞特徵進行融合,歸一化;
list1 = np.sum(np.array(keyList), axis=0)
計算sim值:
1、用hash得出來的hash值兩兩進行比較;
t1 = '0b' + self.sim1
t2 = '0b' + self.sim2
n = int(t1, 2) ^ int(t2, 2)
2、通過異或比較,得處simhash值。
i = 0
while n:
n &= (n - 1)
i += 1
return i
處理大規模文本
如何使用simhash處理大規模文本數據,原理很簡單,以上步驟我們可以計算兩個字符串之間的相似度,引申這種思想,對文本中的數據進行處理。
其中使用到了排序的思路,我們對文本中的數據進行兩兩比較,那麼本身不用比,本身和後面字符串比較過的也不必比較,那就是一個對角矩陣,即i與i+1個元素對比。
for i in range(len(list)-1):
for y in range(i+1,len(list))
以上爲在處理大規模文本相似度時所用到的simhash思想。
# -*- coding: utf-8 -*-
# !/usr/bin/env python
'''
function:python實現大規模simhash對比
time:2020-06-19 14:32:10
author:爲援不可圖
'''
import jieba
import jieba.analyse
import numpy as np
# 獲取字符串對應的hash值
class SimhashStr():
def __init__(self, str):
self.str = str
# 得到輸入字符串的hash值
def get_hash(self):
# 結巴分詞
seg = jieba.cut(self.str)
# 取前20個關鍵詞
keyword = jieba.analyse.extract_tags('|'.join(seg), topK=20, withWeight=True, allowPOS=())
keyList = []
# 獲取每個詞的權重
for feature, weight in keyword:
# 每個關鍵詞的權重*總單詞數
weight = int(weight * 20)
# 獲取每個關鍵詞的特徵
feature = self.string_hash(feature)
temp = []
# 獲取每個關鍵詞的權重
for i in feature:
if i == '1':
temp.append(weight)
else:
temp.append(-weight)
keyList.append(temp)
# 將每個關鍵詞的權重變成一維矩陣
list1 = np.sum(np.array(keyList), axis=0)
# 獲取simhash值
simhash = ''
for i in list1:
# 對特徵標準化表示
if i > 0:
simhash = simhash + '1'
else:
simhash = simhash + '0'
return simhash
def string_hash(self, feature):
if feature == "":
return 0
else:
# 將字符轉爲二進制,並向左移動7位
x = ord(feature[0]) << 7
m = 1000003
mask = 2 ** 128 - 1
# 拼接每個關鍵詞中字符的特徵
for c in feature:
x = ((x * m) ^ ord(c)) & mask
x ^= len(feature)
if x == -1:
x = -2
# 獲取關鍵詞的64位表示
x = bin(x).replace('0b', '').zfill(64)[-64:]
return str(x)
# 比較兩個字符串的相似度
class simliary():
def __init__(self, sim1, sim2):
self.sim1 = sim1
self.sim2 = sim2
# 比較兩個simhash值的相似度
def com_sim(self):
# 轉爲二進制結構
t1 = '0b' + self.sim1
t2 = '0b' + self.sim2
n = int(t1, 2) ^ int(t2, 2)
# 相當於對每一位進行異或操作
i = 0
while n:
n &= (n - 1)
i += 1
return i
#比較大量文本中數據之間的相似度
class com_file_data_sim():
def __init__(self, path):
self.path = path
# 獲取文件中的數據列表
def get_file_data(self):
content_txt = []
with open(self.path, 'r', encoding='utf-8') as f:
lines = f.readlines()
for line in lines:
content = line.strip()
content_txt.append(content)
return content_txt
# 對列表中的數據進行hash值比對
def com_data_sim(self):
content_data = self.get_file_data()
for i in range(len(content_data) - 1):
for y in range(i + 1, len(content_data)):
str1 = content_data[i]
str2 = content_data[y]
sim1 = SimhashStr(str1).get_hash()
sim2 = SimhashStr(str2).get_hash()
sim = simliary(sim1, sim2).com_sim()
print(str1 + ' ' + str2 + ' ' + '\n'+'simhash值爲:'+str(sim))
if __name__ == '__main__':
com_file_data_sim('com.txt').com_data_sim()
本程序參考自https://blog.csdn.net/madujin/article/details/53152619並在原基礎上進行了說明和改善。