前几天去吃葫芦头的路上,大飞哥给详细的讲解了他在比较文本相似度实验时对Google的simhash方法高效的惊叹,回来特意去找了原文去拜读。

Simhash

传统IR领域内文本相似度比较所采用的经典方法是文本相似度的向量夹角余弦,其主要思想是根据一个文章中出现词的词频构成一个向量,然后计算两篇文章对应向量的向量夹角。但由于有可能一个文章的特征向量词特别多导致整个向量维度很高,使得计算的代价太大,对于Google这种处理万亿级别的网页的搜索引擎而言是不可接受的,simhash算法的主要思想是降维,将高维的特征向量映射成一个f-bit的指纹(fingerprint),通过比较两篇文章的f-bit指纹的Hamming Distance来确定文章是否重复或者高度近似。

simhash算法很精巧,但却十分容易理解和实现,具体的simhash过程如下:

1. 首先基于传统的IR方法,将文章转换为一组加权的特征值构成的向量。

2.初始化一个f维的向量V,其中每一个元素初始值为0。

3.对于文章的特征向量集中的每一个特征,做如下计算:

利用传统的hash算法映射到一个f-bit的签名。对于这个f- bit的签名,如果签名的第i位上为1,则对向量V中第i维加上这个特征的权值,否则对向量的第i维减去该特征的权值。

4.对整个特征向量集合迭代上述运算后,根据V中每一维向量的符号来确定生成的f-bit指纹的值,如果V的第i维为正数,则生成f-bit指纹的第i维为1,否则为0。

simhash和普通hash最大的不同在于传统的hash函数虽然也可以用于映射来比较文本的重复,但是对于可能差距只有一个字节的文档也会映射成两个完全不同的哈希结果,而simhash对相似的文本的哈希映射结果也相似。Google的论文中取了f=64,即将整个网页的加权特征集合映射到一个64-bit的fingerprint上。

比起simhash,整片文章中Google所采用的查找与给定f-bit的fingerprint的海明距离(Hamming Distance)小于k的算法相对还稍微难理解点。

fingerprint的Hamming Distance

问题:一个80亿的64-bit指纹组成的集合Q,对于一个给定64-bit的指纹F,如何在a few millionseconds中找到Q中和f至多只有k(k=3)位差别的指纹。

思想:1. 对于一个具有2^d个记录的集合,只需要考虑d-bit hash。2. 选取一个d’使得|d’-d|十分小,因此如果两fingerprint在d’-bits上都相同,那么在d-bits也很可能相同。然后在这些d-bit match的结果中寻找整个f-bit的Hamming Distance小于k的fingerprint。 简单的说,就是利用fingerprint少量特征位数比较从而首先缩小范围,然后再去确定是否差异小于k个bit。

算法:

1. 首先对于集合Q构建多个表T1,T2…Tt,每一个表都是采用对应的置换函数π(i)将64-bit的fingerprint中的某p(i)位序列置换换到整个序列的最前面。即每个表存储都是整个Q的fingerprint的复制置换。

2.对于给定的F,在每个Ti中进行匹配,寻找所有前pi位与F经过π(i)置换后的前pi位相同的fingerprint。

3.对于所有在上一步中匹配到的置换后的fingerprint,计算其是否与π(i)(F)至多有k-bit不同。

算法的重点在于对于集合Q的分表以及每个表所对应的置换函数,假设对于64-bit的fingerprint,k=3,存储16个table,划分参考下图:

将64-bit按照16位划分为4个区间,每个区间剩余的48-bit再按照每个12-bit划分为4个区间,因此总共16个table并行查找,即使三个不同的k-bit落在A、B、C、D中三个不同的区块,此划分方法也不会导致遗漏。

以上方法是对于online的query,即一个给定的F在集合中查找相似的fingerprint。如果爬虫每天爬取了100w个网页,快速的查找这些新抓取的网页是否在原集合中有Near-duplication,对于这种batch-query的情况,Map-Reduce就发挥它的威力了。

不同的是,在batch-query的处理中,是对待查集合B(1M个fingerprint)进行复制置换构建Table而非8B的目标集合,而在每一个chunkserver上对Fi(F为整个8B的fingerprint)在整个Table(B)中进行探测,每一个chunkserver上的的该Map过程输出该Fi中与整个B的near-duplicates,Reduces过程则将所有的结果收集、去重、然后输出为一个sorted file。

Haffman编码压缩

上述的查询过程,特别是针对online-version的算法,可以看出需要对8B的fingerprint进行多表复制和构建,其占据的容量是非常大的,不过由于构建的每一个置换Table都是sorted的,因此可以利用每一个fingerprint与其前一个的开始不同的bit-position h(h∈[0,f-1]) 来进行数据压缩,即如果前一个编码是11011011,而自身是11011001,则后一个可以编码为(6)1,即h=6,其中6表示从第6位(从0开始编号)开始和上一个fingerprint不相同(上一个为1,这个必然为0),然后再保存不相同位置右侧的编码,依次生成整个table。

Google首先计算整个排序的fingerprint表中h的分布情况,即不同的h出现次数,依据此对[0,f-1]上出现的h建立Haffman code,再根据上述规则生成table(例如上面的6就表示成对应的Haffman code)。其中table分为多个block,每一个block中的第一个fingerprint保存原数据,后面的依次按照编码生成。

将每一个block中所对应的最后一个fingerprint保存在内存中,因此在比对的时候就可以直接根据内存中的fingerprint来确定是哪一个block需要被decompress进行比较。

8B个64-bit的fingerprint原占据空间大约为64GB,利用上述Haffman code压缩后几乎会减少一般,而内存中又只对每一个block保存了一个fingerprint。

每次看Google的论文都会让人眼前一亮,而且与很多(特别是国内)的论文是对未来进行设想不同,Google的东西都是已经运行了2,3年了再到WWW,OSDI这种顶级会议上灌个水。再次各种羡慕能去这个Dream Company工作的人,你们懂得。

参考:

Detecting Near-Duplicates for Web Crawling(Paper)

Detecting Near-Duplicates for Web Crawling(PPT)

转载 http://leoncom.org/?p=650607

simhash与Google的网页去重的更多相关文章

  1. 使用simhash库来进行网页去重

    首先感谢作者yanyiwu贡献的开源项目https://github.com/yanyiwu/simhash.在做项 目过程中,翻了一遍<这就是搜索引擎  核心技术详解>这本书的查重算法, ...

  2. 高效网页去重算法-SimHash

    记得以前有人问过我,网页去重算法有哪些,我不假思索的说出了余弦向量相似度匹配,但如果是数十亿级别的网页去重呢?这下糟糕了,因为每两个网页都需要计算一次向量内积,查重效率太低了!我当时就想:论查找效率肯 ...

  3. 网页去重之Simhash算法

    Simhash算法是Google应用在网页去重中的一个常用算法,在开始讲解Simhash之前,先了解——什么是网页去重?为什么要进行网页去重?如何进行网页去重,其基本框架是什么?   网页去重,顾名思 ...

  4. Google 谷歌网页搜索, 学术搜索

    Google 谷歌网页搜索, 学术搜索 1. 网页搜索引擎-Google * https://letsgg.tk/ * https://google.kfd.me/ 谷歌搜索镜像:  http://d ...

  5. simhash进行文本查重 Simhash算法原理和网页查重应用

    simhash进行文本查重http://blog.csdn.net/lgnlgn/article/details/6008498 Simhash算法原理和网页查重应用http://blog.jobbo ...

  6. 一个基于特征向量的近似网页去重算法——term用SVM人工提取训练,基于term的特征向量,倒排索引查询相似文档,同时利用cos计算相似度

    摘  要  在搜索引擎的检索结果页面中,用户经常会得到内容相似的重复页面,它们中大多是由于网站之间转载造成的.为提高检索效率和用户满意度,提出一种基于特征向量的大规模中文近似网页检测算法DDW(Det ...

  7. Google官方网页载入速度检测工具PageSpeed Insights 使用教程

    相信有接触前端开发的大神们都听说过Google官方的PageSpeed Tools,这个网页载入速度检测工具有在线版本也有一个 Chrome 扩展,叫PageSpeed Insights,在此之前,J ...

  8. ctrl+shift+r / ctrl+f5 强制(不使用缓存)刷新google chrome网页

    我改了csdn图片后, 一直看到的是旧图片, n天之后, 还是旧图片.猜测应该是用了缓存(且缓存更新逻辑失败, 定是csdn的bug), 用ctrl+shift+r, 或者ctrl+f5, 强制刷新页 ...

  9. google插件网页播放mp4代码

    <script src="http://html5media.googlecode.com/svn/trunk/src/html5media.min.js"></ ...

随机推荐

  1. 8I - 吃糖果

    HOHO,终于从Speakless手上赢走了所有的糖果,是Gardon吃糖果时有个特殊的癖好,就是不喜欢将一样的糖果放在一起吃,喜欢先吃一种,下一次吃另一种,这样:可是Gardon不知道是否存在一种吃 ...

  2. Linux下使用rsync最快速删除海量文件的方法

    常用的删除命令rm -fr * 就不好用了,因为要等待的时间太长.所以必须要采取一些非常手段.我们可以使用rsync来实现快速删除大量文件. 1.先安装rsync:  yum install rsyn ...

  3. laravel目录结构

  4. vitas高音

    http://music.163.com/#/song/19674656?userid=65416848

  5. base64编码是什么

    首先明确一点base64 是一种编码格式.就想utf-8一样,能在电脑上表示所有字符,或者换句话说通过编码能让电脑理解你想要标识的字符(因为电脑只知道0和1 ) 就像ascII 中 0100 0001

  6. spring学习 六 spring与mybatis整合

    在mybatis学习中有两种配置文件 :全局配置文件,映射配置文件.mybatis和spring整合,其实就是把mybatis中的全局配置文件的配置内容都变成一个spring容器的一个bean,让sp ...

  7. rails 新建user的phonenumber字段

    1.新建字段 //rails g migration add_字段名_to_表名 字段名:字段类型 rails g migration add_title_to_contents title:stri ...

  8. 852. Peak Index in a Mountain Array

    class Solution { public: int peakIndexInMountainArray(vector<int>& A) { return max_element ...

  9. 用模糊查询like语句时如果要查是否包含%字符串该如何写

  10. Linux服务器上新增开放端口号

    开放端口的方法: 方法一:命令行方式               1. 开放端口命令: /sbin/iptables -I INPUT -p tcp --dport 8080 -j ACCEPT    ...