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求众数问题实例
Sep 26 Python
python中字符串前面加r的作用
Jun 04 Python
Python将图片转换为字符画的方法
Jun 16 Python
django认证系统实现自定义权限管理的方法
Jul 16 Python
Python文件读写保存操作的示例代码
Sep 14 Python
CentOS7安装Python3的教程详解
Apr 10 Python
python 标准差计算的实现(std)
Jul 29 Python
如何用Python来搭建一个简单的推荐系统
Aug 07 Python
python自动循环定时开关机(非重启)测试
Aug 26 Python
Python 类的私有属性和私有方法实例分析
Sep 29 Python
ubuntu 18.04 安装opencv3.4.5的教程(图解)
Nov 04 Python
python可视化之颜色映射详解
Sep 15 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实现网站插件机制的方法
2009/11/10 PHP
PHP 使用pcntl和libevent 实现Timer功能
2013/10/27 PHP
PHP中使用虚代理实现延迟加载技术
2014/11/05 PHP
开启PHP Static 关键字之旅模式
2015/11/13 PHP
Windows平台实现PHP连接SQL Server2008的方法
2017/07/26 PHP
flash javascript之间的通讯方法小结
2008/12/20 Javascript
探讨JQUERY JSON的反序列化类 using问题的解决方法
2013/12/19 Javascript
jquery处理页面弹出层查询数据等待操作实例
2015/03/25 Javascript
JavaScript中exec函数用法实例分析
2015/06/08 Javascript
AngularJS基础 ng-repeat 指令简单示例
2016/08/03 Javascript
jQuery Dialog 取消右上角删除按钮事件
2016/09/07 Javascript
jQuery表单元素选择器代码实例
2017/02/06 Javascript
Bootstrap路径导航与分页学习使用
2017/02/08 Javascript
jQuery查找dom的几种方法效率详解
2017/05/17 jQuery
Vue+jquery实现表格指定列的文字收缩的示例代码
2018/01/09 jQuery
Bootstrap标签页(Tab)插件切换echarts不显示问题的解决
2018/07/13 Javascript
javascript和php使用ajax通信传递JSON的实例
2018/08/21 Javascript
Vue基本指令实例图文讲解
2021/02/25 Vue.js
[01:01:29]2018DOTA2亚洲邀请赛 4.4 淘汰赛 VP vs Liquid 第一场
2018/04/05 DOTA
python 实现语音聊天机器人的示例代码
2018/12/02 Python
pyhanlp安装介绍和简单应用
2019/02/22 Python
Python 3.6 -win64环境安装PIL模块的教程
2019/06/20 Python
python判断链表是否有环的实例代码
2020/01/31 Python
基于TensorFlow中自定义梯度的2种方式
2020/02/04 Python
如何基于windows实现python定时爬虫
2020/05/01 Python
django 利用Q对象与F对象进行查询的实现
2020/05/15 Python
使用python matploblib库绘制准确率,损失率折线图
2020/06/16 Python
Python入门基础之数字字符串与列表
2021/02/01 Python
Python中对象的比较操作==和is区别详析
2021/02/12 Python
日本最大的旅游网站:Rakuten Travel(乐天旅游)
2018/08/02 全球购物
工作过失检讨书
2014/02/23 职场文书
标准毕业生自荐信
2014/06/24 职场文书
销售简历自我评价怎么写
2014/09/26 职场文书
公司放假通知怎么写
2015/04/15 职场文书
Mysql中调试存储过程最简单的方法
2021/06/30 MySQL
九大龙王魂骨,山龙王留下躯干骨,榜首死的最憋屈(被捏碎)
2022/03/18 国漫