相似度算法——余弦相似度;1)理论基础;2)举例;3)一些拓展思考
参考以及部分转载:
[1] 牧野之歌, 相似度算法之余弦相似度, CSDN, https://blog.csdn.net/zz_dd_yy/article/details/51926305.
[2] 京东云成都, 余弦相似度度量,CSDN,https://blog.csdn.net/u012160689/article/details/15341303
1、理论基础:
1)求余弦相似度,等价于计算求给定的两个向量之间夹角的余弦值。
(例如:两个向量之间的夹角越接近0,则两个向量的余弦值越接近1,表示两个向量方向越相似,则两个向量越相似)
2)余弦值求法:(如图1、图2)
图1 直角三角形
cosθ = a/c
图2 普通三角形
cosθ = (a^2 + b^2 + c^2) / (2*a*b)
3)若给定a(x1, y1), b(x2, y2), 则计算余弦相似度方法为:
cosθ = a · b / ( ||a||*||b|| )
= (x1, y1) · (x2, y2) / (sqrt(x1^2+ y1^2) + sqrt(x2^2+ y2^2))
2、举例(这部分直接转载):
1)NLP中计算文本相似度:
句子A:这只皮靴号码大了。那只号码合适
句子B:这只皮靴号码不小,那只更合适
基本思路是:如果这两句话的用词越相似,它们的内容就应该越相似。因此,可以从词频入手,计算它们的相似程度。
Step1, 分词。
句子A:这只/皮靴/号码/大了。那只/号码/合适。
句子B:这只/皮靴/号码/不/小,那只/更/合适。
Step2, 列出所有的词。
这只,皮靴,号码,大了。那只,合适,不,小,很
Step3,计算词频。
这只 | 皮靴 | 号码 | 大了 | 那只 | 合适 | 不 | 小 | 很 | |
句子A | 1 | 1 | 2 | 1 | 1 | 1 | 0 | 0 | 0 |
句子B | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 |
Step4,写出词频向量。
句子A:(1,1,2,1,1,1,0,0,0)
句子B:(1,1,1,0,1,1,1,1,1)
Step5,计算两个句子向量的向量余弦值
Step6, 结论:计算结果中夹角的余弦值为0.81非常接近于1,所以,上面的句子A和句子B是基本相似的
2)改进的余弦相似度计算方法:
情景:用户对内容评分,按5分制,X和Y两个用户对两个内容的评分分别为(1,2)和(4,5),使用余弦相似度得到的结果是0.98,两者极为相似。
分析:但从评分上看X似乎不喜欢2这个 内容,而Y则比较喜欢,余弦相似度对数值的不敏感导致了结果的误差。
改进方法:调整余弦相似度,将所有维度上的数值都减去一个均值,比如X和Y的评分均值都是3,那么调整后为(-2,-1)和(1,2),再用余弦相似度计算,得到-0.8,相似度为负值并且差异不小,但显然更加符合现实。
3、一些拓展思考:
1)按NLP中的使用情况看:对于句子:“我今天吃了饭”和“今天我吃了饭”相似度为1。那么我们可以想到,在论文查重去重的时候,以句号为一个句子的断尾,则句中词句进行杂乱排序是没有效果的。(必须要换词换说法,比如“本文基于***”, 改为“我们根据***”)
2)按词频划分做相似度检测,它的道理在于统计相同词出现的次数组成的向量。那么词的划分应该成为一个关键。比如:“我想”和“想我”,这两句完全不同,但若划分不同,则统计词频,余弦相似度非常不同。可能会出现相似度为1的情况。
3)这种方法为什么有用呢?越多相同词出现的频率越接近,则两个向量的余弦值越大吗?(纯数学从公式看,好像是的,分子增长速度大于分母的速度,应该考虑求个极限算算增长速度)
附:具体代码实现,可参考,参考【1】