天天看點

【Python】用zip函數求歐氏距離、餘弦相似度

首先歐氏距離,如此高大上的名稱,其實大家都學過的也就是坐标系,或者說是N維向量坐标系的兩點之間的距離^_^。也被稱作“歐幾裡得度量”。

在二維坐标系,公式是這樣:

【Python】用zip函數求歐氏距離、餘弦相似度

在N維坐标是,公式就是:

【Python】用zip函數求歐氏距離、餘弦相似度

而餘弦相似度,就是兩個向量的夾角餘弦值,這個數值常用來評估他們的相似度,具體的公式如下:

【Python】用zip函數求歐氏距離、餘弦相似度

,換算成具體的數值就是:

【Python】用zip函數求歐氏距離、餘弦相似度

也就是說具體為兩個向量的點乘積(數量積、内積)除于各自的模之積

當然,本文不是來介紹數學,是介紹怎麼用python快速地,用幾行的代碼就搞掂這個求解。

首先要先介紹python的zip函數,其作用是将同長度的數組tuple(小括号表示的東東)、清單list(中括号表示的東東)的各項組成一個新的由tuple組成的例子,

還是直接上代碼吧,比如下述的一段代碼:

#-*-coding:utf-8-*-
x=[1,2,3];
y=[4,5,6];
z=[7,8,9];
print zip(x,y,z);
           

運作結果如下:

【Python】用zip函數求歐氏距離、餘弦相似度

這樣,有了zip函數就可以為我們同時周遊兩個數組、清單List的寫作提供了友善。for a,b,c in zip(x,y,z)就成了foreach List x,y,z,也就是對于x,y,z的第i項怎麼怎麼樣。

是以,上面的N維向量的歐式距離的求解是變成這樣:

#-*-coding:utf-8-*-
def distance(vector1,vector2):
    d=0;
    for a,b in zip(vector1,vector2):
        d+=(a-b)**2;
    return d**0.5;
    
v1=(1,1,1);
v2=(-1,-1,-1);
print distance(v1,v2);

v3=(1,1);
v4=(-1,-1);
print distance(v3,v4);
           

運作結果如下:

【Python】用zip函數求歐氏距離、餘弦相似度

上面的結果一個是 兩倍根号3,另一個是兩倍根号2。

結果很顯然是對的,比較(1,1)與(-1,-1)兩點距離如下圖就是兩倍根号2。

【Python】用zip函數求歐氏距離、餘弦相似度

餘弦相似度同理,根據公式我們可以得到如下的程式:

#-*-coding:utf-8-*-
def cos(vector1,vector2):
    dot_product = 0.0;
    normA = 0.0;
    normB = 0.0;
    for a,b in zip(vector1,vector2):
        dot_product += a*b
        normA += a**2
        normB += b**2
    if normA == 0.0 or normB==0.0:
        return None
    else:
        return dot_product / ((normA*normB)**0.5)
    
    
v1=(1,1);
v2=(-1,-1);
print cos(v1,v2);

v3=(0,1,1);
v4=(0,-1,1);
print cos(v3,v4);
           

運作結果如下:

【Python】用zip函數求歐氏距離、餘弦相似度

很顯然,你從我徒手搞出那個坐标系草圖就可以看出v1=(1,1)與v2=(-1,-1)是兩個互為平行,從原點反方向延伸出來的兩個向量,夾角顯然為180度,cos 180度=-1這很正确。

之後v3=(0,1,1)與v4=(0,-1,1)是三維坐标系上互為垂直的兩個向量,cos 90度=0,這是顯然的。

這可以說明v1與v2兩個向量簡直就是兩個不可調和的沖突,而v3與v4則是毫無關系的兩個向量,你可以這樣了解。