转自http://hi.baidu.com/dobit/blog/item/87ef4eed8701c92d62d09f2b.html
1.信息指纹算法
判断重复网页的思想:为每个网页计算出一组信息指纹(Fingerprint),若两个网页有一定数量相同的信息指纹,则认为这两个网页的内容重叠性很高,也就是说两个网页是内容复制的。
判断内容复制的方法中最关键的两点:
1、计算信息指纹(Fingerprint)的算法;
2、判断信息指纹的相似程度的参数。
信息指纹就是提取网页正文信息的特征,通常是一组词或者一组词+权重,然后根据这组词调用特别的算法,例如MD5,将之转化为一组代码,这组代码就成为标识这个信息的指纹。从理论上讲,每两个不同文本的特征信息是不同的,那么得到的代码也应该是不一样的,就象人的指纹。
得到预处理后的网页,然后对网页进行向量化处理,简单的讲就是分词,统计,并按照词频生成一个列表.
例如:
网页12
搜索10
引擎7
...
...
然后取前N个关键词作为信息的矢量,例如:[网页 12搜索10引擎7] 这是可以直接进行MD5哈系,或者按照其它规则进行重排后进行MD5哈系。例如本例,取前3个关键词,再进行哈希,得到的信息指纹就是:a7eb9d92a83cf438881915e0bc2df70b。这样a7eb9d92a83cf438881915e0bc2df70b 就作为本文档的指纹和以往的文档进行比较,如果有相同的,就说明指纹上看是一样的,就可以进入消重处理。至于关键词的权重,因为有众多的提取算法,比较常用的是nf/df。
2.分段签名算法
这种算法是按照一定的规则把网页切成N段,对每一段进行签名,形成每一段的信息指纹。如果这N个信息指纹里面有M个相同时(M是系统定义的阈值),则认为两者是复制网页。这种算法对于小规模的判断复制网页是很好的一种算法,但是对于像google这样海量的搜索引擎来说,算法的复杂度相当高。
3.基于关键词的复制网页算法
像google这类搜索引擎,他在抓取网页的时候都会记下以下网页信息:
1、网页中出现的关键词(中文分词技术)以及每个关键词的权重(关键词密度);
2、提取meta descrīption或者每个网页的512个字节的有效文字。
关于第2点,baidu和google有所不同,google是提取meta descrīption,没有查询关键字相关的512个字节,而百度是直接提取后者。
在以下算法描述中,首先约定几个信息指纹变量:
Pi表示第i个网页;
该网页权重最高的N个关键词构成集合Ti={t1,t2,...tn},其对应的权重为Wi={w1,w2,...wn}
摘要信息用Des(Pi)表示,前n个关键词拼成的字符串用Con(Ti)表示,对这n个关键词排序后形成的字符串用Sort(Ti)表示。
以上信息指纹都用MD5函数进行加密。
基于关键词的复制网页算法有以下5种:
1、MD5(Des(Pi))=MD5(Des(Pj)),就是说摘要信息完全一样,i和j两个网页就认为是复制网页;
2、MD5(Con(Ti))=MD5(Con(Tj)),两个网页前n个关键词及其权重的排序一样,就认为是复制网页;
3、MD5(Sort(Ti))=MD5(Sort(Tj)),两个网页前n个关键词一样,权重可以不一样,也认为是复制网页;
4、MD5(Con(Ti))=MD5(Con(Tj))并且Wi-Wj的平方除以Wi和Wj的平方之和小于某个阙值a,则认为两者是复制网页;
5、MD5(Sort(Ti))=MD5(Sort(Tj))并且Wi-Wj的平方除以Wi和Wj的平方之和小于某个阙值a,则认为两者是复制网页;
关于第4和第5的那个阈值a,主要是因为前一个判断条件下,还是会有很多内容部分相同的网页被认为相同而被排除掉,因此要根据权重的分布比例调节a的大小。
以上5种算法运行的时候,算法的效果取决于N,就是关键词数目的选取。选的数量越多,判断就会越精确,但是随之而来的计算速度也会减慢下来。所以必须考虑一个计算速度和去重准确率的平衡。据天网试验结果,10个左右关键词最恰当。
4.随机映射(Random Projection)算法:
先给每个词语(Token)生成随机的特征向量,保存为一个集合,然后对网页正文进行分词,得到一系列的词语,从词语的特征向量集合中取出这些词语的特征向量(如果词语不在在集合中,那么给词语生成一个随机的特征向量,将其加入集合),将这些特征向量按位进行一个特殊的加运算,最后得到网页的特征向量。判断两个网页是否具有相似或重复内容就可以通过判断它们特征向量相同的位数(bit)来进行。
5.近似网页发现算法
首先,定义几个算法中用到的参数:
Percentage :允许参与生成指纹的关键词的比例。
Sum_interval :参与生成指纹的关键词个数的增长单位。
算法如下:
1、对网页正文切词,生成网页正文的特征向量(已经去掉了停用词)
2、将向量中保留的关键词按照词频排序,相同词频的关键词按照字符排序(从大到小)。
3、在2中生成的关键词列表中选取前sum2 = sum1 * Percentage个关键词作为候选关键词。
4、在3中生成的关键词列表中选取前sum3 = sum2 DIV Sum_interval * Sum_interval个作为参与生成指纹的关键词集合。
5、将4中得到的关键词按照字符排序(从大到小),就得到了最终要生成指纹的字符串。
6、以5中生成的字符串为源串调用MD5函数得到该网页的指纹。
指纹比较的过程中,只要对网页的指纹值直接排序就可以将重复的网页聚到一起。
6.Hash算法
1、对于每一个xml文件去标记,得到文本内容并进行分词,生成分词后的语料库C;
2、遍历语料库C,计算词语的IDF值;
3、对于每一篇文档,保留其idf值较大的前70%,并降序排列,构成该文档的特征向量;
4、计算任一文档的特征串的hash值,(拟用ELFhash),生成二元组<doc_id, hashvalue>。对具有相同hash值的文档,比较两个文档的特征串是否相同,如果相同,则是重合文档,否则不是重合文档。
简单说明:
a. hash函数的选择很关键,如果hash选择很好,时间复杂度为O(N), N为文档规模,最坏情况下所有特征串的hash值相等,则时间复杂度是 O(N*N);
b.我们添加了对同hash值文档的特征串进行比较,所以增加了时间复杂度;经过几天编程方法已经实现,本方法相对对重复的要求更严格,内容完全重复的一定可以识别,另外对Hash函数的选择也很关键;为了更好选择hash函数,做了以下实验,语料为1000个xml博客文件;
实际重复文档数:419
实际应该产生冲突数:419
ELFHash产生冲突数: 594 所用时间为:60s
RSHash产生冲突数:584 所用时间为:60S
JSHash产生冲突数:546 所用时间为:58S
PJWHash产生冲突数:594 所用时间为:61.4S
BKDRHash产生冲突数:601 所用时间为:64.5S
SDBMHash产生冲突数:546 所用时间为:61.5S
DJBHas产生冲突数: 595 所用时间为:66S
APHash产生冲突数: 543 所用时间为:57.1S
经以上实验,选用了APHash函数来处理重复文档检测
7.一般处理的方法
(1)最原始的使用文本相似度判别,相当准确,但是计算速度慢,提高的方法无非是先索引进行预处理,或者用SVD来降维减少矩阵运算时间
(2)文本摘要为文本特征,进行特征重复判别
(3)抽取文本关键词,构成比较小的文本向量做为特征进行判别
大家考虑过以上3中算法的共性没?那就是要分词,中文分词博大精深,效果越好速度越慢这是铁律,但具体还要看分词算法的设计。所以这部分时间的消耗以上3中方法是无可避免的必须进行的步骤。
8.基于句子的方式
而我所考虑的是从句子的角度,但如果单个句子的特征,特征未免单一,而不具有代表性,句子多了又可能,造成特征过于复杂和容错性能的下降,毕竟我们通过自动抽取的网页正文不能保证100%无任何噪音和抽取失误带来的原文缺失。在这个角度上我们进一步考虑是否能有更好的方法呢?传统中文断句,我们主要依赖于标点符号,那我的想法就是标点符号左右的汉字已经能有很强的代表性来作为句子的特征,而句子又能作为文本的特征,因此尝试了取逗号 句号 感叹 问号 左右2边各2个汉字或英文作为特征,来进行文本表示。
全文按照标点符号取出汉字后构成了1个比较长的串,但为了信息指纹的需要,我们必须考虑容错性的问题,这个串如果直接HASH,有可能因为噪音的加入产生巨大的偏差,因此我对这个长串做了截断的处理,同时考虑一般标题的信息含量很高,单独认为标题也成为1个字串,指纹特征就变成了1个标题的HASH码 3个截断后的子串HASH码 同时标题的权重为1.5 其他子串权重为1.0 阀值设定为3 这样如果有标题相同 并有2个字串相同的文章我们就认为是重复,或者标题不相同 3个字串完全相同的是重复。具体消重特征判别,是使用数据库的内存表还是BLOOMFILTER之类的算法就随便你了。
当然以上算法的前提是正文和标题抽取的准确如果噪音过多,这个算法可能降低到一个完全无法应用的程度,怎么提高该算法的在噪音比较高情况下的容错性,该是自己考虑的问题了。
9.我的一些想法
需要排除重复文本有如下几种:1.绝大部分一样(比如转载);2.部分一样(修修改改);3.话题一样(聚类范畴)。
上面各种方法:
1)一种是有序的如2,8;另一种是无序的,如1,3,4,5,6,按照特征权重排序;
2)特征值的生成有三种,MD5,按位加,哈希。
基于段落和句子的有序算法,可能会漏排;而基于特征的算法可能会误排。
既然是网页文本排重,可以把网页的信息考虑进去:比如
可以根据title,keywords,description等信息获取核心词指纹(核心词可以是几个,方法参考上面的方法),再获取内容的分段(可以把小的段合并,再取最大的几段)指纹。先比较核心词指纹,如果一样,则比较内容指纹;如果核心词不一样,则直接排除。这个方法只用核心词,而不是整个标题,可以容忍标题噪音,用核心词做一次粗排,再用精确指纹进行细排;第一次核心词指纹查找可以排除大量不相干的网页(毕竟重复的比重还是比较低的),只是从近似网页(近似网页少很多)中查找分段指纹,计算效率上有保证,比如1亿网页,和当前文本核心词一样的比如只有1万,则分段指纹只需要比较1万个。
后记:
SimHash算法可以用来排重:
http://www.cnblogs.com/linecong/archive/2010/08/28/simhash.html
利用simhash来进行文本去重复
http://blog.csdn.net/fuyangchang/archive/2010/06/01/5639595.aspx
SimHash算法可以用来排重,但是SimHash的特征取值,同样需要处理,因为网页排重不是比较两个网页源文件是否重复,而是比较其内容是否重复,所以,必须进行去噪和提取特征的步骤。
其实排重分为两步
1、是特征的选择,选择什么样的特征来代表整个网页
2、特征的计算,MD5、Hash等算法
我认为第1个是难点。