转发请注明出处:https://blog.csdn.net/HHTNAN

对于文本去重来说,我个人处理上会从数据量、文本特征、文本长度(短文本、长文本)几个方向考虑。
常见的去重任务,如网页去重,帖子去重,评论去重等等。
好的去重任务是不仅比对文本的相似性,还要比对语义上的相似性。

下面我们来介绍下文本去重的方案。

1.传统签名算法与文本完整性判断

一、传统签名算法与文本完整性判断
问题抛出:
(1)运维上线一个bin文件,将文件分发到4台线上机器上,如何判断bin文件全部是一致的?
(2)用户A将消息msg发送给用户B,用户B如何判断收到的msg_t就是用户A发送的msg?

思路:

一个字节一个字节的比对两个大文件或者大网页效率低,我们可以用一个签名值(例如md5值)代表一个大文件,签名值相同则认为大文件相同(先不考虑冲突率)

回答:

(1)将bin文件取md5,将4台线上机器上的bin文件也取md5,如果5个md5值相同,说明一致

(2)用户A将msg以及消息的md5同时发送给用户B,用户B收到msg_t后也取md5,得到的值与用户A发送过来的md5值如果相同,则说明msg_t与msg相同

结论: md5是一种签名算法,常用来判断数据的完整性与一致性

md5设计原则: 两个文本哪怕只有1个bit不同,其md5签名值差别也会非常大,故它只适用于“完整性”check,不适用于“相似性”check。

新问题抛出:

有没有一种签名算法,如果文本非常相似,签名值也非常相似呢?
此方法来源于网络,我认为很好,故直接引用了,作为开篇,如有侵权,可随时与我联系。

simhash


simhash是google用来处理海量文本去重的算法。 google出品,你懂的。 simhash最牛逼的一点就是将一个文档,最后转换成一个64位的字节,暂且称之为特征字,然后判断重复只需要判断他们的特征字的距离是不是<n(根据经验这个n一般取值为3),就可以判断两个文档是否相似。

原理

simhash值的生成图解如下

概花三分钟看懂这个图就差不多怎么实现这个simhash算法了。特别简单。谷歌出品嘛,简单实用。

  • 1、分词,把需要判断文本分词形成这个文章的特征单词。最后形成去掉噪音词的单词序列并为每个词加上权重,我们假设权重分为5个级别(1~5)。比如:“
    美国“51区”雇员称内部有9架飞碟,曾看见灰色外星人 ” ==> 分词后为 “ 美国(4) 51区(5) 雇员(3) 称(1) 内部(2)
    有(1) 9架(3) 飞碟(5) 曾(1) 看见(3) 灰色(4) 外星人(5)”,括号里是代表单词在整个句子里重要程度,数字越大越重要。

  • 2、hash,通过hash算法把每个词变成hash值,比如“美国”通过hash算法计算为 100101,“51区”通过hash算法计算为
    101011。这样我们的字符串就变成了一串串数字,还记得文章开头说过的吗,要把文章变为数字计算才能提高相似度计算性能,现在是降维过程进行时。

  • 3、加权,通过 2步骤的hash生成结果,需要按照单词的权重形成加权数字串,比如“美国”的hash值为“100101”,通过加权计算为“4
    -4 -4 4 -4 4”;“51区”的hash值为“101011”,通过加权计算为 “ 5 -5 5 -5 5 5”。

  • 4、合并,把上面各个单词算出来的序列值累加,变成只有一个序列串。比如 “美国”的 “4 -4 -4 4 -4 4”,“51区”的 “ 5
    -5 5 -5 5 5”, 把每一位进行累加, “4+5 -4±5 -4+5 4±5 -4+5 4+5” ==》 “9 -9 1 -1 1 9”。这里作为示例只算了两个单词的,真实计算需要把所有单词的序列串累加。

  • 5、降维,把4步算出来的 “9 -9 1 -1 1 9” 变成 0 1 串,形成我们最终的simhash签名。 如果每一位大于0 记为1,小于0 记为 0。最后算出结果为:“1 0 1 0 1 1”。
    整个过程图为:


到此,如何从一个doc到一个simhash值的过程已经讲明白了。

大家可能会有疑问,经过这么多步骤搞这么麻烦,不就是为了得到个 0 1 字符串吗?我直接把这个文本作为字符串输入,用hash函数生成 0 1 值更简单。其实不是这样的,传统hash函数解决的是生成唯一值,比如 md5、hashmap等。md5是用于生成唯一签名串,只要稍微多加一个字符md5的两个数字看起来相差甚远;hashmap也是用于键值对查找,便于快速插入和查找的数据结构。不过我们主要解决的是文本相似度计算,要比较的是两个文章是否相识,当然我们降维生成了hashcode也是用于这个目的。看到这里估计大家就明白了,我们使用的simhash就算把文章中的字符串变成 01 串也还是可以用于计算相似度的,而传统的hashcode却不行。我们可以来做个测试,两个相差只有一个字符的文本串,“你妈妈喊你回家吃饭哦,回家罗回家罗” 和 “你妈妈叫你回家吃饭啦,回家罗回家罗”。

通过simhash计算结果为:

10000100101011011111111000001010110100010011111000010010110010111000010010101101011111100000101011010001001111100001101010001011

通过 hashcode计算为:

11111111111111111111111111111111100010000011001101001110110111101010010001111111110010110011101

大家可以看得出来,相似的文本只有部分 01 串变化了,而普通的hashcode却不能做到,这个就是局部敏感哈希的魅力。目前Broder提出的shingling算法和Charikar的simhash算法应该算是业界公认比较好的算法。在simhash的发明人Charikar的论文中并没有给出具体的simhash算法和证明,量子图灵”得出的证明simhash是由随机超平面hash算法演变而来的。

下面是关于【海明距离】
二进制串A 和 二进制串B 的海明距离 就是 A xor B 后二进制中1的个数。
举例如下:

>     A = 100111;
>     B = 101010;
>     hamming_distance(A, B) = count_1(A xor B) = count_1(001101) = 3;

当我们算出所有doc的simhash值之后,需要计算doc A和doc B之间是否相似的条件是:

A和B的海明距离是否小于等于n,这个n值根据经验一般取值为3,

simhash本质上是局部敏感性的hash,和md5之类的不一样。 正因为它的局部敏感性,所以我们可以使用海明距离来衡量simhash值的相似度。

simhash是由 Charikar 在2002年提出来的,参考 《Similarity estimation techniques from rounding algorithms》 。

通过这样的转换,我们把库里的文本都转换为simhash 代码,并转换为long类型存储,空间大大减少。现在我们虽然解决了空间,但是如何计算两个simhash的相似度呢?难道是比较两个simhash的01有多少个不同吗?对的,其实也就是这样,我们通过海明距离(Hamming distance)就可以计算出两个simhash到底相似不相似。两个simhash对应二进制(01串)取值不同的数量称为这两个simhash的海明距离。举例如下: 10101 和 00110 从第一位开始依次有第一位、第四、第五位不同,则海明距离为3。对于二进制字符串的a和b,海明距离为等于在a XOR b运算结果中1的个数(普遍算法)。

为了高效比较,我们预先加载了库里存在文本并转换为simhash code 存储在内存空间。来一条文本先转换为 simhash code,然后和内存里的simhash code 进行比较,测试100w次计算在100ms。速度大大提升。

小节:

  • 1、目前速度提升了但是数据是不断增量的,如果未来数据发展到一个小时100w,按现在一次100ms,一个线程处理一秒钟 10次,一分钟 60 10 次,一个小时 6010 60 次 = 36000次,一天 601060*24 = 864000次。 我们目标是一天100w次,通过增加两个线程就可以完成。但是如果要一个小时100w次呢?则需要增加30个线程和相应的硬件资源保证速度能够达到,这样成本也上去了。能否有更好的办法,提高我们比较的效率?
  • 2、通过大量测试,simhash用于比较大文本,比如500字以上效果都还蛮好,距离小于3的基本都是相似,误判率也比较低。但是如果我们处理的是微博信息,最多也就140个字,使用simhash的效果并不那么理想。看如下图,在距离为3时是一个比较折中的点,在距离为10时效果已经很差了,不过我们测试短文本很多看起来相似的距离确实为10。如果使用距离为3,短文本大量重复信息不会被过滤,如果使用距离为10,长文本的错误率也非常高,如何解决?

代码实现

#coding:utf8
import math
import jieba
import jieba.analyseclass SimHash(object):def __init__(self):passdef getBinStr(self, source):if source == "":return 0else:x = ord(source[0]) << 7m = 1000003mask = 2 ** 128 - 1for c in source:x = ((x * m) ^ ord(c)) & maskx ^= len(source)if x == -1:x = -2x = bin(x).replace('0b', '').zfill(64)[-64:]print(source, x)return str(x)def getWeight(self, source):# fake weight with keywordreturn ord(source)def unwrap_weight(self, arr):ret = ""for item in arr:tmp = 0if int(item) > 0:tmp = 1ret += str(tmp)return retdef simHash(self, rawstr):seg = jieba.cut(rawstr, cut_all=True)keywords = jieba.analyse.extract_tags("|".join(seg), topK=100, withWeight=True)print(keywords)ret = []for keyword, weight in keywords:binstr = self.getBinStr(keyword)keylist = []for c in binstr:weight = math.ceil(weight)if c == "1":keylist.append(int(weight))else:keylist.append(-int(weight))ret.append(keylist)# 对列表进行"降维"rows = len(ret)cols = len(ret[0])result = []for i in range(cols):tmp = 0for j in range(rows):tmp += int(ret[j][i])if tmp > 0:tmp = "1"elif tmp <= 0:tmp = "0"result.append(tmp)return "".join(result)def getDistince(self, hashstr1, hashstr2):length = 0for index, char in enumerate(hashstr1):if char == hashstr2[index]:continueelse:length += 1return lengthif __name__ == "__main__":simhash = SimHash()s1="感冒了怎么办"  #效果不好,语义s2="感冒了怎么治"# s1 = "100元=38万星币,加微信"  #效果不好# s2 = "38万星币100元,加VX"# with open("a.txt", "r") as file:#     s1 = "".join(file.readlines())#     file.close()# with open("b.txt", "r") as file:#     s2 = "".join(file.readlines())#     file.close()# s1 = "this is just test for simhash, here is the difference"# s2 = "this is a test for simhash, here is the difference"# print(simhash.getBinStr(s1))# print(simhash.getBinStr(s2))hash1 = simhash.simHash(s1)hash2 = simhash.simHash(s2)distince = simhash.getDistince(hash1, hash2)# value = math.sqrt(len(s1)**2 + len(s2)**2)value = 5print("海明距离:", distince, "判定距离:", value, "是否相似:", distince<=value)


参考资料:直通车

文本去重的技术方案讨论(一)相关推荐

  1. 汉字转拼音技术方案讨论

    汉字转拼音技术方案讨论   将汉字转化成拼音的应用需求有很多,例如:1.在搜索引擎输入框的智能纠错上,将"刘德花"自动纠正成"刘德华";2.按照拼音检索电话本. ...

  2. 铁路通信线路、传输及接入网设计规范_信号系统车地传输技术方案讨论

    概述基于无线通信的移动闭塞 ATC 系统就车-地双向信息传输技术而言,可分为无线局域网(WLAN)技术和 TD-LTE 技术.由此,提供以下两套系统方案:方案一:基于 TD-LTE 技术的车地通信传输 ...

  3. 《结合DDD讲清楚编写技术方案的七大维度》再讨论

    欢迎大家关注公众号「JAVA前线」查看更多精彩分享文章,主要包括源码分析.实际应用.架构思维.职场分享.产品思考等等,同时欢迎大家加我个人微信「java_front」一起交流学习 1 前文回顾 我在之 ...

  4. 技术天地 | CSS-in-JS:一个充满争议的技术方案

    导读 为了解决传统CSS在现代前端应用开发中遇到的痛点,FreeWheel评估了大量新一代的CSS框架/工具/方案.在本文中,作者以评估过程为线索,介绍了CSS-in-JS的背景.现状.开发特点和趋势 ...

  5. iOS - 图文混排技术方案分享

    前言 不少同学在工作中都能遇到图文混排的需求.但是实现图文混排的技术方案有好几种,相应的方案优劣也有差别.今天和大家一起分享一下图文混排的技术方案以及我的选择. Demo和解析工具已经开源 GitHu ...

  6. SemEval-2020自由文本关系抽取冠军方案解读 (附NLP竞赛常用技巧总结)

    本文将回顾平安人寿近期在PaperWeekly × Biendata直播间进行的主题为「SemEval-2020自由文本关系抽取冠军方案解读(附NLP竞赛常用技巧总结)」的技术分享,由平安人寿AI团队 ...

  7. 直播 | SemEval-2020自由文本关系抽取冠军方案解读(附NLP竞赛常用技巧总结)

    「PW Live」是由 PaperWeekly 和 biendata 共同发起的学术直播间,旨在帮助更多的青年学者宣传其最新科研成果.我们一直认为,单向地输出知识并不是一个最好的方式,而有效地反馈和交 ...

  8. 2020 ICDM 知识图谱竞赛获奖技术方案

    导读:ICDM(IEEE International Conference on Data Mining,简称ICDM)是数据挖掘领域的国际顶级会议.京东数科硅谷机器学习算法组朱翔宇带队在Knowle ...

  9. 如何加速大模型开发?技术方案拆解来了:昇思MindSpore技术一览

    随着人工智能爆火出圈,狂飙之势从22年底持续到23年初,与以往的技术突破不同的是,此次的大模型不仅被技术界关注,而且备受投资界.产业界和大众消费者的追捧,使它成为历史上最快月活过亿的现象级应用,继而引 ...

  10. php ajax mysql 分页查询_基于PHP_MySql_Ajax的分页技术方案

    一.引言 Ajax的全称是AsynchronousJavaScriptAndXML(异步JavaScript和XML),它不是一项新技术,而是很多成熟的技术的集合. 和Applet,Flash相比,A ...

最新文章

  1. Qt中文手册 之 QHeaderView
  2. win7关闭系统索引服务器,win7系统关闭磁盘索引功能的操作方法
  3. 编译器优化陷阱之典型代码
  4. windowswps怎么以文件形式发送_一个招投标项目出现了履约争议,但是没有签订合同,怎么办?...
  5. Python数据分析实战项目-共享单车骑行数据分析
  6. python算法应用(一)——提供推荐
  7. POJ PKU 2305 java大数进制转化 JAVA 大数转换成字符串 转
  8. oralce 存储过程、函数和触发器
  9. renameTo()方法的用法
  10. 画三线格子的高效方法,不用再一个格子一个格子的选中啦
  11. Nginx常用配置和使用详解梳理
  12. 信息论领域内的计算方法仿真,Mutual Information,互信息;
  13. MQTT-Eclipse paho mqtt源码分析-连接MQTT Broker
  14. IDEA中配置Vue启动Configurations
  15. 在线ASCII转换HEX
  16. 强生单剂新冠疫苗对“德尔塔”有效;赛诺菲巴斯德将每年投资4亿欧元建mRNA疫苗中心 | 美通社头条...
  17. SpringBoot上传图片问题
  18. 奥比中光astra 摄像头采集深度图和RGB图像(小白版)
  19. android 复制屏幕,iphone或者android的手机或者pad可以屏幕复制到Z1上了!
  20. 接入微信登录时返回errcode=-6

热门文章

  1. html什么布局可以兼容多平台,腾讯游戏:浅谈游戏官网现状及设计趋势
  2. 位置不可用无法访问介质受写入保护 chkdsk无法修复. 不知道怎样找到呢?
  3. 【支付】——毕业设计中利用websocket做模拟支付
  4. vs工程生成自定义图标的exe
  5. 【强化学习】动态规划
  6. 简洁高效的JQuery
  7. 手机图片转换成文字怎么办
  8. ubuntu更新时Not enough free disk space
  9. oracle 返回 xml解析,Oracle xmltable解析返回LPX-00209(Oracle xmltable parsing return LPX-00209)...
  10. BiTree T 和 Bitree T 和 BitNode *T 和 T-lchild