数据挖掘之lsh minhash simhash


在项目中碰到这样的问题:

互联网用户每天会访问很多的网页,假设两个用户访问过相同的网页,说明两个用户相似,相同的网页越多,用户相似度越高,这就是典型的CF中的user-based推荐算法。

算法的原理很简单,只要两两计算用户的相似性,针对每个用户,获取最相似的K个用户即可。

但是在实际的工程上,假定用户规模在亿的规模N,计算复杂度为N*N,即使是分布式,也是非常可怕的复杂度。

考虑一下,我们是不是真的需要计算所有用户之间的相似性?其实我们只需要计算和用户A最相似的K个用户即可,如果已知B和A一定不相似,那么就没有必要计算,这就是LSH的思想。

 

LSH:local sensitive hash,局部敏感哈希,关注可能相似的pair,而非所有的pair,这是lsh的基本思想。

 

举个例子:

用户user1 访问过 url1,url2

用户user2访问过 url2,url3

用户user3访问过url3

很明显,user1和user2相似,而 user1和user3是不相似的,换句话,user1和user3是不需要比较的。

如何做到呢?最简单的思路,把url作为hash的key,user作为value,计算同一个key下面user的相似度。

url1:user1

url2:user1 user2

url3:user2 user3

这样分别计算user1 user2 以及user2和user3的相似性即可,不用计算user1和user3,也就是不相似的user不需要计算其相似性,基本上就是LSH的思想

 

但是,很明显,上面的作法过于简单和粗暴:

1.如果每个user有上w维的特征,针对每个特征做一个hash,会导致计算复杂度大大增加,两个特征相同的用户,需要计算w次相似性

2.无法刻画lsh中,只关注相似的paire 中的"相似”程度,比如如果相似性<0.5,则认为不相似,尽量不出现在一个桶等等

 

第一个问题谈到是降维,第二个是如何进行刻画相似性以及进行hash。

 

 

minhash以及simhash就是来解决上面的两个问题的,这两个都是来刻画jaccard距离的。

回到刚开始的例子,及时就是计算user1与user2的jaccard距离,假设url进行了编号,有唯一的id,最大编号为N,每个用户访问过的url数目为N(u)。

这样我们可以理解每个用户有N个特征,其中访问过的对应位置为1,没有访问的为0,维数很高,几十B的规模。

 

minhash就是来解决降维的问题,具体的minhash原理网上有很多介绍,就不在详细说了。

minhash最后的产出是每个用户有K维的特征{id1,id2....idk},不同用户第k特特征相同的概率和直接利用用户原始的N维特征计算jaccard距离的相似性相同, K<

如果利用K维特征,计算2-2相似性,复杂度还是很高。

 

利用LSH思想,我们只需要计算可能形似用户的相似度,保证相似的用户对应的hash值一样,而不相似的对应的hash值不同。

两个用户度为p,则用户对应相同位置特征值相同的概率为p,有证明。

将K个特征划分为band,b1,b2...bm,每个band里面的元素个数为r个,r*m=K

用户每个band里面r个特征全部相同的概率为p^r,也就是基于这个band作为hash值,两个用户hash值相同的概率为p^r,那么hash值不同的概率为1-s^r,m个band hash值都不一样的概率为(1-p^r)^m,也就是两个用户不在任何一个桶里面的概率。

而1-(1-p^r)^m 则为两个用户落在至少一个桶里面的概率,很容易理解,如果r越小,最后值越大,很不相似(p很小)的元素落在一个桶里面的概率很大,计算的复杂度高。如果r很大,则最后的值很小,也就是很相似(p比较到)落在一个桶里面的概率很小.

比如 r=1, m=16,p=0.2,计算后为99.8%,也就是相似性为0.2的两个元素,99.2%的概率会落在一个桶里面,进行计算,事实上是没有必要的。

r=20,m=1,p=0.8,计算后0.02%,也就是说相似性为0.8的两个元素,0.02%的概率是落着一个桶里面,概率很低,影响召回率。

这时候根据实际需要来确定r的大小,比如 r=2,m=8,

p=0.3时为53%概率落在一个桶

p=0.5时为90%概率落在一个桶

p=0.7时为99.6%概率裸着一个桶。

通过这个方法平衡计算复杂度和项目需求

 

整体来看,minhash主要是用来降维,且为LSH提供的条件。


 MinHash首先它是一种基于 Jaccard Index 相似度的算法,也是一种LSH的降维的方法,应用于大数据集的相似度检索、推荐系统。下边按我的理解介绍下MinHash。

   举例A,B 两个集合:

   A = {s1, s3, s6, s8, s9}

   B = {s3, s4, s7, s8, s10}

   根据Jaccard Index公式,A,B的相似度 S(A,B) = |A∩B|/|A∪B| = 2/8 = 0.25, 用图表示如下:

   数据挖掘之lsh minhash simhash_第1张图片

   当然直接计算两个集合的交集与并集,是很耗计算资源的,特别是在海量数据场景下不可行。

   假如,我们随机从两个集合中各挑选一个元素s(A)、s(B),刚好这两个无素相同的概率是多少呢?

   从图上看,这个概率其实等同于,在A∪B这个大的随机域里,选中的元素落在A∩B这个区域的概率,这个概率就等于Jaccard的相似度!这就是MinHash的基本原理。

   基于这一原理,我们找一个随机的哈希函数h,对集合的每一个元素作哈希运算,比如集合A,可以算出5个hash值,因为是随机的,这5个hash值里值最小的那个元素,对于A集合中所有元素概率都是均等的。同样方法从B中取最小hash值,2个minhash相等的概率就是集合的相似度了。

   我们只需要找到N个哈希函数,对集合生成一组minhash,算两个集合的相似度,也就是这2组minhash中,交集/并集了。

   这个计算相对容易了,因为每个集合的元素数变成了常数N,也就是说,MinHash其实是一种降维技术

   在Mahout中用MinHash作聚类,则是将每个minhash相同的向量聚集为一个簇,哈希函数个数为10的情况下,有一个hash相同就表示至少有20%的相似度了。

   你可能注意到,这个相似度其实没有说元素的权重,另一个问题是哈希函数个数,理论上次数越多,会越准确,但是计算复杂度也越高,实际应用需要找一个平衡点。

   我在一个推荐人的场景——将几十万优质用户按相似度推荐给几千万的普通用户,就是先用MinHash筛选一次,为每个普通用户推荐一个按MinHash相同个数作排序的、至少跟用户交集的优质用户备选集,再计算用户跟备选集的余弦相似度,找出最相似的TOPN作为推荐。这种方法虽然不是最优解(计算量仍然很大),但是在一个可接受的时间范围内,效果跟两两计算余弦相似取TOPN相比比较接近(通过取样测试,取用户权重最重的TOPN个属性作MinHash计算,这样的结果往在做TOPN的推荐容易接近于基于COS的最优解)。另外因为涉及到两个量级差异比较大的集合的推荐,简单用聚类推荐效果很难达到使用MinHash的方法。

 

simhash和minhash有很大的相似性,都是lsh的一个方法,但是其牛逼的地方在于,simhash值之间的海明距离可以刻画其相似程度。

simhash本身也是用来降维以及很方便的利用LSH思想。

 

具体的simhash的介绍很多,不做介绍。

假设simhash的结果是16bit的0-1串作为特征 ,假设有最多k个bit不同,我们认为其相似,那么需要将其划分成k+1个band

比如 k=3,我们需要划分成4个band,这个比较容易理解,也有很完整的证明。

 

整体来看,lsh是来解相似性计算的规模问题,避免计算所有pair,只计算可能相似的pair。

基本的思路就是划分band,band的大小和计算复杂度以及召回率有很大的关系。

针对基于jaccard距离的问题,直接基于在原始特征上,无法划分band,因为维度过高以及数据很稀疏,效果不好。

这时候,就需要将数据降维,便于高效处理。

minhash、simhash从不同的角度解决这个问题。



你可能感兴趣的:(R,DW)