1 前言
最简单的检测重复网页的方法就是对每一个网页计算用指纹生成算法出一个简洁的“指纹”。接着,当两个网页的“指纹”一样时,我们就进一步地去比对它们的网页内容是否一样,但是这个最简单的办法在捕捉“相似的副本”方面是失败的。在许多情况下,一个网页只有几个字符与另一个网页不同——比如一篇文章最后落款的日期不同,但是文章内容完全一致。面对这种情况,我们就要去识别两个网页之间的相似度来让我们只需检索其中一个网页。
2 直接计算Jaccard系数的shingling算法
首先给定一个正整数k,和文档d。我们定义“the k-shingle of d”为“文档d中所有长度为k的连续词序列”,例如:
文档d: "a rose is a rose is a rose"
the 4-shingle of d(k=4是在文档相似度检测方面比较经典的值):(a rose is a)、(rose is a rose)、(is a rose is)。其中前两个shingle(小瓦片)都出现了两次。
很直观地,两个文档的shingle集合很接近,那么它们也就是相似的。但是我们想要更精确,然后就发展出了一种高效计算和比对互联网上所有网页的方法,那就是我们令S(dj)为文档dj的shingle集合;J(S(d1),S(d2))为两个文档的shingle集的Jaccard系数(交集 / 并集),我们用这个Jaccard系数作为两个网页之间的相似度,假如这个相似度大于一阈值(比如0.9),我们就将它们判定为相似网页。
3 MinHash估计Jaccard系数的shingling算法
上一部分所述的直接计算两个文档的shingle集的jaccard系数虽然精确,但是通常一个文档可以分出上千个shingle,两个文档放一起计算jaccard系数需要逐一比对shingle,计算量会很大,更别说去和互联网上大量的网页去比对。所以,用MinHash来估计jaccard系数的方法被提出。该方法基于一个结论:
J(S(d1),S(d2))=P(x1=x2)
即两个集合的jaccard系数等于两个集合的MinHash值相等的概率。该算法流程如下:
(1)用n个哈希函数来哈希S(d1),S(d2)得到哈希集H(d1),H(d2);
(2)用每次hash过程后的哈希序列第一个哈希值用来表示该集合;
(3)n次hash后,每个文档都会生成一个n维的“签名”,两个n维签名序列间对应相等的个数(可以用Hamming Distance来计算)就是Jaccard的估计值。
原来计算Jaccard系数每一个shingle都要逐一比对另一文档的所有shingle,计算量非常之大,现在只需比对对应位置的数值,比对n次,用一个概率来估计这个Jaccard系数,实现了文档特征向量的降维。