Hash综述

来源:互联网 发布:淘宝商家入口 编辑:程序博客网 时间:2024/06/01 09:28
 

MinHash算法


1.概述

    跟SimHash一样,MinHash也是LSH的一种,可以用来快速估算两个集合的相似度。MinHash由Andrei Broder提出,最初用于在搜索引擎中检测重复网页。它也可以应用于大规模聚类问题。

2.Jaccard index

    在介绍MinHash之前,我们先介绍下Jaccard index。

    Jaccard index是用来计算相似性,也就是距离的一种度量标准。假如有集合A、B,那么,

    

    也就是说,集合A,B的Jaccard系数等于A,B中共同拥有的元素数与A,B总共拥有的元素数的比例。很显然,Jaccard系数值区间为[0,1]。

3.MinHash

    先定义几个符号术语:
    h(x):  把x映射成一个整数的哈希函数。   
    hmin(S):集合S中的元素经过h(x)哈希后,具有最小哈希值的元素。

    那么对集合A、B,hmin(A) = hmin(B)成立的条件是A ∪ B 中具有最小哈希值的元素 ∩ B中。这里

有一个假设,h(x)是一个良好的哈希函数,它具有很好的均匀性,能够把不同元素映射成不同的整数。

    所以有,Pr[hmin(A) = hmin(B)] = J(A,B),即集合A和B的相似度为集合A、B经过hash后最小哈希值相

等的概率。

        有了上面的结论,我们便可以根据MinHash来计算两个集合的相似度了。一般有两种方法:
        
        第一种:使用多个hash函数

        为了计算集合A、B具有最小哈希值的概率,我们可以选择一定数量的hash函数,比如K个。然后用这K个hash函数分别对集合A、B求哈希值,对
每个集合都得到K个最小值。比如Min(A)k={a1,a2,...,ak},Min(B)k={b1,b2,...,bk}。
        那么,集合A、B的相似度为|Min(A)k ∩ Min(B)k| / |Min(A)k  ∪  Min(B)k|,及Min(A)k和Min(B)k中相同元素个数与总的元素个数的比例。

       第二种:使用单个hash函数

       第一种方法有一个很明显的缺陷,那就是计算复杂度高。使用单个hash函数是怎么解决这个问题的呢?请看:
       前面我们定义过 hmin(S)为集合S中具有最小哈希值的一个元素,那么我们也可以定义hmink(S)为集合S中具有最小哈希值的K个元素。这样一来,
我们就只需要对每个集合求一次哈希,然后取最小的K个元素。计算两个集合A、B的相似度,就是集合A中最小的K个元素与集合B中最小的K个元素
的交集个数与并集个数的比例。
        
      看完上面的,你应该大概清楚MinHash是怎么回事了。但是,MinHash的好处到底在哪里呢?计算两篇文档的相似度,就直接统计相同的词数和总的
次数,然后就Jaccard index不就可以了吗?对,如果仅仅对两篇文档计算相似度而言,MinHash没有什么优势,反而把问题复杂化了。但是如果有海量的文档需要求相似度,比如在推荐系统
中计算物品的相似度,如果两两计算相似度,计算量过于庞大。下面我们看看MinHash是怎么解决问题的。

      比如 元素集合{a,b,c,d,e},其中s1={a,d},s2={c},s3={b,d,e},s4={a,c,d}   那么这四个集合的矩阵表示为:  
      
    如果要对某一个集合做MinHash,则可以从上面矩阵的任意一个行排列中选取一个,然后MinHash值是排列中第一个1的行号。
    例如,对上述矩阵,我们选取排列 beadc,那么对应的矩阵为
          
    那么, h(S1) = a,同样可以得到h(S2) = c, h(S3) = b, h(S4) = a。
        如果只对其中一个行排列做MinHash,不用说,计算相似度当然是不可靠的。因此,我们要选择多个行排列来计算MinHash,最后根据Jaccard index公式 来计算相似度。但是求排列本身的复杂度比较高,特别是针对很大的矩阵来说。因此,我们可以设计一个随机哈希函数去模拟排列,能够把行号0~n随机映射到0~n上。比如H(0)=100,H(1)=3...。当然,冲突是不可避免的,冲突后可以二次散列。并且如果选取的随机哈希函数够均匀,并且当n较大时,冲突发生的概率还是比较低的。

    说到这里,只是讨论了用MinHash对海量文档求相似度的具体过程,但是它到底是怎么减少复杂度的呢?
    比如有n个文档,每个文档的维度为m,我们可以选取其中k个排列求MinHash,由于每个对每个排列而言,MinHash把一篇文档映射成一个整数,所以对k个排列计算MinHash就得到k个整数。那么所求的MinHash矩阵为n*k维,而原矩阵为n*m维。n>>m时,计算量就降了下来。
    

4.参考文献
    (1) http://en.wikipedia.org/wiki/MinHash
           (2)  http://fuliang.iteye.com/blog/1025638
转自:http://my.oschina.net/pathenon/blog/65210

SimHash
说到文本相似性计算,大家首先想到的应该是使用向量空间模型VSM(Vector Space Model)。使用VSM计算相似度,先对文本进行分词,然后建立文本向量,把相似度的计算转换成某种特征向量距离的计算,比如余弦角、欧式距离、Jaccard相似系数等。这种方法存在很大一个问题:需要对文本两两进行相似度比较,无法扩展到海量文本的处理。想想像Google这种全网搜索引擎,收录了上百亿的网页,爬虫每天爬取的网页数都是百万千万级别的。为了防止重复收录网页,爬虫需要对网页进行判重处理。如果采用VSM方法,计算量是相当可观的。
    
    这里介绍的SimHash算法很好的解决了VSM方法的缺陷,该方法最初由Google提出,用于网页去重。

    在介绍SimHash前,先大概说下传统的Hash算法。我们知道,衡量一个Hash算法好坏的一个指标是随机性。也被称作简单一致散列假设:每个关键字都等可能地散列到m个槽位中的任何一个中去,并与其他的关键字已被散列到哪一个槽位中无关。说白了,就是让散列的分布尽量均匀,哪怕内容发生很小的变化,hash值也会发生很大的变化。因此,根据传统的hash值无法得知被散列内容的相似程度。

    下面正式谈谈SimHash算法。它的神奇之处就在 它的签名值除了提供原始内容是否相等的信息外,还能额外提供不相等的原始内容的差异程度的信息。SimHash的思想非常简单,如图所示:
 
    
     算法描述如下:
    输入为一个N维向量V,比如文本的特征向量,每个特征具有一定权重。输出是一个C位的二进制签名S。
    1)初始化一个C维向量Q为0,C位的二进制签名S为0。
    2)对向量V中的每一个特征,使用传统的Hash算法计算出一个C位的散列值H。对1<=i<=C,
       如果H的第i位为1,则Q的第i个元素加上该特征的权重;
       否则,Q的第i个元素减去该特征的权重。
    3)如果Q的第i个元素大于0,则S的第i位为1;否则为0;
    4)返回签名S。
   

    对每篇文档根据SimHash算出签名后,再计算两个签名的海明距离(两个二进制异或后1的个数)即可。根据经验值,对64位的SimHash,海明距离在3以内的可以认为相似度比较高。

    读到这里,你也许有一个疑惑:SimHash到底是怎样解决VSM需要两两比较的缺陷呢?请继续往下看。
    
    假设对64位的SimHash,我们要找海明距离在3以内的所有签名。我们可以把64位的二进制签名均分成4块,每块16位。根据鸽巢原理(也成抽屉原理,见组合数学),如果两个签名的海明距离在3以内,它们必有一块完全相同。你也许很兴奋,说的这些你都懂。但是请不要忘了,我们事先是不知道具体是哪一块完全相同,因此我们需要穷举,对,你没看错,是穷举。但是这里的穷举也就是4次而已。我们把上面分成的4块中的每一个块分别作为前16位来进行查找。什么意思呢?请看图:
 
    通过这幅图,不知道你看明白没有,反正我还没有明白。下面让咱们一起进一步探索。
    举个简单的例子,对于8位的二进制签名 01 10 00 11,咱们分别把每一块拿出来,在所有的8位二进制签名中查找前两位分别是01,10,00,11的签名。也许你要说,那不同样需要两两比较吗?对,常规意义下却是如此。但是咱们可以做索引啊!按照前两位进行索引,比如00111111和00101010放在一个簇中,10111111和10101010放在一个簇中。这下应该明白了吧。
    
    如果库中有2^34个(大概10亿)签名,那么匹配上每个块的结果最多有2^(34-16)=262144个候选结果,四个块返回的总结果数为4* 262144(大概100万)。原本需要比较10亿次,经过索引,大概就只需要处理100万次了。由此可见,确实大大减少了计算量。


参考文献:
1.《 Similarity Estimation Techniques From Rounding Algorithms
2.  http://grunt1223.iteye.com/blog/964564
3.  http://www.cnblogs.com/linecong/archive/2010/08/28/simhash.html
转自:http://my.oschina.net/pathenon/blog/63747


基于hash方法的相似计算

3 基于hash方法的相似计算

       基于hash的相似度计算方法,是一种基于概率的高维度数据的维度削减的方法,主要用于大规模数据的压缩与实时或者快速的计算场景下,基于hash方法的相似度计算经常用于高维度大数据量的情况下,将利用原始信息不可存储与计算的问题转化为映射空间的可存储计算问题,在海量文本重复性判断方面,近似文本查询方面有比较多的应用,google的网页去重[1],google news的协同过滤[2,3]等都是采用hash方法进行近似相似度的计算,比较常见的应用场景Near-duplicate detection、Image similarity identification、nearest neighbor search,常用的一些方法包括I-match,Shingling、Locality-Sensitive Hashing族等方法,下面针对几种常见的hash方法进行介绍。

3.1 minhash方法介绍

       Minhash方法是Locality-sensitive hashing[4,5]算法族里的一个常用方法,基本的思想是,对于每一个对象的itemlist,将输入的item进行hash,这样相似的item具有很高的相似度被映射到相同的buckets里面,这样尽量保证了hash之后两个对象之间的相似程度和原来是高相似的,而buckets的数量是远远小于输入的item的,因此又达到降低复杂度的目的。

       minhash方法用Jaccard进行相似度的计算方法,则对于两个集合和 , 和 的相似性的计算方法为:

当两个集合越相似,则该值越接近1,否则越接近0。用minhash方法,将一个集合映射到[0-R-1]之间的值,以相同的概率随机的抽取一个[0-R-1[的一个排列,依次排列查找第一次出现1的行。

设随机排列为43201(edcab),对于C1列,第一次出现1的行是R4,所以h(C1) = 3,同理有h(C2)=2, h(C3)=4, h(C4)=3。

通过多次抽取随机排列得到n个minhash函数h1,h2,…,hn,依此对每一列都计算n个minhash值。对于两个集合,看看n个值里面对应相等的比例,即可估计出两集合的Jaccard相似度。可以把每个集合的n个minhash值列为一列,得到一个n行C列的签名矩阵。因为n可远小于R,这样在压缩了数据规模的同时,并且仍能近似计算出相似度。

3.2 simhash方法介绍

simhash方法是在大文本重复识别常用的一个方法,该方法主要是通过将对象的原始特征集合映射为一个固定长度的签名,将对象之间的相似度的度量转化为签名的汉明距离,通过这样的方式,极大限度地进行了降低了计算和存储的消耗。

3.2.1 签名计算过程

       该方法通过对输入特征集合的计算步骤可以描述如下:

  1. 将一个f维的向量V初始化为0;f位的二进制数S初始化为0;
  2. 对每一个特征:用传统的hash算法对该特征产生一个f位的签名b。对i=1到f:

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

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

  1. 如果V的第i个元素大于0,则S的第i位为1,否则为0;
  2. 输出S作为签名。

通过上述步骤将输入的表示对象的特征集合转化为该对象的一个签名,在完成签名之后,度量两个对象的相似度的差异即变成了对量二者的指纹的K位的差异情况。

3.2.2 汉明距离查找优化

对于如何快速查找出某一个签名是否与其存在最大差异不超过K个bit的指纹,Detecting Near-Duplicates for Web Crawling这篇论文中进行了介绍。该查找方法的基本思想是利用空间换时间的方法,该方法的依据是需要查找的两个指纹的差异很小,这样可以通过将原始指纹进行分块索引,如果两个指纹的差异很小,则合理的分块后,根据鸽笼原理,其中存在一定数量的块是一致的,通过利用相同的块进行相似的指纹的召回,只需要比对召回的块中有差异的块的bit差异,这样减少了需要比对的数量,节省了比对的时间开销。

3.3 小结

       hash方法的相似度计算的主要应用场景,一般是针对大规模数据进行压缩,在保证效果损失可接受的情况下,节省存储空间,加快运算速度,针对该方法的应用,在目前的大规模的互联网处理中,很多相似度的计算都是基于这种近似性的计算,并取得了比较好的效果。

设随机排列为43201(edcab),对于C1列,第一次出现1的行是R4,所以h(C1) = 3,同理有h(C2)=2, h(C3)=4, h(C4)=3。

通过多次抽取随机排列得到n个minhash函数h1,h2,…,hn,依此对每一列都计算n个minhash值。对于两个集合,看看n个值里面对应相等的比例,即可估计出两集合的Jaccard相似度。可以把每个集合的n个minhash值列为一列,得到一个n行C列的签名矩阵。因为n可远小于R,这样在压缩了数据规模的同时,并且仍能近似计算出相似度。

转自:http://huangbo929.blog.edu.cn/2012/758781.html



0 0
原创粉丝点击