在目前的自然语言处理、数据挖掘以及机器学习中,相似性度量算法是一种比较常用的算法,是文本计算的基础。相似性度量有助于帮助开发者发现数据关联性,其核心点在于两个方面:1.数据的特征表示。2. 集合之间的表示方法。
1. Jaccard相似系数
Jaccard index, 又称为Jaccard相似系数(Jaccard similarity coefficient),也称之为雅可比相似度系数,用于比较有限样本集之间的相似性与差异性。Jaccard系数值越大,样本相似度越高。
狭义的Jaccard相似系数
狭义的Jaccard相似系数是通过两组样本直接的交集与总集之间的比值来度量,公式如下:
当集合A,B都为空时,J(A,B)定义为1。根据上述公式,当集合A和集合B两者之间的交集越大时,表明两者之间的相似程度越高。特别的,当集合A和集合B相同时,J(A,B)为1。因此:
J(A,B)∈[0,1]
广义的Jaccard相似系数
广义的Jaccard相似系数也称作Tanimoto系数,一般用EJ表示,公式如下:
上述公式中的AB分别表示两个向量,与侠义的Jaccrad中的元素为二值数据不同,广义Jaccard可以使元素不仅是0或1,实质是狭义Jaccard系数的扩展。
2. 基于MinHash的相似性算法
Minhash是一种基于Jaccard相关系数的快速对两个几个进行相似性分析的方法。该算法起初主要用于在搜索引擎中的重复网页检测,现在也大量应用于解决大规模聚类问题。
在采用Jaccard系数进行相似度计算时,需要计算两个集合的交集和并集,在海量维度场景下,计算的时间和空间复杂度都非常巨大。而Minhash在Jaccard的基础上可以起到很好的降维效果。
采用Minhash可以起到很好的减少计算复杂度的作用,其基本原理为:对于两个集合A,B,在集合A和集合B的并集中选取元素的概率等于Jaccard系数。例如对于集合A={a, b, c},集合B={b,c,d},集合A和B的合集为{a,b,c,d},集合A和B的交集为{b,c},集合A和集合B的Jaccard系数为:0.5,而从交集{b,c}中挑选任何一个元素的概率也为:0.5,即与Jaccard系数相等。
关于MinHash,先定义几个符号术语:
h(x): 把x映射成一个整数的哈希函数。
hmin(S):集合S中的元素经过h(x)哈希后,具有最小哈希值的元素。
那么对集合A、B,hmin(A) = hmin(B)成立的条件是A ∪ B 中具有最小哈希值的元素也在 A ∩ B中。这里有一个假设,h(x)是一个良好的哈希函数,它具有很好的均匀性,能够把不同元素映射成不同的整数。所以有,Pr[hmin(A) = hmin(B)] = J(A,B),即集合A和B的相似度为集合A、B经过hash后最小哈希值相等的概率。
基于以上结论,我们便可以根据MinHash来计算两个集合的相似度了。一般有两种方法:
1:使用多个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中相同元素个数与总的元素个数的比例。
2:使用单个hash函数
第一种方法有一个很明显的缺陷,那就是计算复杂度高。使用单个hash函数是怎么解决这个问题的呢?请看:前面我们定义过 hmin(S)为集合S中具有最小哈希值的一个元素,那么我们也可以定义hmink(S)为集合S中具有最小哈希值的K个元素。这样一来我们就只需要对每个集合求一次哈希,然后取最小的K个元素。计算两个集合A、B的相似度,就是集合A中最小的K个元素与集合B中最小的K个元素的交集个数与并集个数的比例。
3. 余弦相似度
虽然MinHash减小了计算复杂度,但是实质上,Jaccard的理论基础支持还不够,因为仅仅依靠内部属性是否出现去判定两者是否相似并不够精准。因此,产生了余弦相似度,它将属性是否出现变更为属性在样本中的权重。余弦相似度是基于向量空间模型的算法,其关键字向量依赖于TF-IDF算法或者其他关键字提取算法。余弦相似度是通过计算两个向量的夹角余弦值来评估他们的相似度。余弦相似度将向量根据坐标值,绘制到向量空间中,如最常见的二维空间。
余弦相似度的计算公式如下:
余弦值的范围在[-1,1]之间,值越趋近于1,代表两个向量的方向越接近;越趋近于-1,他们的方向越相反;接近于0,表示两个向量近乎于正交。
最常见的应用就是计算文本相似度。将两个文本根据他们词,建立两个向量,计算这两个向量的余弦值,就可以知道两个文本在统计学方法中他们的相似度情况。实践证明,这是一个非常有效的方法。
4.基于SimHsh的相似性算法
SimHash是一种局部敏感的哈希算法那,可以理解为指纹码,此类指纹码不同于其他哈希算法对应的指纹码,指纹码虽然几乎唯一,但是SimHash可以使得相似的文本具有相似的哈希值。通过计算汉明距离,表达两个文本之间的相似度。这是SIMHash最重要的特征。
前面我们介绍了基于Jaccard相似系数、改进的MinHash,以及余弦相似度来度量样本间的相似性。正常情况下,余弦相似度是一种比较可取的方式,但是在现实中,采用余弦相似度面临的问题也越来越突出:
(1)余弦相似度两两计算的方式,效果虽然明显,但是计算复杂度较高。
(2)通过关键词的特征向量表达文本的特征,不易于存储。
(3)在文本单词较少时,可能会因为一两个关键词波动较大。
而SimHash可以很好的解决上述问题。
SimHash计算过程
- 分词与权重计算。将词语进行分词处理,并计算每个分词在文本中的权重。当所需处理的文本长度过长时,只需要按照权重由高到低筛选出前K个词语即可,不需要将每个词都纳入计算。
- 哈希二进制计算。对词语进行二进制转换,转换的结果可以是一个32位或64位的二进制值。
- 词语加权。在步骤1中已经得到每个词语在文中的权重,这些权重需要表现在其二进制内容中,将权重与词语的二进制值进行按位乘法,不同点在于,遇到二进制值为0时乘以权重的负数,遇到二进制值为1时乘以权重的即可。
- 合并累计。对文本中的词语进行加权计算之后,最终每个词语都会产生加权值,这些值内容代表着该词语在每个二进制位上的特征。若需计算文本的全局特征,只需将文本词语的加权值进行合并累计,该过程即可理解为将加权值按照每一位进行求和。
- 降维输出。步骤四的累加结果中,实质上已经产生了文本的特征码,但是在绝对多数情况下,该特征码不仅较长,而且内容也会各式各样,会给特征比较带来困难,因此,需要将特征码进行降维输出。降维的目的是降低特征码的复杂度,约定位值小于0的为-1,大于等于0的为1,该值即为SimHash。
SimHash目前主要用于重复信息的过滤,通过比较两个文本的汉明距离来判定两个文本的相似度。与余弦相似度相比,SimHash可以大大复杂文本的计算复杂度。