各種相似度計算的python實現
前言
在數據挖掘中有很多地方要計算相似度,比如聚類分析和協同過濾。計算相似度的有許多方法,其中有歐幾里德距離、曼哈頓距離、Jaccard系數和皮爾遜相關度等等。我們這里把一些常用的相似度計算方法,用python進行實現以下。如果是初學者,我認為把公式先寫下來,然后再寫代碼去實現比較好。
歐幾里德距離
幾個數據集之間的相似度一般是基於每對對象間的距離計算。最常用的當然是歐幾里德距離,其公式為:
#-*-coding:utf-8 -*- #計算歐幾里德距離: def euclidean(p,q): #如果兩數據集數目不同,計算兩者之間都對應有的數 same = 0 for i in p: if i in q: same +=1 #計算歐幾里德距離,並將其標准化 e = sum([(p[i] - q[i])**2 for i in range(same)]) return 1/(1+e**.5)
我們用數據集可以去算一下:
p = [1,3,2,3,4,3] q = [1,3,4,3,2,3,4,3] print euclidean(p,q)
得出結果是:0.261203874964
皮爾遜相關度
幾個數據集中出現異常值的時候,歐幾里德距離就不如皮爾遜相關度‘穩定’,它會在出現偏差時傾向於給出更好的結果。其公式為:
-*-coding:utf-8 -*- #計算皮爾遜相關度: def pearson(p,q): #只計算兩者共同有的 same = 0 for i in p: if i in q: same +=1 n = same #分別求p,q的和 sumx = sum([p[i] for i in range(n)]) sumy = sum([q[i] for i in range(n)]) #分別求出p,q的平方和 sumxsq = sum([p[i]**2 for i in range(n)]) sumysq = sum([q[i]**2 for i in range(n)]) #求出p,q的乘積和 sumxy = sum([p[i]*q[i] for i in range(n)]) # print sumxy #求出pearson相關系數 up = sumxy - sumx*sumy/n down = ((sumxsq - pow(sumxsq,2)/n)*(sumysq - pow(sumysq,2)/n))**.5 #若down為零則不能計算,return 0 if down == 0 :return 0 r = up/down return r
用同樣的數據集去計算:
p = [1,3,2,3,4,3] q = [1,3,4,3,2,3,4,3] print pearson(p,q)
得出結果是:0.00595238095238
曼哈頓距離
曼哈頓距離是另一種相似度計算方法,不是經常需要,但是我們仍然學會如何用python去實現,其公式為:
#-*-coding:utf-8 -*- #計算曼哈頓距離: def manhattan(p,q): #只計算兩者共同有的 same = 0 for i in p: if i in q: same += 1 #計算曼哈頓距離 n = same vals = range(n) distance = sum(abs(p[i] - q[i]) for i in vals) return distance
用以上的數據集去計算:
p = [1,3,2,3,4,3] q = [1,3,4,3,2,3,4,3] print manhattan(p,q)
得出結果為4
Jaccard系數
當數據集為二元變量時,我們只有兩種狀態:0或者1。這個時候以上的計算相似度的方法就無法派上用場,於是我們引出Jaccard系數,這是一個能夠表示兩個數據集都是二元變量(也可以多元)的相似度的指標,其公式為:
#-*-coding:utf-8 -*- # 計算jaccard系數 def jaccard(p,q): c = [a for i in p if v in b] return float(len(c))/(len(a)+len(b)-len(b)) #注意:在使用之前必須對兩個數據集進行去重
我們用一些特殊的數據集去測試一下:
p = ['shirt','shoes','pants','socks'] q = ['shirt','shoes'] print jaccard(p,q)
得出結果是:0.5
Tanimoto系數
Tanimoto系數是一種度量兩個集合之間相似程度的方法(與Jaccard 系數相似,但不是完全相同)。其主要用於二元變量或者多元變量之間的數據集之間的相似度計算,其公式為:
#-*-coding:utf-8-*- def tanimoto(p,q): c = [v for v in p if v in q] return float(len(c) / (len(a) + len(b) - len(c)))
當比較的數據集的數據集合中的元素都是相異的時候,Jaccard系數與Tanimoto系數相同。
參考:《集體智慧編程》
《數據挖掘:概念與技術》