文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
10.2 基于用户的协同过滤算法在 Python 中的实现
下面通过个性化的电影推荐的例子演示基于用户的协同过滤算法在Python中的实现。现在影视已经成为大众在喜爱的休闲娱乐的方式之一,合理的个性化电影推荐一方面能够促进电影行业的发展,另一方面也可以让大众在数量众多的电影中迅速得到自己想要的电影,从而做到两全齐美。甚至更进一步,可以明确市场走向、对后续电影的类型导向等起到重要作用。
现有的部分电影评分数据如表10-1所示:
表10-1 脱敏后的电影评分数据
在Python中实现基于用户的协同过滤推荐系统首先需要计算用户之间的相关系数。实现代码如代码清单10-1所示。其中,我们自行编写了基于用户的皮尔逊相似度的协同过滤算法函数recommender.py,以方便读者参考。
代码清单10-1 协同过滤算法函数
#-*- coding: utf-8 -*- import numpy as np import pandas as pd import math def prediction(df,userdf,Nn=15):#Nn邻居个数 corr=df.T.corr(); rats=userdf.copy() for usrid in userdf.index: dfnull=df.loc[usrid][df.loc[usrid].isnull()] usrv=df.loc[usrid].mean()#评价平均值 for i in range(len(dfnull)): nft=(df[dfnull.index[i]]).notnull() #获取邻居列表 if(Nn<=len(nft)): nlist=df[dfnull.index[i]][nft][:Nn] else: nlist=df[dfnull.index[i]][nft][:len(nft)] nlist=nlist[corr.loc[usrid,nlist.index].notnull()] nratsum=0 corsum=0 if(0!=nlist.size): nv=df.loc[nlist.index,:].T.mean()#邻居评价平均值 for index in nlist.index: ncor=corr.loc[usrid,index] nratsum+=ncor*(df[dfnull.index[i]][index]-nv[index]) corsum+=abs(ncor) if(corsum!=0): rats.at[usrid,dfnull.index[i]]= usrv + nratsum/corsum else: rats.at[usrid,dfnull.index[i]]= usrv else: rats.at[usrid,dfnull.index[i]]= None return rats def recomm(df,userdf,Nn=15,TopN=3): ratings=prediction(df,userdf,Nn)#获取预测评分 recomm=[]#存放推荐结果 for usrid in userdf.index: #获取按 NA值获取未评分项 ratft=userdf.loc[usrid].isnull() ratnull=ratings.loc[usrid][ratft] #对预测评分进行排序 if(len(ratnull)>=TopN): sortlist=(ratnull.sort_values(ascending=False)).index[:TopN] else: sortlist=ratnull.sort_values(ascending=False).index[:len(ratnull)] recomm.append(sortlist) return ratings,recomm
*代码详见:示例程序/code/recommender.py
将原始的事务性数据导入Python中,因原始数据无字段名,所以首先对相应的字段进行重命名,然后再运行基于用户的协同过滤算法。实现代码如代码清单10-2所示。
代码清单10-2 协同过滤算法实现
#-*- coding: utf-8 -*- #使用基于 UBCF算法对电影进行推荐 from __future__ import print_function import pandas as pd ############ 主程序 ############## if __name__ == "__main__": print("\n--------------使用基于 UBCF算法对电影进行推荐 运行中 ... -----------\n") traindata = pd.read_csv('../data/u1.base',sep='\t', header=None,index_col=None) testdata = pd.read_csv('../data/u1.test',sep='\t', header=None,index_col=None) #删除时间标签列 traindata.drop(3,axis=1, inplace=True) testdata.drop(3,axis=1, inplace=True) #行与列重新命名 traindata.rename(columns={0:'userid',1:'movid',2:'rat'}, inplace=True) testdata.rename(columns={0:'userid',1:'movid',2:'rat'}, inplace=True) traindf=traindata.pivot(index='userid', columns='movid', values='rat') testdf=testdata.pivot(index='userid', columns='movid', values='rat') traindf.rename(index={i:'usr%d'%(i) for i in traindf.index} , inplace=True) traindf.rename(columns={i:'mov%d'%(i) for i in traindf.columns} , inplace=True) testdf.rename(index={i:'usr%d'%(i) for i in testdf.index} , inplace=True) testdf.rename(columns={i:'mov%d'%(i) for i in testdf.columns} , inplace=True) userdf=traindf.loc[testdf.index] #获取预测评分和推荐列表 trainrats,trainrecomm=recomm(traindf,userdf)
*代码详见:示例程序/code/10-1.py
Python程序输出的结果如下:
usr1([u'mov1290', u'mov1354', u'mov1678'], dtype='object', name=u'movid'), usr2([u'mov1491', u'mov1354', u'mov1371'], dtype='object', name=u'movid'), usr3([u'mov1304', u'mov1621', u'mov1678'], dtype='object', name=u'movid'), usr4([u'mov1502', u'mov1659', u'mov1304'], dtype='object', name=u'movid'), usr5([u'mov1304', u'mov1621', u'mov1472'], dtype='object', name=u'movid'), usr6([u'mov1618', u'mov1671', u'mov1357'], dtype='object', name=u'movid'), usr7([u'mov1472', u'mov1467', u'mov1374'], dtype='object', name=u'movid'), usr8([u'mov1659', u'mov1316', u'mov1494'], dtype='object', name=u'movid'), usr9([u'mov1621', u'mov1304', u'mov1491'], dtype='object', name=u'movid'), usr10([u'mov1486', u'mov1494', u'mov437'], dtype='object', name=u'movid'), usr11([u'mov1659', u'mov1654', u'mov1626'], dtype='object', name=u'movid'), usr12([u'mov1659', u'mov1618', u'mov1661'], dtype='object', name=u'movid'), usr13([u'mov1486', u'mov1494', u'mov1662'], dtype='object', name=u'movid'), usr14([u'mov1661', u'mov1308', u'mov1671'], dtype='object', name=u'movid'), usr15([u'mov1626', u'mov1671', u'mov1678'], dtype='object', name=u'movid'), usr16([u'mov1618', u'mov1486', u'mov1494'], dtype='object', name=u'movid'), usr17([u'mov1316', u'mov1621', u'mov1304'], dtype='object', name=u'movid'), usr18([u'mov1618',u'mov1654',u'mov1626'], dtype='object', name=u'movid'), usr19([u'mov1316', u'mov1661', u'mov1275'], dtype='object', name=u'movid'), usr20([u'mov1659', u'mov1292', u'mov1304'], dtype='object', name=u'movid'),…… Total: 80000rows
对输出结果进行解释:其中最前端格式为“usr+整数”,该字符串代表用户编号,“[]”内的字符串代表三部电影的编号,dtype为类型,name为字段名。整体代表的意思是,根据算法得出对用户usr1推荐他并未看过的三部电影,编号为:mov1290,mov1354,mov1678。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论