在推荐算法概述中介绍了几种推荐算法的概念,但是没有具体代码实现,本篇文章首先来看一下基于用户的协同过滤python代码。
本次案例中,我们使用用户对电影的打分数据进行演示。数据包含两个表,一个是movies表,记录了电影编号和电影名称的对应关系?
另外一张是ratings表,记录了每个用户对电影的打分情况?
这里简述几个主要过程:
########获得初始化数据
def __init__(self,data):
data_dic = {}
for line in data.itertuples():
if not line[1] in data_dic.keys():
data_dic[line[1]]={line[4]:line[2]}
else:
data_dic[line[1]][line[4]]=line[2]
self.data = data_dic
########计算两个用户间距离
#pearson系数
def Pearson(self,user1,user2):
sum_xy = 0
sum_x = 0
sum_y = 0
sum_x2 = 0
sum_y2 = 0
n = 0
for key in user1:
if key in user2:
n += 1
x = user1[key]
y = user2[key]
sum_xy += x * y
sum_x += x
sum_y += y
sum_x2 += pow(x, 2)
sum_y2 += pow(y, 2)
if n == 0:
return 0
#皮尔逊相关系数计算公式
denominator = sqrt(sum_x2 - pow(sum_x, 2) / n) * sqrt(sum_y2 - pow(sum_y, 2) / n)
if denominator == 0:
return 0
else:
return (sum_xy - (sum_x * sum_y) / n) / denominator
#欧式距离
def Euclidean(self,user1,user2):
#取出两位用户评论过的电影和评分
distance = 0
#找到两位用户都评论过的电影,并计算欧式距离
for movie1,score1 in user1.items():
if movie1 in user2.items():#计算公共的电影的评分
#注意,distance越大表示两者越相似
distance += pow(float(user1[movie1])-float(user2[movie1]),2)
return 1/(1+sqrt(distance))#这里返回值越小,相似度越大
#选择计算距离方式
def getDistance(self,user1,user2,type):
if type == 'Pearson':
dis = self.Pearson(user1,user2)
if type == 'Euclidean':
dis = self.Euclidean(user1,user2)
return dis
########找到与当前用户最近的n个邻居
def nearstUser(self,username,type,n=1):
distances={};#用户,相似度
for otherUser,items in self.data.items():#遍历整个数据集
if otherUser != username:#非当前的用户
distance=self.getDistance(self.data[username],self.data[otherUser],type)#计算两个用户的相似度
distances[otherUser]=distance
sortedDistance=sorted(distances.items(),key=operator.itemgetter(1),reverse=True);#最相似的N个用户
#print ("排序后的用户为:",sortedDistance)
return sortedDistance[:n]
#给用户推荐电影
def Recomand(self,username,tp = 'Pearson',n=1):
recommand={};#待推荐的电影
for user,score in dict(self.nearstUser(username,tp,n)).items():#最相近的n个用户
#print ("推荐的用户:",(user,score))
for movies,scores in self.data[user].items():#推荐的用户的电影列表
if movies not in self.data[username].keys():#当前username没有看过
#print ("%s为该用户推荐的电影:%s"%(user,movies))
if movies not in recommand.keys():#添加到推荐列表中
recommand[movies]=scores
return sorted(recommand.items(),key=operator.itemgetter(1),reverse=True);
最终得到结果如下:
本代码只是对算法逻辑进行了最基本实现,真实应用时还可以加入打分时间、电影分类等维度,提升预测准确率。
后台回复“协同过滤用户”获得数据及完整代码