日萌社
人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度學習實戰(不定時更新)
Adaboost 人臉檢測:Haar特徵及積分圖、分類器的級聯
關鍵點提取:face_recognition、疲勞檢測、人臉校準、人臉數據庫
餘弦相似度/餘弦相似性
1.餘弦相似度
通過計算兩個向量的夾角餘弦值來評估他們之間的相似度。
夾角餘弦值的取值範圍在[-1,1],任何角度的餘弦值都在-1到1之間。
兩個向量之間的夾角角度的餘弦值(餘弦相似度的值)確定兩個向量是否大致指向相同的方向,與向量的的長度無關,僅僅與向量的指向方向相關。
兩個向量之間夾角爲0°的話,餘弦值(餘弦相似度的值)爲1,代表兩個向量的指向方向相同。
兩個向量之間夾角爲90°的話,餘弦值(餘弦相似度的值)爲0,代表兩個向量的指向方向垂直。
兩個向量之間夾角爲180°的話,餘弦值(餘弦相似度的值)爲-1,代表兩個向量的指向方向相反。
餘弦相似度通常用於正空間,因此給出的值爲0到1之間,通常用於文本挖掘中的文件比較。
一個向量空間中兩個向量夾角間的餘弦值作爲衡量兩個個體之間差異的大小,餘弦值接近1,夾角趨於0,表明兩個向量越相似;
餘弦值接近於0,夾角趨於90度,表明兩個向量越不相似。
2.餘弦相似度,又稱爲餘弦相似性,是通過計算兩個向量的夾角餘弦值來評估他們的相似度。
餘弦相似度將向量根據座標值,繪製到向量空間中,如最常見的二維空間。
餘弦相似度用於評估兩個向量的夾角的相似度。
餘弦值的範圍在[-1,1]之間,值越趨近於1,代表兩個向量的方向越接近;越趨近於-1,他們的方向越相反;接近於0,表示兩個向量近乎於正交。
最常見的應用就是計算文本相似度。將兩個文本根據他們詞,建立兩個向量,計算這兩個向量的餘弦值,就可以知道兩個文本在統計學方法中他們的相似度情況。
實踐證明,這是一個非常有效的方法。
3.餘弦相似性通過測量兩個向量的夾角的餘弦值來度量它們之間的相似性。0度角的餘弦值是1,而其他任何角度的餘弦值都不大於1;並且其最小值是-1。
從而兩個向量之間的角度的餘弦值確定兩個向量是否大致指向相同的方向。兩個向量有相同的指向時,餘弦相似度的值爲1;
兩個向量夾角爲90°時,餘弦相似度的值爲0;兩個向量指向完全相反的方向時,餘弦相似度的值爲-1。
這結果是與向量的長度無關的,僅僅與向量的指向方向相關。餘弦相似度通常用於正空間,因此給出的值爲-1到1之間。
注意這上下界對任何維度的向量空間中都適用,而且餘弦相似性最常用於高維正空間。
例如在信息檢索中,每個詞項被賦予不同的維度,而一個維度由一個向量表示,其各個維度上的值對應於該詞項在文檔中出現的頻率。
餘弦相似度因此可以給出兩篇文檔在其主題方面的相似度。
另外,它通常用於文本挖掘中的文件比較。此外,在數據挖掘領域中,會用到它來度量集羣內部的凝聚力。
4.兩個向量間的餘弦值可以通過使用歐幾里得點積公式求出:
給定兩個屬性向量,A和B,其餘弦相似性θ由點積和向量長度給出,如下所示:
給出的相似性範圍從-1到1:-1意味着兩個向量指向的方向正好截然相反,1表示它們的指向是完全相同的,0通常表示它們之間是獨立的,
而在這之間的值則表示中間的相似性或相異性。
對於文本匹配,屬性向量A和B通常是文檔中的詞頻向量。餘弦相似性,可以被看作是在比較過程中把文件長度正規化的方法。
在信息檢索的情況下,由於一個詞的頻率(TF-IDF權)不能爲負數,所以這兩個文檔的餘弦相似性範圍從0到1。並且,兩個詞的頻率向量之間的角度不能大於90°。
5.角相似性
“餘弦相似性”一詞有時也被用來表示另一個係數,儘管最常見的是像上述定義那樣的。透過使用相同計算方式得到的相似性,
向量之間的規範化角度可以作爲一個範圍在[0,1]上的有界相似性函數,從上述定義的相似性計算如下:
這式子適用於向量係數可以爲正或負的情況。或者,用以下式子計算
這式子適用於向量係數總爲正的情況。
雖然“餘弦相似性”一詞有時會用來表示這個角距離,但實際上很少這樣說,因爲角度的餘弦值只是作爲一種計算角度的簡便方法而被用到,
本身並不是意思的一部分。角相似係數的優點是,當作爲一個差異係數(從1減去它)時,產生的函數是一個嚴格距離度量,
而對於第一種意義的“餘弦相似性”則不然。然而,對於大多數的用途,這不是一個重要的性質。若對於某些情況下,
只有一組向量之間的相似性或距離的相對順序是重要的,那麼不管是使用哪個函數,所得出的順序都是一樣的。
6.與“Tanimoto”係數的混淆
有時,餘弦相似性會跟一種特殊形式的、有着類似代數形式的相似係數相混淆:
事實上,這個代數形式是首先被Tanimoto定義,作爲在所比較集合由位元向量表示時計算其Jaccard係數的方法。
雖然這公式也可以擴展到向量,它具有和餘弦相似性頗爲不同的性質,並且除了形式相似外便沒有什麼關係。
7.Ochiai係數
這個係數在生物學中也叫Ochiai係數,或Ochiai-Barkman係數:
這裏A和B是集合,n(A)是A的元素個數。如果集合由位元向量所代表,那麼可看到Ochiai係數跟餘弦相似性是等同的。
8.計算餘弦值推導
1.餘弦函數在三角形中的計算公式爲
a和b代表兩個向量(向量是在空間中具有大小和方向的量,在數據計量中表示帶箭頭的線段)
2.二維空間的餘弦函數的公式:將a、b兩個向量二維化,通過餘弦定理與二維空間結合,即可推導出來二維空間下計算兩個向量的餘弦相似性公式。
上圖中向量a用座標(x1,y1)表示,向量b用座標(x2,y2)表示。向量a和向量b在直角座標中的長度分別爲
向量a和向量b之間的距離我們用向量c表示,那麼向量c在直角座標系中的長度爲
將a,b,c帶入三角函數的公式中便得到了直角座標系中向量表示的三角形的餘弦函數。
二維向量圖和餘弦定理的結合:
3.多維空間的餘弦函數的公式
9.計算餘弦相似度例子一
1.餘弦相似度量:計算個體間的相似度。
相似度越小,距離越大。相似度越大,距離越小。
2.假設有3個物品,item1,item2和item3,用向量表示分別爲:item1[1,1,0,0,1],item2[0,0,1,2,1],item3[0,0,1,2,0]。
3.用歐式距離公式計算item1、itme2之間的距離,以及item2和item3之間的距離,分別是:
4.用餘弦函數計算item1和item2夾角間的餘弦值爲:
5.用餘弦函數計算item2和item3夾角間的餘弦值爲:
6.由此可得出item1和item2相似度小,兩個之間的距離大(距離爲7),item2和itme3相似度大,兩者之間的距離小(距離爲1)。
7.餘弦相似度算法:
一個向量空間中兩個向量夾角間的餘弦值作爲衡量兩個個體之間差異的大小,餘弦值接近1,夾角趨於0,表明兩個向量越相似;
餘弦值接近於0,夾角趨於90度,表明兩個向量越不相似。
10.計算餘弦相似度例子二
1.使用餘弦相似度計算兩段文本的相似度。
思路:1、對原文進行jieba中文分詞;
2、set中去重後存儲所有詞,並使用dict字段存儲set中元素值(key)和索引值(value);
3、中文分詞進行編碼:每個中文分詞轉換爲出現在set中的索引值;
4、詞頻向量化:即計算每個分詞出現的次數,通過oneHot編碼對分詞進行編碼來計算詞頻,從而得到兩個句子分別的詞頻向量;
5、根據餘弦相似度的公式分別計算出兩個句子的的相似度,即計算兩個句子分別的詞頻向量之間夾角的餘弦值,值越大相似度越高。
2.原文句子A:這隻皮靴號碼大了。那隻號碼合適。
原文句子B:這隻皮靴號碼不小,那隻更合適。
3.分詞
使用jieba分詞對上面兩個原文句子分詞後,分別得到兩個列表:
listA=['這', '只', '皮靴', '號碼', '大', '了', '那', '只', '號碼', '合適']
listB=['這', '只', '皮靴', '號碼', '不小', '那', '只','更合', '合適']
3.列出所有詞,將listA和listB放在一個set中,set中去重後得到:
set={'不小', '了', '合適', '那', '只', '皮靴', '更合', '號碼', '這', '大'}
將上述set轉換爲dict,key爲set中的詞,value爲set中詞出現的索引位置。
dict1={'不小': 0, '了': 1, '合適': 2, '那': 3, '只': 4, '皮靴': 5, '更合': 6, '號碼': 7, '這': 8, '大': 9},
可以看出“不小”這個詞在set中排第1,下標爲0。
4.將listA和listB中的中文分詞進行編碼,將每個中文分詞轉換爲出現在set中的索引值,轉換後爲:
listAcode=[8, 4, 5, 7, 9, 1, 3, 4, 7, 2]
listBcode=[8, 4, 5, 7, 0, 3, 4, 6, 2]
我們來分析listAcode,結合dict1,得知元素值8對應的字是“這”,元素值4對應的字是“只”,元素值9對應的字是“大”,就是句子A和句子B轉換爲用set中的索引值來表示。
5.對listAcode和listBcode進行oneHot編碼,就是計算每個分詞出現的次數。
詞頻向量化:即計算每個分詞出現的次數,通過oneHot編碼對分詞進行編碼來計算詞頻,從而得到兩個句子分別的詞頻向量。
oneHot編號後得到的結果如下:
listAcodeOneHot = [0, 1, 1, 1, 2, 1, 0, 2, 1, 1]
listBcodeOneHot = [1, 0, 1, 1, 2, 1, 1, 1, 1, 0]
6.根據餘弦相似度的公式分別計算出兩個句子的的相似度,即計算兩個句子分別的詞頻向量之間夾角的餘弦值,值越大相似度越高。
7.流程圖
11.實現餘弦相似度的代碼
import jieba
import math
s1 = '這隻皮靴號碼大了。那隻號碼合適'
s1_cut = [i for i in jieba.cut(s1, cut_all=True) if i != '']
s2 = '這隻皮靴號碼不小,那隻更合適'
s2_cut = [i for i in jieba.cut(s2, cut_all=True) if i != '']
print(s1_cut) #['這', '只', '皮靴', '號碼', '大', '了', '那', '只', '號碼', '合適']
print(s2_cut)#['這', '只', '皮靴', '號碼', '不小', '那', '只', '更合', '合適']
#兩個set分別對中文切割後的數組元素進行去重,然後兩個set聯合union放到一起組成一個新的set
word_set = set(s1_cut).union(set(s2_cut))
print(word_set)#{'只', '合適', '不小', '更合', '號碼', '皮靴', '這', '了', '大', '那'}
word_dict = dict()
i = 0
#構建dict字典中的key爲set中的每個中文單詞,value爲set中的該中文單詞的索引值
for word in word_set:
word_dict[word] = i
i += 1
print(word_dict) #{'只': 0, '合適': 1, '不小': 2, '更合': 3, '號碼': 4, '皮靴': 5, '這': 6, '了': 7, '大': 8, '那': 9}
#把原文中每個中文單詞作爲key對應的從dict字典中取出對應的value,值爲set中的該中文單詞的索引值
s1_cut_code = [word_dict[word] for word in s1_cut]
print(s1_cut_code) #[6, 0, 5, 4, 8, 7, 9, 0, 4, 1]
#把原文中每個中文單詞作爲key對應的從dict字典中取出對應的value,值爲set中的該中文單詞的索引值
s2_cut_code = [word_dict[word] for word in s2_cut]
print(s2_cut_code) #[6, 0, 5, 4, 2, 9, 0, 3, 1]
#重新創建一個新的和dict字典鍵值對數量相同的初始化值爲0的數組
s1_cut_code = [0]*len(word_dict)
#oneHot編碼:計算原文中每個中文分詞出現的次數,即能得到原文句子的詞頻向量
#根據原文中相同中文單詞出現的重複次數記錄到新數組中,出現次數要記錄到的索引位置爲該中文單詞在set中索引值,或者說dict字典中的該中文單詞作爲key對應的value
for word in s1_cut:
s1_cut_code[word_dict[word]]+=1
print(s1_cut_code)#[2, 1, 0, 0, 2, 1, 1, 1, 1, 1]
#重新創建一個新的和dict字典鍵值對數量相同的初始化值爲0的數組
s2_cut_code = [0]*len(word_dict)
#oneHot編碼:計算原文中每個中文分詞出現的次數,即能得到原文句子的詞頻向量
#根據原文中相同中文單詞出現的重複次數記錄到新數組中,出現次數要記錄到的索引位置爲該中文單詞在set中索引值,或者說dict字典中的該中文單詞作爲key對應的value
for word in s2_cut:
s2_cut_code[word_dict[word]]+=1
print(s2_cut_code)#[2, 1, 1, 1, 1, 1, 1, 0, 0, 1]
# 計算餘弦相似度
sum = 0
sq1 = 0
sq2 = 0
#通過計算餘弦值的公式cos(θ)= (x1*x2 + y1*y2) / sqrt(pow(x1,2)+pow(y1,2)) * sqrt(pow(x2,2)+pow(y2,2))
#pow(x,y)函數用於求 x 的 y 次方
for i in range(len(s1_cut_code)):
#計算(x1*x2 + y1*y2):x1*x2或y1*y2均代表詞頻向量s1_cut_code中的元素值 乘以 詞頻向量s2_cut_code中的元素值
sum += s1_cut_code[i] * s2_cut_code[i]
#計算pow(x1,2)+pow(y1,2):代表求詞頻向量s1_cut_code中的每個元素值的2次方
sq1 += pow(s1_cut_code[i], 2)
#計算pow(x2,2)+pow(y2,2):代表求詞頻向量s2_cut_code中的每個元素值的2次方
sq2 += pow(s2_cut_code[i], 2)
try:
#sqrt() 計算平方根,即開平方
#round(浮點數x,四捨五入要保留的小數位) 方法返回浮點數x的四捨五入值。
#計算出餘弦值的結果cos(θ)= (x1*x2 + y1*y2) / sqrt(pow(x1,2)+pow(y1,2)) * sqrt(pow(x2,2)+pow(y2,2))
result = round(float(sum) / (math.sqrt(sq1) * math.sqrt(sq2)), 2)
except ZeroDivisionError:
result = 0.0
print(result) #0.81