首页IT科技java hmacsha算法(Simhash算法原理和网页查重应用)

java hmacsha算法(Simhash算法原理和网页查重应用)

时间2025-09-17 12:01:59分类IT科技浏览9383
导读:传统的hash算法只负责将原始内容尽量均匀随机地映射为一个签名值,原理上相当于伪随机数产生算法。产生的两个签名,如果相等,说明原始内容在一定概率下是相等的;如果不相等,除了说明原始内容不相等外,不再提供任何信息,因为即使原始内容只相差一个字节,所产生的签名也很可能差别极大。从这个意义上来说,要设计一个h...

传统的hash算法只负责将原始内容尽量均匀随机地映射为一个签名值                  ,原理上相当于伪随机数产生算法                 。产生的两个签名                         ,如果相等        ,说明原始内容在一定概率下是相等的;如果不相等                  ,除了说明原始内容不相等外                          ,不再提供任何信息        ,因为即使原始内容只相差一个字节         ,所产生的签名也很可能差别极大                          。从这个意义上来说                          ,要设计一个hash算法                 ,对相似的内容产生的签名也相近         ,是更为艰难的任务                          ,因为它的签名值除了提供原始内容是否相等的信息外                 ,还能额外提供不相等的原始内容的差异程度的信息        。

而Google的simhash算法产生的签名,可以用来比较原始内容的相似度时                          ,便很想了解这种神奇的算法的原理         。出人意料                         ,这个算法并不深奥,其思想是非常清澈美妙的                          。

Simhash算法

simhash算法的输入是一个向量                  ,输出是一个f位的签名值                 。为了陈述方便                         ,假设输入的是一个文档的特征集合        ,每个特征有一定的权重         。比如特征可以是文档中的词                  ,其权重可以是这个词出现的次数                          。simhash算法如下:

1                          ,将一个f维的向量V初始化为0;f位的二进制数S初始化为0;

2        ,对每一个特征:用传统的hash算法对该特征产生一个f位的签名b                 。对i=1到f:

如果b的第i位为1         ,则V的第i个元素加上该特征的权重;

否则                          ,V的第i个元素减去该特征的权重。

3                 ,如果V的第i个元素大于0         ,则S的第i位为1                          ,否则为0;

4                 ,输出S作为签名                          。

算法几何意义和原理

这个算法的几何意义非常明了                          。它首先将每一个特征映射为f维空间的一个向量,这个映射规则具体是怎样并不重要                          ,只要对很多不同的特征来说                         ,它们对所对应的向量是均匀随机分布的,并且对相同的特征来说对应的向量是唯一的就行。比如一个特征的4位hash签名的二进制表示为1010                  ,那么这个特征对应的

4维向量就是(1, -1, 1,

-1)T                         ,即hash签名的某一位为1        ,映射到的向量的对应位就为1                  ,否则为-1                 。然后                          ,将一个文档中所包含的各个特征对应的向量加权求和        ,加权的系数等于该特征的权重                          。得到的和向量即表征了这个文档         ,我们可以用向量之间的夹角来衡量对应文档之间的相似度        。最后                          ,为了得到一个f位的签名                 ,需要进一步将其压缩         ,如果和向量的某一维大于0                          ,则最终签名的对应位为1                 ,否则为0                 。这样的压缩相当于只留下了和向量所在的象限这个信息,而64位的签名可以表示多达264个象限                          ,因此只保存所在象限的信息也足够表征一个文档了                          。

明确了算法了几何意义                         ,使这个算法直观上看来是合理的        。但是,为何最终得到的签名相近的程度                  ,可以衡量原始文档的相似程度呢?这需要一个清晰的思路和证明         。在simhash的发明人Charikar的论文中[2]并没有给出具体的simhash算法和证明                         ,以下列出我自己得出的证明思路                          。

Simhash是由随机超平面hash算法演变而来的        ,随机超平面hash算法非常简单                  ,对于一个n维向量v                          ,要得到一个f位的签名(f<<n)        ,算法如下:

1         ,随机产生f个n维的向量r1,…rf;

2                          ,对每一个向量ri                 ,如果v与ri的点积大于0         ,则最终签名的第i位为1                          ,否则为0.

这个算法相当于随机产生了f个n维超平面                 ,每个超平面将向量v所在的空间一分为二,v在这个超平面上方则得到一个1                          ,否则得到一个0                         ,然后将得到的

f个0或1组合起来成为一个f维的签名                 。如果两个向量u, v的夹角为θ,则一个随机超平面将它们分开的概率为θ/π                  ,因此u,

v的签名的对应位不同的概率等于θ/π         。所以                         ,我们可以用两个向量的签名的不同的对应位的数量        ,即汉明距离                  ,来衡量这两个向量的差异程度                          。

Simhash算法与随机超平面hash是怎么联系起来的呢?在simhash算法中                          ,并没有直接产生用于分割空间的随机向量        ,而是间接产生的:第

k个特征的hash签名的第i位拿出来         ,如果为0                          ,则改为-1                 ,如果为1则不变         ,作为第i个随机向量的第k维                 。由于hash签名是f位的                          ,因此这样能产生

f个随机向量                 ,对应f个随机超平面。下面举个例子:

假设用5个特征w1,…,w5来表示所有文档,现要得到任意文档的一个3维签名                          。假设这5个特征对应的3维向量分别为:

h(w1) = (1, -1, 1)T

h(w2) = (-1, 1, 1)T

h(w3) = (1, -1, -1)T

h(w4) = (-1, -1, 1)T

h(w5) = (1, 1, -1)T

按simhash算法                          ,要得到一个文档向量d=(w1=1, w2=2, w3=0, w4=3, w5=0)

T的签名                         ,

先要计算向量m = 1*h(w1) + 2*h(w2) + 0*h(w3) + 3*h(w4) + 0*h(w5) = (-4,

-2, 6) T,

然后根据simhash算法的步骤3                  ,得到最终的签名s=001                          。

上面的计算步骤其实相当于                         ,先得到3个5维的向量        ,第1个向量由h(w1),…,h(w5)的第1维组成:

r1=(1,-1,1,-1,1) T;

第2个5维向量由h(w1),…,h(w5)的第2维组成:

r2=(-1,1,-1,-1,1) T;

同理                  ,第3个5维向量为:

r3=(1,1,-1,1,-1) T.

按随机超平面算法的步骤2                          ,分别求向量d与r1,r2,r3的点积:

d T r1=-4 < 0        ,所以s1=0;

d T r2=-2 < 0         ,所以s2=0;

d T r3=6 > 0                          ,所以s3=1.

故最终的签名s=001                 ,与simhash算法产生的结果是一致的。

从上面的计算过程可以看出         ,simhash算法其实与随机超平面hash算法是相同的                          ,simhash算法得到的两个签名的汉明距离                 ,可以用来衡量原始向量的夹角                 。这其实是一种降维技术,将高维的向量用较低维度的签名来表征                          。衡量两个内容相似度                          ,需要计算汉明距离                         ,这对给定签名查找相似内容的应用来说带来了一些计算上的困难;我想,是否存在更为理想的simhash算法                  ,原始内容的差异度                         ,可以直接由签名值的代数差来表示呢?

大规模网页的近似查重

详细内容可以看WWW07的 Detecting Near-Duplicates

for Web Crawling        。

例如        ,文本的特征可以选取分词结果                  ,而权重可以用df来近似                 。

Simhash具有两个“冲突的性质                 ”:

1. 它是一个hash方法

2. 相似的文本具有相似的hash值                          ,如果两个文本的simhash越接近        ,也就是汉明距离越小         ,文本就越相似                          。

因此海量文本中查重的任务转换位如何在海量simhash中快速确定是否存在汉明距离小的指纹        。也就是:在n个f-bit的指纹中                          ,查询汉明距离小于k的指纹         。

在文章的实验中                 ,simhash采用64位的哈希函数                          。在80亿网页规模下汉明距离=3刚好合适                 。

因此任务的f-bit=64 , k=3 , n= 8*10^11

任务清晰         ,首先看一下两种很直观的方法:

1.

枚举出所有汉明距离小于3的simhash指纹                          ,对每个指纹在80亿排序指纹中查询         。(这种方法需要进行C(64                 ,3)=41664词的simhash指纹,再为每个进行一次查询)

2.

所有接近的指纹排序到一起                          ,这至多有41664排序可能                         ,需要庞大的空间                          。提出的方法介于两者之间,合理的空间和时间的折中                 。

假设我们有一个已经排序的容量为2d                  ,f-bit指纹集。看每个指纹的高d位                          。该高低位具有以下性质:尽管有很多的2d位组合存在                         ,但高d位中有只有少量重复的                          。

现在找一个接近于d的数字d’        ,由于整个表是排好序的                  ,所以一趟搜索就能找出高d’位与目标指纹F相同的指纹集合f’。因为d’和d很接近                          ,所以找出的集合f’也不会很大                 。

• 最后在集合f’中查找 和F之间海明距离为k的指纹也就很快了                          。

• 总的思想:先要把检索的集合缩小        ,然后在小集合中检索f-d’位的海明距离

按照例子         ,80亿网页 有2^34

个                          ,那么理论上34位就能表示完80亿不重复的指纹        。我们假设最前的34位的表示完了80亿指纹                 ,假设指纹在前30位是一样的         ,那么后面4位还可以表示24个                          ,

只需要逐一比较这16个指纹是否于待测指纹汉明距离小于3                 。

假设:对任意34位中的30位都可以这么做                          。

因此在一次完整的查找中                 ,限定前q位精确匹配(假设这些指纹已经是q位有序的,可以采用二分查找                          ,如果指纹量非常大                         ,且分布均匀,甚至可以采用内插搜索)                  ,之后的2d-q个指纹剩下64-q位需要比较汉明距离小于3        。

于是问题就转变为如何切割64位的q         。

将64位平分成若干份                         ,例如4份ABCD        ,每份16位                          。

假设这些指纹已经按A部分排序好了                  ,我们先按A的16位精确匹配到一个区间                          ,这个区间的后BCD位检查汉明距离是否小于3                 。

同样的假设        ,其次我们按B的16位精确匹配到另一个区间         ,这个区间的所有指纹需要在ACD位上比较汉明距离是否小于3         。

同理还有C和D

所以这里我们需要将全部的指纹T复制4份                          , T1 T2 T3 T4                 , T1按A排序         ,T2按B排序…

4份可以并行进行查询                          ,最后把结果合并                          。这样即使最坏的情况:3个位分别落在其中3个区域ABC,ACD,BCD,ABD…都不会被漏掉                 。

只精确匹配16位                 ,还需要逐一比较的指纹量依然庞大,可能达到2d-16个                          ,我们也可以精确匹配更多的。

例如:将64位平分成4份ABCD                         ,每份16位,在BCD的48位上                  ,我们再分成4份                         ,WXZY        ,每份12位                  ,

汉明距离的3位可以散落在任意三块                          ,那么A与WXZY任意一份合起来做精确的28位…剩下3份用来检查汉明距离                          。

同理B        ,C         ,D也可以这样                          ,那么T需要复制16次                 ,ABCD与WXYZ的组合做精确匹配         ,每次精确匹配后还需要逐一比较的个数降低到2d-28个                          。不同的组合方式也就是时间和空间上的权衡。

最坏情况是其中3份可能有1位汉明距离差异为1                 。

算法的描述如下:

1)先复制原表T为Tt份:T1,T2,….Tt

2)每个Ti都关联一个pi和一个πi                          ,其中pi是一个整数, πi是一个置换函数                 ,负责把pi个bit位换到高位上                          。

3)应用置换函数πi到相应的Ti表上,然后对Ti进行排序

4)然后对每一个Ti和要匹配的指纹F                  、海明距离k做如下运算:

a) 然后使用F’的高pi位检索                          ,找出Ti中高pi位相同的集合

b) 在检索出的集合中比较f-pi位                         ,找出海明距离小于等于k的指纹

5)最后合并所有Ti中检索出的结果

由于文本已经压缩成8个字节了,因此其实Simhash近似查重精度并不高:

附参考文献:

[1] Detecting near-duplicates for web crawling.

[2] Similarity estimation techniques from rounding

algorithms.

[3] http://en.wikipedia.org/wiki/Locality_sensitive_hashing

[4] http://www.coolsnap.net/kevin/?p=23

[5] http://www.cnblogs.com/linecong/archive/2010/08/28/simhash.html

[6] http://blog.csdn.net/lgnlgn/article/details/6008498

博主注:本文主要就是拼接了参考文献[5][6]而成        。

声明:本站所有文章                  ,如无特殊说明或标注                         ,均为本站原创发布                 。任何个人或组织        ,在未征得本站同意时                  ,禁止复制                         、盗用        、采集                  、发布本站内容到任何网站                          、书籍等各类媒体平台                          。如若本站内容侵犯了原著者的合法权益                          ,可联系我们进行处理        。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
flutter apns(Mac系统下Flutter安装教程) 介绍几款开源博客系统(Typecho:轻量级开源博客平台)