- 1、余弦相似度
余弦距離,也稱為余弦相似度,是用向量空間中兩個向量夾角的余弦值作為衡量兩個個體間差異的大小的度量。余弦值越接近1,就表明夾角越接近0度,也就是兩個向量越相似,這就叫"余弦相似性"。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
上圖兩個向量a,b的夾角很小可以說a向量和b向量有很高的的相似性,極端情況下,a和b向量完全重合。如下圖:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
如上圖可以認為a和b向量是相等的,也即a,b向量代表的文本是完全相似的,或者說是相等的。如果a和b向量夾角較大,或者反方向,可以說a向量和b向量有很低的的相似性,或者說a和b向量代表的文本基本不相似。
向量a和向量b的夾角 的余弦計算如下:
? ? ??
擴展,如果向量a和b不是二維而是n維,上述余弦的計算法仍然正確。假定a和b是兩個n維向量,a是? ,b是? ,則a與b的夾角 的余弦等于:
?
- 2、如下舉例說明利用余弦計算句子相似度
句子A:這只皮靴號碼大了。那只號碼合適
句子B:這只皮靴號碼不小,那只更合適
怎樣計算上面兩句話的相似程度?
基本思路是:如果這兩句話的用詞越相似,它們的內容就應該越相似。因此,可以從詞頻入手,計算它們的相似程度。
第一步,分詞。
句子A:這只/皮靴/號碼/大了。那只/號碼/合適。
句子B:這只/皮靴/號碼/不/小,那只/更/合適。
第二步,列出所有的詞。
這只,皮靴,號碼,大了。那只,合適,不,小,更
第三步,計算詞頻。(下面程序用的jieba分詞工具所以結果不一樣但不影響計算)
句子A:這只1,皮靴1,號碼2,大了1。那只1,合適1,不0,小0,更0
句子B:這只1,皮靴1,號碼1,大了0。那只1,合適1,不1,小1,更1
第四步,寫出詞頻向量。
句子A:(1,1,2,1,1,1,0,0,0)
句子B:(1,1,1,0,1,1,1,1,1)
第五步,利用上述公式計算
- 3、python代碼實現
1 # -*- coding: utf-8 -*- 2 """ 3 Created on Mon Jul 30 09:35:54 2018 4 5 @author: Administrator 6 """ 7 8 import jieba 9 import numpy as np 10 11 def get_word_vector(): 12 """ 13 w = np.ones((3,4)) 14 q = np.ones((3,4")) 15 print(w) 16 print(np.sum(w * q)) 17 """ 18 19 s1 = input("句子1:") 20 s2 = input("句子2:") 21 22 cut1 = jieba.cut(s1) 23 cut2 = jieba.cut(s2) 24 25 list_word1 = (','.join(cut1)).split(',') 26 list_word2 = (','.join(cut2)).split(',') 27 print(list_word1) 28 print(list_word2) 29 30 key_word = list(set(list_word1 + list_word2))#取并集 31 print(key_word) 32 33 word_vector1 = np.zeros(len(key_word))#給定形狀和類型的用0填充的矩陣存儲向量 34 word_vector2 = np.zeros(len(key_word)) 35 36 for i in range(len(key_word)):#依次確定向量的每個位置的值 37 for j in range(len(list_word1)):#遍歷key_word中每個詞在句子中的出現次數 38 if key_word[i] == list_word1[j]: 39 word_vector1[i] += 1 40 for k in range(len(list_word2)): 41 if key_word[i] == list_word2[k]: 42 word_vector2[i] += 1 43 44 print(word_vector1)#輸出向量 45 print(word_vector2) 46 return word_vector1, word_vector2 47 48 def cosine(): 49 v1, v2 = get_word_vector() 50 return float(np.sum(v1 * v2))/(np.linalg.norm(v1) * np.linalg.norm(v2)) 51 52 print(cosine())
- 4、運行結果