背景

如何设计一个比较两篇文章相似度的算法?可能你会回答几个比较传统点的思路:

  • 一种方案是先将两篇文章分别进行分词,得到一系列特征向量,然后计算特征向量之间的距离(可以计算它们之间的欧氏距离、海明距离或者夹角余弦等等),从而通过距离的大小来判断两篇文章的相似度。
  • 另外一种方案是传统hash,我们考虑为每一个web文档通过hash的方式生成一个指纹(finger print)。

下面,我们来分析下这两种方法。

  • 采取第一种方法,若是只比较两篇文章的相似性还好,但如果是海量数据呢,有着数以百万甚至亿万的网页,要求你计算这些网页的相似度。你还会去计算任意两个网页之间的距离或夹角余弦么?想必你不会了。
  • 而第二种方案中所说的传统加密方式md5,其设计的目的是为了让整个分布尽可能地均匀,但如果输入内容一旦出现哪怕轻微的变化,hash值就会发生很大的变化。

举个例子,我们假设有以下三段文本:

  • the cat sat on the mat
  • the cat sat on a mat
  • we all scream for ice cream

使用传统hash可能会得到如下的结果:

  • irb(main):006:0> p1 = 'the cat sat on the mat'

    • irb(main):007:0> p1.hash => 415542861
  • irb(main):005:0> p2 = 'the cat sat on a mat'
    • irb(main):007:0> p2.hash => 668720516
  • irb(main):007:0> p3 = 'we all scream for ice cream'
    • irb(main):007:0> p3.hash => 767429688 "

可理想当中的hash函数,需要对几乎相同的输入内容,产生相同或者相近的hash值,换言之,hash值的相似程度要能直接反映输入内容的相似程度,故md5等传统hash方法也无法满足我们的需求。

出世

车到山前必有路,来自于GoogleMoses Charikar发表的一篇论文“detecting near-duplicates for web crawling”中提出了simhash算法,专门用来解决亿万级别的网页的去重任务。

simhash作为locality sensitive hash(局部敏感哈希)的一种:

  • 其主要思想是降维,将高维的特征向量映射成低维的特征向量,通过两个向量的Hamming Distance来确定文章是否重复或者高度近似。

    • 其中,Hamming Distance,又称汉明距离,在信息论中,两个等长字符串之间的汉明距离是两个字符串对应位置的不同字符的个数。也就是说,它就是将一个字符串变换成另外一个字符串所需要替换的字符个数。例如:1011101 与 1001001 之间的汉明距离是 2。至于我们常说的字符串编辑距离则是一般形式的汉明距离。

如此,通过比较多个文档的simHash值的海明距离,可以获取它们的相似度。

流程

simhash算法分为5个步骤:分词、hash、加权、合并、降维,具体过程如下所述:

  • 分词

    • 给定一段语句,进行分词,得到有效的特征向量,然后为每一个特征向量设置1-5等5个级别的权重(如果是给定一个文本,那么特征向量可以是文本中的词,其权重可以是这个词出现的次数)。例如给定一段语句:“CSDN博客结构之法算法之道的作者July”,分词后为:“CSDN 博客 结构 之 法 算法 之 道 的 作者 July”,然后为每个特征向量赋予权值:CSDN(4) 博客(5) 结构(3) 之(1) 法(2) 算法(3) 之(1) 道(2) 的(1) 作者(5) July(5),其中括号里的数字代表这个单词在整条语句中的重要程度,数字越大代表越重要。
  • hash
    • 通过hash函数计算各个特征向量的hash值,hash值为二进制数01组成的n-bit签名。比如“CSDN”的hash值Hash(CSDN)为100101,“博客”的hash值Hash(博客)为“101011”。就这样,字符串就变成了一系列数字。
  • 加权
    • 在hash值的基础上,给所有特征向量进行加权,即W = Hash * weight,且遇到1则hash值和权值正相乘,遇到0则hash值和权值负相乘。例如给“CSDN”的hash值“100101”加权得到:W(CSDN) = 100101 4 = 4 -4 -4 4 -4 4,给“博客”的hash值“101011”加权得到:W(博客)=101011 5 = 5 -5 5 -5 5 5,其余特征向量类似此般操作。
  • 合并
    • 将上述各个特征向量的加权结果累加,变成只有一个序列串。拿前两个特征向量举例,例如“CSDN”的“4 -4 -4 4 -4 4”和“博客”的“5 -5 5 -5 5 5”进行累加,得到“4+5 -4+-5 -4+5 4+-5 -4+5 4+5”,得到“9 -9 1 -1 1”。
  • 降维
    • 对于n-bit签名的累加结果,如果大于0则置1,否则置0,从而得到该语句的simhash值,最后我们便可以根据不同语句simhash的海明距离来判断它们的相似度。例如把上面计算出来的“9 -9 1 -1 1 9”降维(某位大于0记为1,小于0记为0),得到的01串为:“1 0 1 0 1 1”,从而形成它们的simhash签名。

其流程如下图所示:

应用

  • 每篇文档得到SimHash签名值后,接着计算两个签名的海明距离即可。根据经验值,对64位的 SimHash值,海明距离在3以内的可认为相似度比较高。

    • 海明距离的求法:异或时,只有在两个比较的位不同时其结果是1 ,否则结果为0,两个二进制“异或”后得到1的个数即为海明距离的大小。

举个例子,上面我们计算到的“CSDN博客”的simhash签名值为“1 0 1 0 1 1”,假定我们计算出另外一个短语的签名值为“1 0 1 0 0 0”,那么根据异或规则,我们可以计算出这两个签名的海明距离为2,从而判定这两个短语的相似度是比较高的。

换言之,现在问题转换为:对于64位的SimHash值,我们只要找到海明距离在3以内的所有签名,即可找出所有相似的短语。

但关键是,如何将其扩展到海量数据呢?譬如如何在海量的样本库中查询与其海明距离在3以内的记录呢?

  • 一种方案是查找待查询文本的64位simhash code的所有3位以内变化的组合

    • 大约需要四万多次的查询。
  • 另一种方案是预生成库中所有样本simhash code的3位变化以内的组合
    • 大约需要占据4万多倍的原始空间。

这两种方案,要么时间复杂度高,要么空间复杂度复杂,能否有一种方案可以达到时空复杂度的绝佳平衡呢?答案是肯定的:

  • 我们可以把 64 位的二进制simhash签名均分成4块,每块16位。根据鸽巢原理(也称抽屉原理),如果两个签名的海明距离在 3 以内,它们必有一块完全相同。如下图所示:
  • 然后把分成的4 块中的每一个块分别作为前16位来进行查找,建倒排索引。

具体如下图所示:

如此,如果样本库中存有2^34(差不多10亿)的simhash签名,则每个table返回2^(34-16)=262144个候选结果,大大减少了海明距离的计算成本。

  • 假设数据是均匀分布,16位的数据,产生的像限为2^16个,则平均每个像限分布的文档数则为2^34/2^16 = 2^(34-16)) ,四个块返回的总结果数为 4* 262144 (大概 100 万)。

    • 这样,原本需要比较10亿次,经过索引后,大概只需要处理100万次。

1.SimHash适用于较长文本(大于三五百字)的相似性比较,文本越短,以3位阈值的误判率越高。
2.鸽巢原理将64位哈希值分为四组,形成四个整数。比较两个哈希值时,先比较各自形成的四个整数,如果这四个整数都不相等,就不用再计算Hamming距离了,因为它们的Hamming距离肯定大于3。由此来减少大样本比较时,相互间Hamming距离的计算量。

simhash算法原理相关推荐

  1. SimHash算法原理与应用(Java版)

    引言 项目中原使用的文本对比算法是使用MD5 Hash的方法.MD5 Hash算法简单来说是指对于任何长度的文本都可生成一段128bit长度的字符串,相同文本生成的Hash字符串是相同的,因此可用来比 ...

  2. Simhash算法及python实现

    1. 为什么需要Simhash? 传统相似度算法:文本相似度的计算,一般使用向量空间模型(VSM),先对文本分词,提取特征,根据特征建立文本向量,把文本之间相似度的计算转化为特征向量距离的计算,如欧式 ...

  3. hash地址_hash 算法原理及应用漫谈

    本文作者:jeffhe,腾讯 IEG 开发工程师 提到hash,相信大多数同学都不会陌生,之前很火现在也依旧很火的技术区块链背后的底层原理之一就是hash,下面就从hash算法的原理和实际应用等几个角 ...

  4. 基于局部敏感哈希的协同过滤算法之simHash算法

    搜集了快一个月的资料,虽然不完全懂,但还是先慢慢写着吧,说不定就有思路了呢. 开源的最大好处是会让作者对脏乱臭的代码有羞耻感. 当一个做推荐系统的部门开始重视[数据清理,数据标柱,效果评测,数据统计, ...

  5. 文本相似度计算——Simhash算法(python实现)

    互联网网页存在着大量重复内容,必须有一套高效的去重算法,否则爬虫将做非常多的无用功,工作时效性无法得到保证,更重要的是用户体验也不好.业界关于文本指纹去重的算法众多,如 k-shingle 算法.go ...

  6. 海量数据去重之SimHash算法简介和应用

    SimHash是什么 SimHash是Google在2007年发表的论文<Detecting Near-Duplicates for Web Crawling >中提到的一种指纹生成算法或 ...

  7. python文章抄袭检测_用Python写了个检测文章抄袭,详谈去重算法原理

    在互联网出现之前,"抄"很不方便,一是"源"少,而是发布渠道少:而在互联网出现之后,"抄"变得很简单,铺天盖地的"源"源 ...

  8. Python检测文章抄袭,谈谈去重算法原理

    中文内容新闻网站的"转载"(其实就是抄)现象非常严重,这种"转载"几乎是全文照抄,或改下标题,或是改下编辑姓名,或是文字个别字修改.所以,对新闻网页的去重很有必 ...

  9. python文件去重算法_使用Python检测文章抄袭及去重算法原理解析

    在互联网出现之前,"抄"很不方便,一是"源"少,而是发布渠道少:而在互联网出现之后,"抄"变得很简单,铺天盖地的"源"源 ...

最新文章

  1. 在MasterPage下FindControl的使用方法
  2. 用Cython加速Python代码,快到起飞!
  3. sketch钢笔工具_设计工具(Sketch,Adobe XD,Figma和InVision Studio)中奇怪的一项功能
  4. 第五章 了解你的用户
  5. Python Ctypes结构体指针处理(函数参数,函数返回)
  6. CSS之创建等高列布局之二
  7. linux下设置oracle开机自启动
  8. Linux as 5 下部署oracle 10.2.0.1(2)
  9. BMVC2018图像检索论文—使用区域注意力网络改进R-MAC方法
  10. JS实现 EventBus
  11. 孩子哭的时候大人应该怎么办?
  12. KVM虚拟化下使用virsh shutdown命令无法关闭windows
  13. java读取文件到字符串_Java读取文件到字符串
  14. 提交太多oracle,急!!请教 用文本域向数据库oracle提交不了太多文字如何解决??...
  15. htc328d屏幕排线怎么换_详细的HTC T328D一键解锁教程(图文)
  16. zscore标准化步骤_几种常用数据标准化方法
  17. 关于计算机知识的动画电影,动画概论总复习题目(附答案)
  18. 从零开始玩转Franka Panda机器人
  19. 【基础框架-SSM】Maven_进阶
  20. matlab抢占时隙算法,基于公平性的D2D时隙调度算法

热门文章

  1. 软件测试为什么要学python,资讯详情-用excel不好吗?为什么还要学python?-柠檬班-自动化测试-软件测试培训-自学官网...
  2. Microsoft Remote Desktop提示「Your session was disconnected」
  3. 微信小程序scroll-view实现滚动卡片
  4. 五子棋游戏AI智能算法设计
  5. Stacked Attention Networks for Image Question Answering(用于图像问答的堆叠注意力网络)
  6. “Derivative of state ‘1‘ in block ‘X/Y/Integrator‘ at time 0.55 is not finite“类问题解决办法
  7. 系统集成十大项目管理(1)
  8. app上架360手机助手流程
  9. 对接顺丰(丰桥)查询物流信息
  10. python排名差怎么改,2017中国大学排名爬虫代码修改