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实现的一个p2p文件传输实例
Jun 04 Python
python抓取网页时字符集转换问题处理方案分享
Jun 19 Python
python打开网页和暂停实例
Sep 30 Python
Python实现根据IP地址和子网掩码算出网段的方法
Jul 30 Python
Python解析json文件相关知识学习
Mar 01 Python
Python中的if、else、elif语句用法简明讲解
Mar 11 Python
深入浅析python继承问题
May 29 Python
Python机器学习之SVM支持向量机
Dec 27 Python
python 用for循环实现1~n求和的实例
Feb 01 Python
pandas取出重复数据的方法
Jul 04 Python
Python爬虫之Selenium实现键盘事件
Dec 04 Python
使用Python判断一个文件是否被占用的方法教程
Dec 16 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实现的MySQL数据浏览器
2007/03/11 PHP
浅析PHP原理之变量分离/引用(Variables Separation)
2013/08/09 PHP
PHP中常用的字符串格式化函数总结
2014/11/19 PHP
thinkPHP框架实现类似java过滤器的简单方法示例
2018/09/05 PHP
phpMyAdmin通过密码漏洞留后门文件
2018/11/20 PHP
基于jQuery架构javascript基础体系
2011/01/01 Javascript
javascript实现checkBox的全选,反选与赋值
2015/03/12 Javascript
AngularJS 中的指令实践开发指南(一)
2016/03/20 Javascript
IE和Firefox之间在JavaScript语法上的差异
2016/04/22 Javascript
Bootstrap3.0学习教程之JS折叠插件
2016/05/27 Javascript
有关suggest快速删除后仍然出现下拉列表的bug问题
2016/12/02 Javascript
vue-router的使用方法及含参数的配置方法
2018/11/13 Javascript
微信小程序实现购物车代码实例详解
2019/08/29 Javascript
Vue使用Clipboard.JS在h5页面中复制内容实例详解
2019/09/03 Javascript
十个Python程序员易犯的错误
2015/12/15 Python
用yum安装MySQLdb模块的步骤方法
2016/12/15 Python
python模拟登录并且保持cookie的方法详解
2017/04/04 Python
python和shell监控linux服务器的详细代码
2018/06/22 Python
python绘制漏斗图步骤详解
2019/03/04 Python
python3应用windows api对后台程序窗口及桌面截图并保存的方法
2019/08/27 Python
Flask之pipenv虚拟环境的实现
2019/11/26 Python
Python面向对象程序设计之继承、多态原理与用法详解
2020/03/23 Python
HTML5 文件域+FileReader 分段读取文件并上传到服务器
2017/10/23 HTML / CSS
澳大利亚拥有最佳跳伞降落点和最好服务的跳伞项目运营商:Skydive Australia
2018/03/05 全球购物
戴尔英国翻新电脑和电子产品:Dell UK Refurbished Computers
2019/07/30 全球购物
行政主管岗位职责
2013/11/18 职场文书
《和田的维吾尔》教学反思
2014/04/14 职场文书
校运会口号
2014/06/18 职场文书
购房委托书范本
2014/09/18 职场文书
大学生赌博检讨书
2014/09/22 职场文书
领导班子四风查摆对照检查材料思想汇报
2014/10/05 职场文书
违纪检讨书
2015/01/27 职场文书
2015年全民国防教育日活动总结
2015/03/23 职场文书
工资证明格式模板
2015/06/12 职场文书
童年读书笔记
2015/06/26 职场文书
宪法宣传标语100条
2019/10/15 职场文书