參考以及部分轉載:
[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】
