在前一篇文章 《海量数据相似度计算之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短文本查找的更多相关文章

  1. 海量数据相似度计算之simhash和海明距离

    通过 采集系统 我们采集了大量文本数据,但是文本中有很多重复数据影响我们对于结果的分析.分析前我们需要对这些数据去除重复,如何选择和设计文本的去重算法?常见的有余弦夹角算法.欧式距离.Jaccard相 ...

  2. LSF-SCNN:一种基于 CNN 的短文本表达模型及相似度计算的全新优化模型

    欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 本篇文章是我在读期间,对自然语言处理中的文本相似度问题研究取得的一点小成果.如果你对自然语言处理 (natural language proc ...

  3. 使用 TF-IDF 加权的空间向量模型实现句子相似度计算

    使用 TF-IDF 加权的空间向量模型实现句子相似度计算 字符匹配层次计算句子相似度 计算两个句子相似度的算法有很多种,但是对于从未了解过这方面算法的人来说,可能最容易想到的就是使用字符串匹配相关的算 ...

  4. 皮尔逊相似度计算的例子(R语言)

    编译最近的协同过滤算法皮尔逊相似度计算.下顺便研究R简单使用的语言.概率统计知识. 一.概率论和统计学概念复习 1)期望值(Expected Value) 由于这里每一个数都是等概率的.所以就当做是数 ...

  5. 图像相似度计算之哈希值方法OpenCV实现

    http://blog.csdn.net/fengbingchun/article/details/42153261 图像相似度计算之哈希值方法OpenCV实现 2014-12-25 21:27 29 ...

  6. java实现 比较两个文本相似度-- java 中文版 simHash 实现 ,

    比较两个文本的相似度 这里采用 simHash 算法 ; 分词是 基于 http://hanlp.linrunsoft.com/ 的开源 中文分词包 来实现分词 ; 实现效果图: 直接上源码: htt ...

  7. Go 实现字符串相似度计算函数 Levenshtein 和 SimilarText

    [转]http://www.syyong.com/Go/Go-implements-the-string-similarity-calculation-function-Levenshtein-and ...

  8. 皮尔森相似度计算举例(R语言)

    整理了一下最近对协同过滤推荐算法中的皮尔森相似度计算,顺带学习了下R语言的简单使用,也复习了概率统计知识. 一.概率论和统计学概念复习 1)期望值(Expected Value) 因为这里每个数都是等 ...

  9. java算法(1)---余弦相似度计算字符串相似率

    余弦相似度计算字符串相似率 功能需求:最近在做通过爬虫技术去爬取各大相关网站的新闻,储存到公司数据中.这里面就有一个技术点,就是如何保证你已爬取的新闻,再有相似的新闻 或者一样的新闻,那就不存储到数据 ...

随机推荐

  1. xhprof学习笔记

    一.简介 XHProf 是一个轻量级的分层性能测量分析器. 在数据收集阶段,它跟踪调用次数与测量数据,展示程序动态调用的弧线图. 它在报告.后期处理阶段计算了独占的性能度量,例如运行经过的时间.CPU ...

  2. ODAC ,MYDAC版本问题

    已确定D7下,ODAC.v6.80.0.47  和 MyDACv5.80.0.47  可以一起用

  3. genymotion启动虚拟机遇到问题解决方法步骤

    通过在不做任务设置时启动genymotion,会遇到一些问题: 会弹出类似如下问题: 要解决这样问题,首先要知道是什么问题,一般按提示在VitualBox中启动虚拟机就可以知道是什么问题. “To f ...

  4. C#实现控制Windows系统关机、重启和注销的方法:

    shutdown命令的参数: shutdown.exe -s:关机shutdown.exe -r:关机并重启shutdown.exe -l:注销当前用户 shutdown.exe -s -t 时间:设 ...

  5. GridView控件RowDataBound事件中获取列字段途径

    今天不知道怎么回事怎么也找不到gridview列中的控件,关键是其为编辑时隐藏域中的控件,取值就很成问题了,网上搜了很到,找到这个比较经典的东东了,可能大家都知道,但很少对比整理到一起,有多种方法可以 ...

  6. UICollectionReusableView 使用时的一些问题

    在使用UICollectionView 时, 设置分区头时, - (UICollectionReusableView *)collectionView:(UICollectionView *)coll ...

  7. 驱动学习---PAE--virtual address to physics address

    PAE是Physical Address Extension的缩写,即物理地址扩展.简单来说,就是把IA-32处理器的寻址能力从原来的4GB扩展到64GB.寻址4GB空间,要求物理地址的宽度为32位. ...

  8. win7不能在同一窗口打开文件夹,如何解决

    regsvr32 "%SystemRoot%\System32\actxprxy.dll"

  9. python-基础介绍

    一.Linux基础 - 计算机以及日后我们开发的程序防止的服务器的简单操作 二.Python开发 http://www.cnblogs.com/wupeiqi/articles/5433893.htm ...

  10. hihoCoder #1199 : Tower Defense Game ——(树型dp)

    题目链接:https://hihocoder.com/problemset/problem/1199. 题意:一棵以1为根的树,每个点有一个p值和q值,到这个点需要当前分数大于等于p,然后消耗掉(p- ...