本篇建立在电影评分的环境下,对多位成员通过各自电影评分的情况,利用两种相似度测量(欧几里得距离和皮尔逊相关度)查看用户之间的相似度。
Python version3.4
电影种类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,推荐系统的数据集构造成。
欧几里得度量定义欧几里得空间中,点x =(x1,...,xn)和 y =(y1,...,yn)之间的距离为
(以上来自维基百科官方定义。其实欧几里得距离就类似在一个一维坐标系中两个点的距离。其中水平轴上一种item,垂直轴上一个item。
>>>from math import sqrt
>>>sqrt (pow(4.5-4, 2) + pow (1-2,2))
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))
>>>import recommendations
>>>recommendations.sim_distance(recommendations.critics,’Cathy’,’Sophie’)
0.29429805508554946
注意:python3中已经移去reload模块,创建的recommendations模块做过任何修改,保存直接用即可。
两个变量之间的皮尔逊相关系数定义为两个变量之间的协方差和标准差的商:
以上方程定义了总体相关系数, 一般表示成希腊字母ρ(rho)。基于样本对协方差和标准差进行估计,可以得到样本相关系数, 一般表示成r:
对于有些用户会给评分的电影普遍打高分,而有些用户普遍打的分低,用皮尔逊相关系数就可以更好的体现相似度,一样可以体现出两种高低趋势下对同种电影的相似偏好。
#返回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
>>> import recommendations1
>>> print (sim_pearson(critics, ‘Cathy’,’Sophie’)
0.39605901719066977
上述的方法只能先计算出任两个人之间的相似度,下面我们就来找和自己有相似品味的影评者。将该函数加入上面皮尔逊方法的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]
>>>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')]