python基于物品协同过滤算法实现代码


Posted in Python onMay 31, 2018

本次测试基于MovieLens数据集实现的基于物品的协同过滤,目前只是在小样本上实现,主要问题是计算太耗内存,后期代码继续优化与完善。

数据集说明:movies.dat中数据是用户对电影的评分。数据格式:UserID::MovieID::Rating::Timestamp。

代码

import pandas as pd
import numpy as np
import math 
import os
import time
import datetime

os.chdir(r'f:\zxx\pthon_work\CF')

def loadData():
 #读入movies.dat, rating.dat,tags.dat
 #mnames=['movie_id','title','genres']
 #movies=pd.read_table(r'.\data\movies.dat',sep='::',header=None,names=mnames)

 rnames=['UserID','MovieID','Rating','Timestamp']
 all_ratings=pd.read_table(r'.\data\ratings.dat',sep='::',header=None,names=rnames,nrows=300000)

 #tnames=['UserID','MovieID','Tag','Timestamp']
 #tags=pd.read_table(r'.\data\tags.dat',sep='::',header=None,names=tnames)
 return all_ratings

#数据探索:rating
def data_alay(ratings):
 """rating nums10000054, 3, 
 示例 : 1  122  5 838985046
 col:'UserID','MovieID','Rating','Timestamp'
  """
 #一个用户只对一个电影打分一次
 UR=ratings.groupby([ratings['UserID'],ratings['MovieID']])
 len(UR.size)

#计算每部电影的平均打分,电影数10677
def avgRating(ratings):
 movies_mean=ratings['Rating'].groupby(ratings['MovieID']).mean()#计算所有用户对电影X的平均打分
 movies_id=movies_mean.index
 movies_avg_rating=movies_mean.values
 return movies_id,movies_avg_rating,movies_mean

#计算电影相似度矩阵相,即建立10677*10677矩阵
def calculatePC(ratings):
 movies_id,movies_avg_rating,movies_mean=avgRating(ratings)
 #pc_mat=np.eye(3)#建立电影相似度单位矩阵
 pc_dic={}
 top_movie=len(movies_id)
 for i in range(0,top_movie):
  for j in range(i+1,top_movie):
   movieAID=movies_id[i]
   movieBID=movies_id[j]
   see_moviesA_user=ratings['UserID'][ratings['MovieID']==movieAID]
   see_moviesB_user=ratings['UserID'][ratings['MovieID']==movieBID]
   join_user=np.intersect1d(see_moviesA_user.values,see_moviesB_user.values)#同时给电影A、B评分的用户
   movieA_avg=movies_mean[movieAID]
   movieB_avg=movies_mean[movieBID]
   key1=str(movieAID)+':'+str(movieBID)
   key2=str(movieBID)+':'+str(movieAID)
   value=twoMoviesPC(join_user,movieAID,movieBID,movieA_avg,movieB_avg,ratings)
   pc_dic[key1]=value   
   pc_dic[key2]=value      
   #pc_mat[i][i+1]=twoMoviesPC(join_user,movieAID,movieBID,movieA_avg,movieB_avg,ratings)
   #print ('---the %s, %d,%d:--movie %s--%s--pc is %f' % (key1,movieAID,movieBID,movieAID,movieBID,pc_dic[key1]))
 return pc_dic

#计算电影A与电影B的相似度,皮尔森相似度=sum(A-A^)*sum(B-B^)/sqrt(sum[(A-A^)*(A-A^)]*sum[(B-B^)*(B-B^)])
def twoMoviesPC(join_user,movieAID,movieBID,movieA_avg,movieB_avg,ratings):
 cent_AB_sum=0.0#相似度分子
 centA_sum=0.0#分母
 centB_sum=0.0#分母
 movieAB_pc=0.0#电影A,B的相似度
 count=0
 for u in range(len(join_user)):
  #print '---------',u
  count=count+1
  ratA=ratings['Rating'][ratings['UserID']==join_user[u]][ratings['MovieID']==movieAID].values[0]#用户给电影A评分
  ratB=ratings['Rating'][ratings['UserID']==join_user[u]][ratings['MovieID']==movieBID].values[0]#用户给电影B评分
  cent_AB=(ratA-movieA_avg)*(ratB-movieB_avg) #去均值中心化
  centA_square=(ratA-movieA_avg)*(ratA-movieA_avg) #去均值平方
  centB_square=(ratB-movieB_avg)*(ratB-movieB_avg)#去均值平方
  cent_AB_sum=cent_AB_sum+cent_AB
  centA_sum=centA_sum+centA_square
  centB_sum=centB_sum+centB_square
 if(centA_sum>0 and centB_sum>0 ):
  movieAB_pc=cent_AB_sum/math.sqrt(centA_sum*centB_sum)
 return movieAB_pc

"""
预测用户U对那些电影感兴趣。分三步,
 1)用户U过去X天看过的电影。
 2)提出用户U已看过的电影,根据用户U过去看过的电影,计算用户U对其他电影的打分.
 3) 拉去打分最高的的电影给用户推荐。
预测用户U对电影C的打分。分三步:(先只做这个)
 1)用户U过去X天看过的电影。
 2)利用加权去中心化公式预测用户U对电影C的打分.

"""
#日期处理: -3天,然后转换为uinxtime
def timePro(last_rat_time,UserU):
 lastDate= datetime.datetime.fromtimestamp(last_rat_time[UserU]) #unix转为日期
 date_sub3=lastDate+datetime.timedelta(days=-3)#减去3天
 unix_sub3=time.mktime(date_sub3.timetuple())#日期转为unix
 return unix_sub3

#取用户最后一次评分前3天评估的电影进行预测
def getHisRat(ratings,last_rat_time,UserUID):
 unix_sub3= timePro(last_rat_time,UserUID)
 UserU_info=ratings[ratings['UserID']==UserUID][ratings['Timestamp']>unix_sub3]
 return UserU_info

#预测用户U对电影C的打分
def hadSeenMovieByUser(UserUID,MovieA,ratings,pc_dic,movies_mean):
 pre_rating=0.0 
 last_rat_time=ratings['Timestamp'].groupby([ratings['UserID']]).max()#获取用户U最近一次评分日期
 UserU_info= getHisRat(ratings,last_rat_time,UserUID)#获取用户U过去看过的电影

 flag=0#表示新电影,用户U是否给电影A打过分
 wmv=0.0#相似度*mv平均打分去均值后之和
 w=0.0#相似度之和
 movie_userU=UserU_info['MovieID'].values#当前用户看过的电影
 if MovieA in movie_userU:
  flag=1
  pre_rating=UserU_info['Rating'][UserU_info['MovieID']==MovieA].values
 else:
  for mv in movie_userU:
   key=str(mv)+':'+str(MovieA)
   rat_U_mv=UserU_info['Rating'][UserU_info['MovieID']==mv][UserU_info['UserID']==UserUID].values#用户U对看过电影mv的打分
   wmv=(wmv+pc_dic[key]*(rat_U_mv-movies_mean[mv]))#相似度*mv平均打分去均值后之和
   w=(w+pc_dic[key])#看过电影与新电影相似度之和
   #print ('---have seen mv %d with new mv %d,%f,%f'%(mv,MovieA,wmv,w))   
  pre_rating=(movies_mean[MovieA]+wmv/w)
 print ('-flag:%d---User:%d rating movie:%d with %f score----' %(flag,UserUID,MovieA,pre_rating))
 return pre_rating,flag

if __name__=='__main__':
 all_ratings=loadData()
 movie_num=100#控制电影数,只针对电影ID在该范围的数据进行计算,否则数据量太大 
 ratings=all_ratings[all_ratings['MovieID']<=movie_num]

 movies_id,movies_avg_rating,movies_mean=avgRating(ratings)
 pc_dic=calculatePC(ratings)#电影相似度矩阵
 #预测
 UserUID=10#当前数据集只看过电影4,7,
 MovieA=6 
 pre_rating,flag=hadSeenMovieByUser(UserUID,MovieA,ratings,pc_dic,movies_mean)

 "-----------------测试ID提取------------------"
 #选取UserUID
 ratings.head(10)#从前10行中随机选取一个用户ID,例如:UserID=10
 #查看该用户在当前数据集中看过那些电影,方便选取新电影(防止选择的是用户已经看过的电影)
 ratings[ratings['UserID']==10]#该用户在当前数据集中,只看过电影MovieID in(4,7),则可选择不是4,7的电影ID进行预测,例如6.

运行结果:

-flag:0---User:10 rating movie:6 with 4.115996 score----

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现在windows下操作word的方法
Apr 28 Python
用Python编写web API的教程
Apr 30 Python
Python基于贪心算法解决背包问题示例
Nov 27 Python
对PyTorch torch.stack的实例讲解
Jul 30 Python
python实现机器学习之元线性回归
Sep 06 Python
在python中实现强制关闭线程的示例
Jan 22 Python
梅尔频率倒谱系数(mfcc)及Python实现
Jun 18 Python
Python图像处理之图片文字识别功能(OCR)
Jul 30 Python
python自动分箱,计算woe,iv的实例代码
Nov 22 Python
Django异步任务线程池实现原理
Dec 17 Python
Python JSON编解码方式原理详解
Jan 20 Python
scrapy头部修改的方法详解
Dec 06 Python
python写入并获取剪切板内容的实例
May 31 #Python
python3实现基于用户的协同过滤
May 31 #Python
python控制windows剪贴板,向剪贴板中写入图片的实例
May 31 #Python
python用户评论标签匹配的解决方法
May 31 #Python
python批量查询、汉字去重处理CSV文件
May 31 #Python
python破解zip加密文件的方法
May 31 #Python
python删除本地夹里重复文件的方法
Nov 19 #Python
You might like
如何从一个php文件向另一个地址post数据,不用表单和隐藏的变量的
2007/03/06 PHP
php数组声明、遍历、数组全局变量使用小结
2013/06/05 PHP
基于laravel制作APP接口(API)
2016/03/15 PHP
js 匿名调用实现代码
2009/06/19 Javascript
json格式化/压缩工具 Chrome插件扩展版
2010/05/25 Javascript
用javascript模仿ie的自动完成类似自动完成功的表单
2012/12/12 Javascript
javascript重复绑定事件造成的后果说明
2013/03/02 Javascript
JavaScript代码简单实现求杨辉三角给定行的最大值
2013/10/29 Javascript
jQuery产品间断向下滚动效果核心代码
2014/05/08 Javascript
jQuery html()方法使用不了无法显示内容的问题
2014/08/06 Javascript
javascript将数字转换整数金额大写的方法
2015/01/27 Javascript
js实现获取当前时间是本月第几周的方法
2015/08/11 Javascript
jQuery实现的仿select功能代码
2015/08/19 Javascript
jquery attr()设置和获取属性值实例教程
2016/09/25 Javascript
使用Bootstrap + Vue.js实现添加删除数据示例
2017/02/27 Javascript
jquery PrintArea 实现票据的套打功能(代码)
2017/03/17 Javascript
详谈innerHTML innerText的使用和区别
2017/08/18 Javascript
react-native使用react-navigation进行页面跳转导航的示例
2017/09/07 Javascript
从Node.js事件触发器到Vue自定义事件的深入讲解
2020/06/26 Javascript
Python中IPYTHON入门实例
2015/05/11 Python
Python利用Nagios增加微信报警通知的功能
2016/02/18 Python
Python实现自定义函数的5种常见形式分析
2018/06/16 Python
Django admin.py 在修改/添加表单界面显示额外字段的方法
2019/08/22 Python
wxPython实现带颜色的进度条
2019/11/19 Python
Pytorch中实现只导入部分模型参数的方式
2020/01/02 Python
自定义Django Form中choicefield下拉菜单选取数据库内容实例
2020/03/13 Python
python实现录制全屏和选择区域录屏功能
2021/02/05 Python
HTML5地理定位实例
2014/10/15 HTML / CSS
印尼最大的网上书店:Gramedia.com
2018/09/13 全球购物
意大利顶级奢侈品电商:LUISAVIAROMA(支持中文)
2020/05/26 全球购物
在DELPHI中调用存储过程和使用内嵌SQL哪种方式更好
2016/11/22 面试题
生产车间班组长岗位职责
2014/01/06 职场文书
早读课迟到检讨书
2014/09/25 职场文书
财务总监岗位职责范本
2015/04/03 职场文书
2015年仓库管理员工作总结
2015/04/21 职场文书
分布式架构Redis中有哪些数据结构及底层实现原理
2022/03/13 Redis