常見距離度量和相似度度量

一.距離度量:歐氏(P)、曼哈頓(P)、切比雪夫(P)

1:歐幾里得距離Euclidean Distance。用于衡量各點間的絕對距離。比如在二維坐標系中點A(x1,y1),B(x2,y2),他們的歐幾里得距離就是

,用坐標來直觀表示吧。推廣到n維坐標,A(x1,x2,x3……),B(y1,y2,y3……)歐幾里得距離則是

X、Y必須是同一特徵的不同值,如同是身高或同時體重

n=1,直線上兩點的距離

n=2,二維坐標系中兩點的距離

n=3,三維坐標系中兩點的距離

#歐氏距離計算用戶相似度#歐氏距離=sqrt(sum(pow(xs-ys,2)))#相似度=1/(1+歐氏距離)defsim_distance(prefs,person1,person2):si = {}forit inprefs[person1]:ifit inprefs[person2]:si[it] =1iflen(si) ==0:return0pSum =math.sqrt(sum(pow(prefs[person1][it]-prefs[person2][it],2)forit insi))return1.0/(1+pSum)

2:曼哈頓距離:Manhattan Distance。這個曼哈頓距離也稱作「城市街區距離」.

#曼哈頓距離計算用戶相似度#曼哈頓距離=sum|xi-yi|#相似度=1/1+曼哈頓距離def sim_manhattan(prefs,person1,person2): si = {} for it in prefs[person1]: ifit inprefs[person2]: si[it] =1 iflen(si) ==0: return 0 pSum =sum(math.fabs(prefs[person1][it]-prefs[person2][it])forit insi) return 1.0/(1+pSum)

3、切比雪夫距離:Chebyshev Distance

相當於從A(x1, y1)到B(x2, y2)最少要走的步數

#切比雪夫距離計算用戶相似度#切比雪夫距離=max|xi-yi|#相似度=1.0/(1+切比雪夫距離)def sim_chebyshev(prefs,person1,person2): si = {} for it in prefs[person1]: if it in prefs[person2]: si[it] =1 if len(si) ==0: return 0 pSum =max(math.fabs(prefs[person1][it]-prefs[person2][it])forit insi) return1.0/(1+pSum)

二.相似度度量:餘弦(P) 、調整餘弦(P) 、皮爾遜(P) 、Jaccard(P)

1、餘弦相似度:Cosine Similarity

相當於計算向量夾角的餘弦值,以此作為兩個個體間相似度大小的衡量

#餘弦係數計算用戶相似度#餘弦相似度=sum(rxs * rys)/sqrt(rxs2 * rys2),其中s為AnBdef sim_cos(prefs,person1,person2): si = {} for it in prefs[person1]: if it in prefs[person2]: si[it] =1 if len(si) ==0: re turn0 pSum =sum([prefs[person1][it]*prefs[person2][it]forit insi]) sum1Sq =sum([pow(prefs[person1][it],2)forit insi]) sum2Sq =sum([pow(prefs[person2][it],2)forit insi]) den =math.sqrt(sum1Sq *sum2Sq) if den ==0: return 0 r =float(pSum)/den return r

2、調整餘弦相似度:Adjusted Cosine Similarity

相當於計算向量夾角的餘弦值,以此作為兩個個體間相似度大小的衡量,由於餘弦相似度對數值不敏感,如個體X、Y對兩個條目的評分分別為(1,2)、(4,5),其餘弦相似度為0.98,調整後需要減去各自的均值,計算相似度為-0.8.通過求出每位用戶的平均打分,調整評分向量為評分偏差向量,再求解餘弦相似度。

#調整餘弦係數計算用戶相似度#其中s屬於AnB,i屬於A,j屬於B;和皮爾遜的差異在分母def sim_ajcos(prefs,person1,person2): si = {} for it in prefs[person1]: if it in prefs[person2]: si[it] =1 if len(si) ==0: return 0 avg1 =float(sum(prefs[person1][it]forit inprefs[person1]))/len(prefs[person1]) avg2 =float(sum(prefs[person2][it]forit inprefs[person2]))/len(prefs[person2]) pSum =sum([(prefs[person1][it]-avg1)*(prefs[person2][it]-avg2)forit insi]) sum1Sq =sum([pow(prefs[person1][it]-avg1,2)forit inprefs[person1]]) sum2Sq =sum([pow(prefs[person2][it]-avg2,2)forit inprefs[person2]]) den =math.sqrt(sum1Sq *sum2Sq) if den ==0: return 0 r =float(pSum)/den return r

3:皮爾遜相關係數。

即為相關分析中的相關係數r,分別對X和Y基於自身總體標準化後計算兩個向量夾角的餘弦值。相當於對數據進行中心化處理,即數據移動了一個樣本平均值以使其均值為零。

。cov(x,y)表示協方差,E(x)和μx表示期望,σ表示標準差。第二個是相對於樣本,代碼中即是樣本公式:,最後一個公式是代碼中的公式。

#皮爾遜相關係數計算用戶相似度#通用的方法,下面一種只是本方法在某些情況下的特例def sim_pearson(prefs,p1,p2): si={} for item in prefs[p1]: if item in prefs[p2]: si[item]=1 if len(si)==0: return 0 n=len(si) #計算開始 sum1=sum([prefs[p1][it] for it in si]) sum2=sum([prefs[p2][it] for it in si]) sum1Sq=sum([pow(prefs[p1][it],2) for it in si]) sum2Sq=sum([pow(prefs[p2][it],2) for it in si]) pSum=sum([prefs[p1][it]*prefs[p2][it] for it in si]) num=pSum-(sum1*sum2/n) den=math.sqrt((sum1Sq-pow(sum1,2)/n)*(sum2Sq-pow(sum2,2)/n)) #計算結束 if den==0: return 0 r=num/den return r

#皮爾遜相關係數計算用戶相似度#通用的方法,下面一種只是本方法在某些情況下的特例def sim_stdpearson(prefs,person1,person2): si = {} for it in prefs[person1]: if it in prefs[person2]: si[it] = 1 lensi = len(si) if lensi == 0: return 0 sum1 = sum(prefs[person1][it] for it in prefs[person1]) sum2 = sum(prefs[person2][it] for it in prefs[person2]) avg1 = float(sum1)/len(prefs[person1]) avg2 = float(sum2)/len(prefs[person2]) sum1Sq = sum([pow(prefs[person1][it]-avg1,2) for it in si]) sum2Sq = sum([pow(prefs[person2][it]-avg2,2) for it in si]) pSum = sum([(prefs[person1][it]-avg1)*(prefs[person2][it]-avg2) for it in si]) den = math.sqrt(sum1Sq*sum2Sq) if den == 0: return 0 r = pSum/den return r

4、Jaccard相似度(狹義)。還存在一個廣義Jaccard相似度,狹義Jaccard相似度在某些方面並不大適用,因為它只能判斷兩者中的元素是否一致,拿上例中的電影例子來說就是,小明對有且只有對三個電影做出了評價,同樣小紅也是有且只有對三個電影做出了評價,注意是做出了評價,而不是做出了什麼評價,這個時候他們的相似度就是1,也就是相同。公式:

#Jaccard計算用戶相似度#Jaccard=|AnB|/|AuB|def sim_jaccard(prefs,person1,person2): si_union = {}#並集 si_inter = {}#交集 si_union =dict(prefs[person1],**prefs[person2]) for it in prefs[person1]: if it in prefs[person2]: si_inter[it] =min(prefs[person1][it],prefs[person2][it]) sum1 =sum(si_inter[it]for it in si_inter) sum2 =sum(si_union[it]for it in si_union) if sum2 ==0: return 0 r =float(sum1)/sum2 return r

餘弦、調整餘弦、皮爾遜相似度均適用於:基於用戶相似度的CF和基於產品相似度的CF;

區別在於:前者是基於評分矩陣中的行向量相似度求解,而後者是基於評分矩陣中的列向量相似度求解。

數據稀疏問題

數據稀疏的一種解決方法:填充

基於用戶評分:填充對應用戶(行)的均值

基於產品評分:填充對應產品(列)的均值


推薦閱讀:

希爾伯特空間無限維空間 內積空間完備的空間 膜世界高次元空間 基底量子力學表象 態狄拉克符號
好的關係,都有距離感
4· 法律講堂|舉例證明,委託代理的法律風險

TAG:Python | 相似度計算 | 距離 |