海量数据相似度计算之simhash短文本查找
在前一篇文章 《海量数据相似度计算之simhash和海明距离》 介绍了simhash的原理,大家应该感觉到了算法的魅力。但是随着业务的增长 simhash的数据也会暴增,如果一天100w,10天就1000w了。我们如果插入一条数据就要去比较1000w次的simhash,计算量还是蛮大,普通PC 比较1000w次海明距离需要 300ms ,和5000w数据比较需要1.8 s。看起来相似度计算不是很慢,还在秒级别。给大家算一笔账就知道了:
随着业务增长需要一个小时处理100w次,一个小时为3600 *1000 = 360w毫秒,计算一下一次相似度比较最多只能消耗 360w / 100w = 3.6毫秒。300ms慢吗,慢!1.8S慢吗,太慢了!很多情况大家想的就是升级、增加机器,但有些时候光是增加机器已经解决不了问题了,就算增加机器也不是短时间能够解决的,需要考虑分布式、客户预算、问题解决的容忍时间?头大时候要相信人类的智慧是无穷的,泡杯茶,听下轻音乐:)畅想下宇宙有多大,宇宙外面还有什么东西,程序员有什么问题能够难倒呢?
加上客户还提出的几个,汇总一下技术问题:
- 1、一个小时需要比较100w次,也就是每条数据和simhash库里的数据比较需要做到3.6毫秒。
- 2、两条同一时刻发出的文本如果重复也只能保留一条。
- 3、希望保留2天的数据进行比较去重,按照目前的量级和未来的增长,2天大概在2000w — 5000w 中间。
- 4、短文本和长文本都要去重,经过测试长文本使用simhash效果很好,短文本使用simhash 准备度不高。
目前我们估算一下存储空间的大小,就以JAVA 来说,存储一个simhash 需要一个原生态 lang 类型是64位 = 8 byte,如果是 Object 对象还需要额外的 8 byte,所以我们尽量节约空间使用原生态的lang类型。假设增长到最大的5000w数据, 5000w * 8byte = 400000000byte = 400000000/( 1024 * 1024) = 382 Mb,所以按照这个大小普通PC服务器就可以支持,这样第三个问题就解决了。
比较5000w次怎么减少时间呢?其实这也是一个查找的过程,我们想想以前学过的查找算法: 顺序查找、二分查找、二叉排序树查找、索引查找、哈希查找。不过我们这个不是比较数字是否相同,而是比较海明距离,以前的算法并不怎么通用,不过解决问题的过程都是通用的。还是和以前一样,不使用数学公式,使用程序猿大家都理解的方式。还记得JAVA里有个HashMap吗?我们要查找一个key值时,通过传入一个key就可以很快的返回一个value,这个号称查找速度最快的数据结构是如何实现的呢?看下hashmap的内部结构:

如果我们需要得到key对应的value,需要经过这些计算,传入key,计算key的hashcode,得到7的位置;发现7位置对应的value还有好几个,就通过链表查找,直到找到v72。其实通过这么分析,如果我们的hashcode设置的不够好,hashmap的效率也不见得高。借鉴这个算法,来设计我们的simhash查找。通过顺序查找肯定是不行的,能否像hashmap一样先通过键值对的方式减少顺序比较的次数。看下图:

存储:
1、将一个64位的simhash code拆分成4个16位的二进制码。(图上红色的16位)
2、分别拿着4个16位二进制码查找当前对应位置上是否有元素。(放大后的16位)
3、对应位置没有元素,直接追加到链表上;对应位置有则直接追加到链表尾端。(图上的 S1 — SN)
查找:
1、将需要比较的simhash code拆分成4个16位的二进制码。
2、分别拿着4个16位二进制码每一个去查找simhash集合对应位置上是否有元素。
2、如果有元素,则把链表拿出来顺序查找比较,直到simhash小于一定大小的值,整个过程完成。
原理:
借鉴hashmap算法找出可以hash的key值,因为我们使用的simhash是局部敏感哈希,这个算法的特点是只要相似的字符串只有个别的位数是有差别变化。那这样我们可以推断两个相似的文本,至少有16位的simhash是一样的。具体选择16位、8位、4位,大家根据自己的数据测试选择,虽然比较的位数越小越精准,但是空间会变大。分为4个16位段的存储空间是单独simhash存储空间的4倍。之前算出5000w数据是 382 Mb,扩大4倍1.5G左右,还可以接受:)
通过这样计算,我们的simhash查找过程全部降到了1毫秒以下。就加了一个hash效果这么厉害?我们可以算一下,原来是5000w次顺序比较,现在是少了2的16次方比较,前面16位变成了hash查找。后面的顺序比较的个数是多少? 2^16 = 65536, 5000w/65536 = 763 次。。。。实际最后链表比较的数据也才 763次!所以效率大大提高!
到目前第一点降到3.6毫秒、支持5000w数据相似度比较做完了。还有第二点同一时刻发出的文本如果重复也只能保留一条和短文本相识度比较怎么解决。其实上面的问题解决了,这两个就不是什么问题了。
- 之前的评估一直都是按照线性计算来估计的,就算有多线程提交相似度计算比较,我们提供相似度计算服务器也需要线性计算。比如同时客户端发送过来两条需要比较相似度的请求,在服务器这边都进行了一个排队处理,一个接着一个,第一个处理完了在处理第二个,等到第一个处理完了也就加入了simhash库。所以只要服务端加了队列,就不存在同时请求不能判断的情况。
- simhash如何处理短文本?换一种思路,simhash可以作为局部敏感哈希第一次计算缩小整个比较的范围,等到我们只有比较700多次比较时,就算使用我们之前精准度高计算很慢的编辑距离也可以搞定。当然如果觉得慢了,也可以使用余弦夹角等效率稍微高点的相似度算法。
参考:
我的数学之美系列二 —— simhash与重复信息识别
原创文章,转载请注明: 转载自LANCEYAN.COM
本文链接地址: 海量数据相似度计算之simhash短文本查找
海量数据相似度计算之simhash短文本查找的更多相关文章
- 海量数据相似度计算之simhash和海明距离
通过 采集系统 我们采集了大量文本数据,但是文本中有很多重复数据影响我们对于结果的分析.分析前我们需要对这些数据去除重复,如何选择和设计文本的去重算法?常见的有余弦夹角算法.欧式距离.Jaccard相 ...
- LSF-SCNN:一种基于 CNN 的短文本表达模型及相似度计算的全新优化模型
欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 本篇文章是我在读期间,对自然语言处理中的文本相似度问题研究取得的一点小成果.如果你对自然语言处理 (natural language proc ...
- 使用 TF-IDF 加权的空间向量模型实现句子相似度计算
使用 TF-IDF 加权的空间向量模型实现句子相似度计算 字符匹配层次计算句子相似度 计算两个句子相似度的算法有很多种,但是对于从未了解过这方面算法的人来说,可能最容易想到的就是使用字符串匹配相关的算 ...
- 皮尔逊相似度计算的例子(R语言)
编译最近的协同过滤算法皮尔逊相似度计算.下顺便研究R简单使用的语言.概率统计知识. 一.概率论和统计学概念复习 1)期望值(Expected Value) 由于这里每一个数都是等概率的.所以就当做是数 ...
- 图像相似度计算之哈希值方法OpenCV实现
http://blog.csdn.net/fengbingchun/article/details/42153261 图像相似度计算之哈希值方法OpenCV实现 2014-12-25 21:27 29 ...
- java实现 比较两个文本相似度-- java 中文版 simHash 实现 ,
比较两个文本的相似度 这里采用 simHash 算法 ; 分词是 基于 http://hanlp.linrunsoft.com/ 的开源 中文分词包 来实现分词 ; 实现效果图: 直接上源码: htt ...
- Go 实现字符串相似度计算函数 Levenshtein 和 SimilarText
[转]http://www.syyong.com/Go/Go-implements-the-string-similarity-calculation-function-Levenshtein-and ...
- 皮尔森相似度计算举例(R语言)
整理了一下最近对协同过滤推荐算法中的皮尔森相似度计算,顺带学习了下R语言的简单使用,也复习了概率统计知识. 一.概率论和统计学概念复习 1)期望值(Expected Value) 因为这里每个数都是等 ...
- java算法(1)---余弦相似度计算字符串相似率
余弦相似度计算字符串相似率 功能需求:最近在做通过爬虫技术去爬取各大相关网站的新闻,储存到公司数据中.这里面就有一个技术点,就是如何保证你已爬取的新闻,再有相似的新闻 或者一样的新闻,那就不存储到数据 ...
随机推荐
- 4、C#进阶:MD5加密、进程、线程、GDI+、XML、委托
MD5加密 将字符串进行加密,无法解密.网上的解密方式也都是在库里找,找不到也没有. 1 protected void Page_Load(object sender, EventArgs e) 2 ...
- Java的基本程序设计结构(上)
在Java中,每一个变量属于一种类型(type).在声明变量时,变量所属的类型位于变量名之前. 例如: double salary; int vacationDays; long earthPopul ...
- Objective - C - 添加类目 - NSDate
1.类目为系统内部的类或者是没有源代码的类添加方法,不有添加实例变量 2.添加的方法会成为原类的一部分,子类照样可以使用 3.类目的文件名为原类名+文件名 4.既可以添加实例方法,也可以添加类方法 X ...
- Eclipse编程时的快捷键总结
" alt + / " 快捷键是代码补全功能 输入" syso alt + / "会自动补全成System.out.println();
- xcode调试技巧
xode报错有时挺无厘头,完全不知道哪里出的问题,最后还得用排除法,记录一些工作中认为有用的调试技巧 1.左侧视图点断点视图,左下角点加号,选择exception breakpoint,类型选c++, ...
- jquery 使用方法(一)
jquery是什麼? jquery,顾名思义,也就是JavaScript和查询(Query),即是辅助JavaScript开发的函數库. javascript是屬於網絡的腳本語言,宿主文件是html, ...
- genymotion启动虚拟机遇到问题解决方法步骤
通过在不做任务设置时启动genymotion,会遇到一些问题: 会弹出类似如下问题: 要解决这样问题,首先要知道是什么问题,一般按提示在VitualBox中启动虚拟机就可以知道是什么问题. “To f ...
- WCF启用日志追踪
调用使用http post调用WCF Restful服务时,WCF会自动反序列化body里的实体,如果实体反序列化不成功时,会返回一个请求错误,让去看服务器日志.需要启用日志追踪功能,才能看到具体的情 ...
- linux学习4 网络命令和关机重启
网络命令 write write 用户名 回车后输入信息 以 ctrl+d 保存结束 wall wall [message] //that is all,发送给所有人 ping ping 选项 IP地 ...
- CSS的两大重点
一.属性:通过属性的复杂叠加才能做出漂亮的网页 二.选择器:通过选择器找到对应的标签设置样式,选择器的作用是:选择对应的标签,为之添加样式 1>标签选择器:根据标签签名找到标签 div{ ...