其實這個題目已經有很多人寫過了,數學之美里就有,最近阮一峰的博客里也寫了,本文基本上遵循的就是他的思路,只是讓其看起來再小白一點點。其實說白了就是用自己的話,再把同樣一件事描述一下,順便擴擴句,把其中跳躍比較大的部分再補充補充。 阮一峰的原文:http://www.ruanyifeng.com/blog/2013/03/cosine_similarity.html
當然雖然題目是比較兩篇文章的相似性,但我們也不會傻到真拿兩篇篇文章來說明,為了簡單起見,我們從句子着手。
句子A:周傑倫是一個歌手,也是一個叉叉
句子B:周傑倫不是一個叉叉,但是是一個歌手
如何比較相似性呢 ?
第一步 分詞
句子A : 周傑倫/是/一個/歌手,也/是/一個/叉叉 (注:假設分詞也是個牛叉叉,可以識別叉叉這個詞)
句子B: 周傑倫/不/是/一個/叉叉 ,但是/是/一個/歌手
第二步 去重復,列出識別的所有單詞
周傑倫、是 、不、一個、叉叉 、歌手、但是、也
第三步 計算詞頻(這里表示某個詞在一個句子里出現的次數)
句子A: 周傑倫1、是2 、不 0 、一個2、叉叉1、歌手1、但是0、也1
句子B: 周傑倫1、是2 、不 1 、一個2、叉叉1、歌手1、但是1、也0
第四步 構造詞頻向量
句子A [1 , 2 , 0 , 2 , 1 , 1 , 0 , 1] 句子B [1 , 2 , 1 , 2 , 1 , 1 , 0 , 1]
上面構造的是兩個多維的向量,其中每個維度的值就是詞頻。
OKAY,構造出了上面的二個多維向量后,比較兩句話的相似度就 變成了比較這兩個向量的相似度了。任何問題只要一變成數學問題,基本上就好解決了 :) ... ...
那么如何比較兩個向量的相似度呢 。先來點高中數學知識 。
上圖是一個二維向量的幾何表示。其中有2個二維向量a和b 。 θ 就是這2個二維向量的夾角;如果夾角為0度,意味着方向相同、線段重合;如果夾角為90度,意味着形成直角,方向完全不相似;如果夾角為180度,意味着方向正好相反。因此,我們可以通過夾角的大小,來判斷向量的相似程度。夾角越小,就代表越相似。
再復習一個初中的知識:余弦定理 (應該是初中吧)
假定a向量是[x1,y1] 。b向量是 [x2,y2]
那么可以將余弦定理改成下面的形式。
在原文中直接給了這個結果,這着實有點跳躍,給人以突兀感,主要是因為其中的推導過程給省略了,雖然推導過程確實有點小白,但我們的題目,就是將小白進行到底,所以還是在下面補出來這個過程。因為我不會畫圖所以直接使用計算機的表示法了。可能不太直觀
Cosθ = (a^2+b^2-c^2)/2abc a^2 = (x1^2+y1^2) b^2 = (x2^2+y2^2) c^2 = (x2-x1)^2 + (y2-y1)^2 (這個不難理解吧) => Cosθ = ((x1^2+y1^2) + (x2^2+y2^2) + ((x2-x1)^2 + (y2-y1)^2))/(2sqrt(x1^2+y1^2)*sqrt(x2^2+y2^2)) => Cosθ = (x1^2+y1^2+x2^2+y2^2-x2^2-x1^2+2x1x2-y2^2-y1^2+2y1y2/(2sqrt(x1^2+y1^2)*sqrt(x2^2+y2^2)) => Cosθ = (2x1x2+y1y2 )/(2sqrt(x1^2+y1^2)*sqrt(x2^2+y2^2)) => Cosθ = (x1x2+y1y2 )/(sqrt(x1^2+y1^2)*sqrt(x2^2+y2^2))
這樣結果就推出來了。
我們現在再來總結一下二維向量情況下余弦定理的規律
2個二維向量 [x1,y1] 、[x2,y2] 那么有
Cosθ = (x1x2+y1y2 )/(sqrt(x1^2+y1^2)*sqrt(x2^2+y2^2) )
我們把[x1,y1]、[x2,y2] 換成 [a1,a2] 、[b1,b2] 那么
有2個二維向量 [a1,a2] 、[b1,b2] 有
Cosθ = (a1b1+a2b2 )/(sqrt(a1^2+a2^2)*sqrt(b1^2+b2^2))
數學已經證明,余弦的這種計算擴展到多維向量也是成立的。
那么 現在我們多一個維度,假設有2個3維向量,例如 [a1,a2,a3]、[b1,b2,b3] 會是什么樣呢
Cosθ = (a1b1+a2b2 +a3b3)/(sqrt(a1^2+a2^2+a3^2)*sqrt(b1^2+b2^2+b3^2))
那么 n維是什么情況呢
Cosθ = (a1b1+a2b2 +a3b3 + .. anbn)/(sqrt(a1^2+a2^2+a3^2 + ... + an^2)*sqrt(b1^2+b2^2+b3^2 + .. + bn^2))
下圖的表示可能更直觀和簡潔一些
有了這個公式就好辦了。我們的兩個句子
句子A [1 , 2 , 0 , 2 , 1 , 1 , 0 , 1] 句子B [1 , 2 , 1 , 2 , 1 , 1 , 0 , 1]
那么他們夾角的余弦是多少呢
Cosθ = (1*1 + 2*2 + 0*1 + 2*2 + 1*1 + 1*1 + 0*0 + 1*1 )/(sqrt(1^2+2^2+0^2+2^2+1^2+1^2+0^2+1^2)*sqrt(1^2+2^2+1^2+2^2+1^2+1^2+1^2+0^2+1^2)) => Cosθ ≈0.961
這個還算是比較高的