在大数据中如何寻找相似的文档(shingle, minhash, LSH)(一)

ps: 文章翻译与 Mining of Massive Datasets

场景:在一堆非常多的文档中,找到相似的文档,或者对文档间的相似性进行评估。

当应用于此类目的的时候,我们最常用的用来表示一篇文档的方法是:shingling。
1. k-shingles
     可以把一篇文档看成一个字符串。那么一篇文档的k-shingle就是在这篇文档中出过现的任何长度为k的字符串。k-shingles就是改篇文档所有k-shingle的集合。 (那么k的大小决定于什么因素呢? 与文档的长度和所有的字符个数有关。k的取值一般要满足一个规则:k的取值应该能够满足,任何一个给定的shingle出现在任何给定的文档中的概率都非常低。)  (一般对于邮件类的文档,k取值为5是最为合适的。假设在邮件中一般只会出现字母字符和空格字符。那么将会有27^5=14,348,907个可能的shingles。而一般的Email的字符长度会远小于14million。而在实际的测试中k=5也确实是表现的非常好。而对于长文档,如研究论文等k取9是一个安全的取值。)
2. Hashing Shingles
     我们可以选择一个hash函数来将k-shingle映射成为数值,这样对文档的表示形式就是一群整数的集合。
3.  对于单词建立shingles
     除了将文档看成字符串,我们也可以以单词为个体建立shingle。对于新闻类的文档,建立单词的shingle是非常有效的。(对于新闻类的文档,会出现非常多的停用词,停用词一般不能告诉我们文档的重要信息,所以一般会先去掉停用词)
     (然而,对于在新闻类文档中找到两个类似的文档问题,研究发现,对于这样的shingle:‘一个停用词后边紧跟着两个词,不管后边的两个词是不是停用词’   能够形成非常有用的shingles集合。它的好处在于,可以让新闻类文档形成的shingles集合中,与webPage本身有关的多于与周围环境有关的 <原因未知,书中也没有更多的说明>。这样非常合适这样的目的:在一大堆网页中,找出网页中文章是相关的,而不管文章周围的内容。)
4.  保持相似度的集合摘要(MinHashing)
   可以发现,文档的shingles集合是非常大的,尽管我们用hash将其映射为4byte或者更大的整数。假设我们有上百万的文档,那么内存中就会放不下这些shingles的集合。
     我们的目标就是把大数据量的shingles集合变换为非常小的代表(称之为签名)。而且这样的签名应该有这样的性质: 能够很容易的对两个签名集合进行比较,并且能够较简单的计算两个签名集合的jaccard距离;而且,签名集合计算出来的的相似度(jaccard距离)应该和实际的相差不大,签名集合越大,越能接近准确值。
     MinHashing就是具有这些性质的获取签名的一种有效方法。 签名一般大概会取几百个左右,每一个值都是原代表集合的一个不同的MinHash值。
     那么如何计算一个集合的minhash值呢? 首先,对集合的表示方法进行改变,假设现在三篇文档,我们用下面的方式来表示,称之为characteristic matrix; 左边的一列是所有出现过的元素。这样每一篇文档被表示为0,1集合。
elements1s2s3
a100
b001
c010
d101
e001
 若要求一个文档的minhash值,首先对每一列的元素进行同样的重新排列,相当于把最左侧的element的顺序进行重排;然后,每一个文档的一个minhash值就是该列元素中第一’1‘所在位置的元素;(假设上表中就是已经重排后的矩阵,那么s1的该minhash值就是a, s2是c; s3是b;)
  同上,我们取几百个不同的minhash函数对矩阵进行不同的重排,就可以得到每个文档的签名(元素数目和所取得函数数目相同)
  分析上边的计算过程,我们可以发现,在实际计算中,我们可以不用真的对所有元素进行重排(对于大数据量文档来说这是一个非常不现实的过程),因为我们只要找到第一个不元素1所在的位置就行了,所需要的只是按照minhash函数的规定一次遍历元素集直到知道元素1为止。
 
5. 如何计算MinHash 签名
     书上给出的是这样的方法: 由于对characteristic matrix的行(一般是百万甚至十亿级别的数量)进行重排是非常耗时的。所以我们通过hash函数来模拟重排过程,利用hash函数将行号映射到与行数相同的buckets中;hash的过程可能会有冲突,不过当k非常大而且冲突并不是非常多的时候区别并不是很大。
     首先随机选取n个hansh函数;h1,h2.....hn;
rows1s2s3s4h1= x+1 mod 5
010011
100102
201013
310114
400100
    我们用SIG(i,c)用来存储第i个hash函数和第c列数据(文档c的变换表示)的签名值,并且初始化为无穷大。
    其次没我们对每一行r进行如下处理:
    1.  计算 h1(r),h2(r)....hn(r);
    2.  对每一列c进行:  如果 c列r行的数值是0,什么也不做;  否则, 对每一个i=1,2,....n 设置SIG(i,c) = min(SIG(i,c), hi(r));也就是设置为当前的SIG(i,c)值和hi(r)的最小值。 (过程相当于在计算的过程中,不断用重排后位置最靠前且数值为1的行号放在相应的SIG中,从而达到前文所述的求签名值得目的)
     通过上面的方法就可以求得一篇文档的minhan签名。但是尽管我们通过minhash将文档压缩为小的签名值,并且能保证相互间相似度的计算;我们仍不能很有效的找到相似度最高的文档对,因为要比较的文档数目可能非常大。这时候,如果我们的目标找到相似度在一定阈值以上的文档对,或者最相似的文档对;而不是计算所有的文档对的相似度,那么我们就可以采用图像处理经常使用的LSH技术来简化计算。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值