python协同过滤可以预测吗_基于用户的协同过滤python代码实现

微信公众号:机器学习养成记在推荐算法概述中介绍了几种推荐算法的概念,但是没有具体代码实现,本篇文章首先来看一下基于用户的协同过滤python代码。

数据准备

本次案例中,我们使用用户对电影的打分数据进行演示。数据包含两个表,一个是movies表,记录了电影编号和电影名称的对应关系

另外一张是ratings表,记录了每个用户对电影的打分情况

Python代码实现

这里简述几个主要过程:数据初始化

原始数据分别通过三列记录了用户、电影及打分,无法直接满足计算需要,因此这里我们首先要将原始数据转化为字典形式,记录每个用户与电影之间的关系。

########获得初始化数据

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个用户,将这n个用户看过但是目标用户没看过的电影进行推荐。

########找到与当前用户最近的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);

最终得到结果如下:

本代码只是对算法逻辑进行了最基本实现,真实应用时还可以加入打分时间、电影分类等维度,提升预测准确率。

往期推荐:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值