python實現Simhash處理大規模文本相似度

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並在原基礎上進行了說明和改善。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章