用Python寫個簡單的推薦系統(一)
本篇建立在電影評分的環境下,對多位成員通過各自電影評分的情況,利用兩種相似度測量(歐幾里得距離和皮爾遜相關度)檢視使用者之間的相似度。
Python version3.4
1. 建立影評評分字典
電影種類6種:a,b,c,d,e,f使用者7人: Cathy, Sophie, Susie, Antonio,Marco,Jack, Leo
critics={'Cathy':{'a':2.5,'b':3.5,'c':3,'d':3.5,'e':2.5,'f':3},
'Sophie':{'a':3,'b':3.5,'c':1.5,'d':5,'e':1.5,'f':3},
'Susie':{'a':2.5,'b':3,'d':3.5,'f':4},
'Antonio':{b':3.5,'c':3,'d':4,'e':2.5,'f':4.5},
'Marco':{'a':3,'b':4,'c':2,'d':3,'e':2,'f':3},
'Jack':{'a':3,'b':4,'d':5,'e':3.5,'f':3}
'Leo':{'b':4.5,'d':4,'e':1.0}}
先儲存該檔案為recommendations.py,推薦系統的資料集構造成。
2. 關於歐幾里得距離和計算
歐幾里得度量定義歐幾里得空間中,點x =(x1,...,xn)和 y =(y1,...,yn)之間的距離為
(以上來自維基百科官方定義。其實歐幾里得距離就類似在一個一維座標系中兩個點的距離。其中水平軸上一種item,垂直軸上一個item。
3. 在python直譯器中秋歐幾里得距離例子:
>>>from math import sqrt
>>>sqrt (pow(4.5-4, 2) + pow (1-2,2))
4. 計算相似度(歐幾里得)
from math import sqrt #返回一個有關person1與person2的基於距離的相似度評價 def sim_distance(prefs,person1,person2): #得到shared_items的列表 si={} for item in prefs[person1]: if item in prefs[person2]: si[item]=1 #如果兩者沒有共同之處,則返回0 if len(si)==0: return 0 #計算所有差值的平方和 sum_of_squares= sum([pow(prefs[person1][item]-prefs[person2][item],2) for item in prefs[person1] if item in prefs[person2]]) return 1/(1+sqrt(sum_of_squares))
5. 呼叫該函式,分別傳入兩個人的名字,並計算出相似度的評價值
>>>import recommendations
>>>recommendations.sim_distance(recommendations.critics,’Cathy’,’Sophie’)
0.29429805508554946
注意:python3中已經移去reload模組,建立的recommendations模組做過任何修改,儲存直接用即可。
皮爾遜相關係數評估相似度
6. 關於皮爾遜相關係數
兩個變數之間的皮爾遜相關係數定義為兩個變數之間的協方差和標準差的商:
以上方程定義了總體相關係數, 一般表示成希臘字母ρ(rho)。基於樣本對協方差和標準差進行估計,可以得到樣本相關係數, 一般表示成r:
對於有些使用者會給評分的電影普遍打高分,而有些使用者普遍打的分低,用皮爾遜相關係數就可以更好的體現相似度,一樣可以體現出兩種高低趨勢下對同種電影的相似偏好。
7. 用皮爾遜相關度定義函式
#返回p1和p2的皮爾遜相關係數
def sim_pearson (prefs,person1,person2):
si={}
for item in prefs[person1]:
if item in prefs[person2]: si[item]=1
n=len(si)
if n==0:return 1
sum1=sum([prefs[person1][it] for it in si])
sum2=sum([prefs[person2][it] for it in si])
sum1Sq=sum([pow(prefs[person1][it],2)for it in si])
sum2Sq=sum([pow(prefs[person2][it],2)for it in si])
pSum=sum([prefs[person1][it]*prefs[person2][it] for it in si])
#calculate the pearsonvlaue
num=pSum-(sum1*sum2/n)
den=sqrt((sum1Sq-pow(sum1,2)/n)*(sum2Sq-pow(sum2,2)/n))
if den==0: return 0
r=num/den
return r
為區別歐幾里得距離的py檔案,皮爾遜的另存為recommendations1.py
8. 用皮爾遜相關係數的recommendations1 模組求相關評價值
>>> import recommendations1
>>> print (sim_pearson(critics, ‘Cathy’,’Sophie’)
0.39605901719066977
9. 相似度排名列表
上述的方法只能先計算出任兩個人之間的相似度,下面我們就來找和自己有相似品味的影評者。將該函式加入上面皮爾遜方法的recommendations1.py中,得到一個人員的有序列表。
def topmatches (prefs,person,n,similarity=sim_pearson):
scores=[(similarity(prefs,person,other),other)
for other in prefs if other!=person]
scores.sort()#sort the similarity
scores.reverse()
return scores[0:n]
10. 得到有關影評者相似度評價值的列表
>>>import recommendations1
>>>recommendation1s.topmatches(critics,’Leo’,5)
得到結果(皮爾遜相關度):
[(1.0, 'Marco'),(0.9912407071619299, 'Cathy'), (0.66284898035987, 'Jack'),(0.38124642583151164, 'Sophie'), (0, 'Antonio')]
如果在之前的歐幾里得距離的recommendations.py中得到人員的有序列表,則:
def topmatches (prefs,person,n,similarity=sim_distance):
scores=[(similarity(prefs,person,other),other)
for other in prefs if other!=person]
scores.sort()#sort the similarity
scores.reverse()
return scores[0:n]
>>>import recommendations
>>>recommendations.topmatches(critics,’Leo’,5)
得到結果:
[(0.5, 'Antonio'),(0.4721359549995794, 'Marco'), (0.38742588672279304, 'Susie'), (0.3483314773547883, 'Cathy'), (0.2674788903885893, 'Jack')]