近日读了 Mining of Massive datasets 中 关于Finding similar items相关内容,遂将其中的MinHash算法整理如下。
MinHash 算法由 Andrei Broder (1997) 提出的, 它是一种快速计算海量文档相似度的近似方法。开始被用在AltaVista 搜索引擎上,用于检测两个duplicate web pages, 如果两个web pages非常的像,则把这个page丢掉。Minhash也被用在lage-scale clustering 算法中。
本文的结构
1. 文本的Jaccard相似度;
2. Minhash 定义,以及Minhash 和 Jaccard相似度关系;
3. 求一组文本的Minhash signature。
1. 文本Jaccard Similarity
Jaccard 是一种常用的计算文本相似度的方法,例如两篇文章S1={a, b, c, d} and S2 ={b,c,d,e}, a,...,e 表示文本的特征(例如K-shingle)。
Jaccard 相似度定义为
例如上例J(S1, S2) = 3/5 = 0.6
在推荐系统中 S可以表示用户, a,...,e 可以表示为购买的产品
Jaccard 可以表示两个用户的相似度。
如果有p个用户,k个产品其实可以表示为一个p*k的矩阵M 如下图,我们可以根据这个矩阵求任意两个用户的相似度。
同时因为这个矩阵很稀疏,所以我们用稀疏矩阵存储。
但是即使M很稀疏,当p q数目很大时,计算也比较耗时。
所以想用一个比较小的特征矩阵去代替这个矩阵M,使得我们可以近似的求解他们的相似度。
Minhash 就是用来解决这个问题的。
下面首先将什么是MinHash, 以及他的一些性质。
最后将如何通过MinHash计算 MinHash Signature矩阵用于近似的计算Jaccard 相似度。
2. MinHash
MinHash 定义为,对于矩阵M的行做一个全排列,比如重新排列成beadc, 我们可以将全排列的过程看出一个Hash过程。
新的M矩阵可以表示成
根据这个hash函数,每个特征向量(例如S1={00110})的minHash值定义为:第一个value不为0的Element的值 (minHash是对应Element的值)
例如 h(S1) = a, h(S2) = c, h(S3) = b, h(S4) = a
根据不同的hash 函数, minHash值也会不同,
MinHash跟Jaccard 相似度相关。
两个集合(用户)经过随机排列转化(及行的全排列)后得到两个minHash相等的概率 等于这两个结合的相似度。
在书中有分析,主要过程是S1 和 S2经过minHash后可能有三种情况
type X:hash之后都为1
type Y:有一个为1 一个为0
type Z:都为0
两个值相等改率为 x/(x+y), 这个值就是S1 和 S2的 Jaccard 相似度
但是这么算相似度,相当于把行做全排列,计算量还是比较大。
下面介绍通过生成MinHash Signature特征矩阵来计算Jaccard相似度。
3. MinHash Signature
实际中,使用n个Hash 函数代替将行全排列,即将M矩阵的所有K行用n个Hash函数 重新做映射 (Hash函数会产生冲突,但是k较大是冲突不是很多)。
如果用h1, h2,...,hn 表示n个Hash 函数, r为原矩阵的行号,SIG表示新生成的 MinHash Signature 矩阵,同时
SIG(i,c)表示第i个hash函数的第c个用户的特征(SIG和M有相同的列数,即用户数)。
计算MinHash Signature过程如下:
Initial: 设置SIG矩阵元素为 MAXINT,对M的行做n个Hash 运算
如果取两个hash函数 h1(x) = (x+1) mod 5, h2(x)=(3x+1)mod 5,对上面的原始矩阵做MinHash Signature 可以得到
s1 s2 s3 s4
h1 1 3 0 1
h2 0 2 0 0
通过这个矩阵SIM(S1,S4)= 1 实际是2/3; SIM (S1, S3)=0.5实际是1/4; SIM(S1, S3) = 0 实际也是0.
参考:
http://yangpengg.github.io/blog/2012/09/05/minhash-and-lsh/