如何利用python实现Simhash算法


Posted in Python onJune 28, 2022

1. 为什么需要Simhash?

传统相似度算法:文本相似度的计算,一般使用向量空间模型(VSM),先对文本分词,提取特征,根据特征建立文本向量,把文本之间相似度的计算转化为特征向量距离的计算,如欧式距离、余弦夹角等。

缺点:大数据情况下复杂度会很高。

Simhash应用场景:计算大规模文本相似度,实现海量文本信息去重。

Simhash算法原理:通过hash值比较相似度,通过两个字符串计算出的hash值,进行异或操作,然后得到相差的个数,数字越大则差异越大。

2. 文章关键词特征提取算法TD-IDF

词频(TF):一个词语在整篇文章中出现的次数与词语总个数之比;

逆向词频(IDF):一个词语,在所有文章中出现的频率都非常高,这个词语不具有代表性,就可以降低其作用,也就是赋予其较小的权值。

如何利用python实现Simhash算法

分子代表文章总数,分母表示该词语在这些文章出现的篇数。一般会采取分母加一的方法,防止分母为0的情况出现,在这个比值之后取对数,就是IDF了。

最终用tf*idf得到一个词语的权重,进而计算一篇文章的关键词。然后根据每篇文章对比其关键词的方法来对文章进行去重。simhash算法对效率和性能进行平衡,既可以很少的对比(关键词不能取太多),又能有好的代表性(关键词不能过少)。

3. Simhash原理

Simhash是一种局部敏感hash。即假定A、B具有一定的相似性,在hash之后,仍然能保持这种相似性,就称之为局部敏感hash。

得到一篇文章关键词集合,通过hash的方法把关键词集合hash成一串二进制,直接对比二进制数,其相似性就是两篇文档的相似性,在查看相似性时采用海明距离,即在对比二进制的时候,看其有多少位不同,就称海明距离为多少。

将文章simhash得到一串64位的二进制,根据经验一般取海明距离为3作为阈值,即在64位二进制中,只要有三位以内不同,就可以认为两个文档是相似的,这里的阈值也可以根据自己的需求来设置。也就是把一个文档hash之后得到一串二进制数的算法,称这个hash为simhash。

simhash具体实现步骤如下:

  • 1. 将文档分词,取一个文章的TF-IDF权重最高的前20个词(feature)和权重(weight)。即一篇文档得到一个长度为20的(feature:weight)的集合。
  • 2. 对其中的词(feature),进行普通的哈希之后得到一个64为的二进制,得到长度为20的(hash : weight)的集合。
  • 3. 根据(2)中得到一串二进制数(hash)中相应位置是1是0,对相应位置取正值weight和负值weight。例如一个词进过(2)得到(010111:5)进过步骤(3)之后可以得到列表[-5,5,-5,5,5,5]。由此可以得到20个长度为64的列表[weight,-weight...weight]代表一个文档。
  • 4. 对(3)中20个列表进行列向累加得到一个列表。如[-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的列表。
  • 5. 对(4)中得到的列表中每个值进行判断,当为负值的时候去0,正值取1。例如,[-7,1,-9,9,3,9]得到010111,这样就得到一个文档的simhash值了。
  • 6. 计算相似性。两个simhash取异或,看其中1的个数是否超过3。超过3则判定为不相似,小于等于3则判定为相似。

Simhash整体流程图如下:

如何利用python实现Simhash算法

4. Simhash的不足

完全无关的文本正好对应成了相同的simhash,精确度并不是很高,而且simhash更适用于较长的文本,但是在大规模语料进行去重时,simhash的计算速度优势还是很不错的。

5. Simhash算法实现

# !/usr/bin/python
# coding=utf-8
class Simhash:
    def __init__(self, tokens='', hashbits=128):
        self.hashbits = hashbits
        self.hash = self.simhash(tokens)
    def __str__(self):
        return str(self.hash)
    # 生成simhash值
    def simhash(self, tokens):
        v = [0] * self.hashbits
        for t in [self._string_hash(x) for x in tokens]:  # t为token的普通hash值
            for i in range(self.hashbits):
                bitmask = 1 << i
                if t & bitmask:
                    v[i] += 1  # 查看当前bit位是否为1,是的话将该位+1
                else:
                    v[i] -= 1  # 否则的话,该位-1
        fingerprint = 0
        for i in range(self.hashbits):
            if v[i] >= 0:
                fingerprint += 1 << i
        return fingerprint  # 整个文档的fingerprint为最终各个位>=0的和
    # 求海明距离
    def hamming_distance(self, other):
        x = (self.hash ^ other.hash) & ((1 << self.hashbits) - 1)
        tot = 0
        while x:
            tot += 1
            x &= x - 1
        return tot
    # 求相似度
    def similarity(self, other):
        a = float(self.hash)
        b = float(other.hash)
        if a > b:
            return b / a
        else:
            return a / b
    # 针对source生成hash值
    def _string_hash(self, source):
        if source == "":
            return 0
        else:
            x = ord(source[0]) << 7
            m = 1000003
            mask = 2 ** self.hashbits - 1
            for c in source:
                x = ((x * m) ^ ord(c)) & mask
            x ^= len(source)
            if x == -1:
                x = -2
            return x

测试:

if __name__ == '__main__':
    s = 'This is a test string for testing'
    hash1 = Simhash(s.split())
    s = 'This is a string testing 11'
    hash2 = Simhash(s.split())
    print(hash1.hamming_distance(hash2), "   ", hash1.similarity(hash2))

到此这篇关于如何利用python实现Simhash算法的文章就介绍到这了,更多相关pythonSimhash算法内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!


Tags in this post...

Python 相关文章推荐
Python发送Email方法实例
Aug 21 Python
Python反射用法实例简析
Dec 22 Python
python绘制中国大陆人口热力图
Nov 07 Python
Python操作MySQL数据库的两种方式实例分析【pymysql和pandas】
Mar 18 Python
Python 中包/模块的 `import` 操作代码
Apr 22 Python
Python获取好友地区分布及好友性别分布情况代码详解
Jul 10 Python
pip install 使用国内镜像的方法示例
Apr 03 Python
Python+Kepler.gl轻松制作酷炫路径动画的实现示例
Jun 02 Python
浅谈keras中Dropout在预测过程中是否仍要起作用
Jul 09 Python
手把手教你从PyCharm安装到激活(最新激活码),亲测有效可激活至2089年
Nov 25 Python
pytorch中的model=model.to(device)使用说明
May 24 Python
python 利用PyAutoGUI快速构建自动化操作脚本
May 31 Python
python数字图像处理:图像的绘制
python数字图像处理数据类型及颜色空间转换
python数据分析之单因素分析线性拟合及地理编码
python可视化分析绘制带趋势线的散点图和边缘直方图
基于Python编写一个监控CPU的应用系统
如何基于python实现单目三维重建详解
python如何读取和存储dict()与.json格式文件
Jun 25 #Python
You might like
PHP输出控制功能在简繁体转换中的应用
2006/10/09 PHP
java EJB 加密与解密原理的一个例子
2008/01/11 PHP
PHP自动重命名文件实现方法
2014/11/04 PHP
PHP ajax 异步执行不等待执行结果的处理方法
2015/05/27 PHP
TP5框架实现签到功能的方法分析
2020/04/05 PHP
jQuery使用手册之二 DOM操作
2007/03/24 Javascript
dtree 网页树状菜单及传递对象集合到js内,动态生成节点
2012/04/14 Javascript
侧栏跟随滚动的简单实现代码
2013/03/18 Javascript
JavaScript将Web页面内容导出到Word及Excel的方法
2015/02/13 Javascript
jQuery右下角旋转环状菜单特效代码
2015/08/10 Javascript
详解javascript事件绑定使用方法
2016/10/20 Javascript
vue + socket.io实现一个简易聊天室示例代码
2017/03/06 Javascript
AngularJS中controller控制器继承的使用方法
2017/11/03 Javascript
vue.js 底部导航栏 一级路由显示 子路由不显示的解决方法
2018/03/09 Javascript
JavaScript高级函数应用之分时函数实例分析
2018/08/03 Javascript
详解element-ui中表单验证的三种方式
2019/09/18 Javascript
nginx配置域名后的二级目录访问不同项目的配置操作
2020/11/06 Javascript
Python3中的真除和Floor除法用法分析
2016/03/16 Python
Python工厂函数用法实例分析
2018/05/14 Python
对python3新增的byte类型详解
2018/12/04 Python
python 读取鼠标点击坐标的实例
2018/12/29 Python
Python解决pip install时出现的Could not fetch URL问题
2019/08/01 Python
L’urv官网:精品女性运动服品牌
2019/07/07 全球购物
土木工程专业自荐信
2013/10/04 职场文书
11月红领巾广播稿
2014/01/17 职场文书
领导接待方案
2014/03/13 职场文书
生态养殖创业计划书
2014/05/06 职场文书
无毒社区工作方案
2014/05/23 职场文书
群众路线个人对照检查材料
2014/09/23 职场文书
校园广播稿100字
2014/10/06 职场文书
陕西导游词
2015/02/04 职场文书
2015年店长个人工作总结
2015/10/23 职场文书
保险公司增员口号
2015/12/25 职场文书
python glom模块的使用简介
2021/04/13 Python
Java Optional<Foo>转换成List<Bar>的实例方法
2021/06/20 Java/Android
Vue实现跑马灯样式文字横向滚动
2021/11/23 Vue.js