python基于物品協(xié)同過濾算法實(shí)現(xiàn)代碼
本次測(cè)試基于MovieLens數(shù)據(jù)集實(shí)現(xiàn)的基于物品的協(xié)同過濾,目前只是在小樣本上實(shí)現(xiàn),主要問題是計(jì)算太耗內(nèi)存,后期代碼繼續(xù)優(yōu)化與完善。
數(shù)據(jù)集說明:movies.dat中數(shù)據(jù)是用戶對(duì)電影的評(píng)分。數(shù)據(jù)格式: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
#數(shù)據(jù)探索:rating
def data_alay(ratings):
"""rating nums10000054, 3,
示例 : 1 122 5 838985046
col:'UserID','MovieID','Rating','Timestamp'
"""
#一個(gè)用戶只對(duì)一個(gè)電影打分一次
UR=ratings.groupby([ratings['UserID'],ratings['MovieID']])
len(UR.size)
#計(jì)算每部電影的平均打分,電影數(shù)10677
def avgRating(ratings):
movies_mean=ratings['Rating'].groupby(ratings['MovieID']).mean()#計(jì)算所有用戶對(duì)電影X的平均打分
movies_id=movies_mean.index
movies_avg_rating=movies_mean.values
return movies_id,movies_avg_rating,movies_mean
#計(jì)算電影相似度矩陣相,即建立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)#同時(shí)給電影A、B評(píng)分的用戶
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
#計(jì)算電影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評(píng)分
ratB=ratings['Rating'][ratings['UserID']==join_user[u]][ratings['MovieID']==movieBID].values[0]#用戶給電影B評(píng)分
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
"""
預(yù)測(cè)用戶U對(duì)那些電影感興趣。分三步,
1)用戶U過去X天看過的電影。
2)提出用戶U已看過的電影,根據(jù)用戶U過去看過的電影,計(jì)算用戶U對(duì)其他電影的打分.
3) 拉去打分最高的的電影給用戶推薦。
預(yù)測(cè)用戶U對(duì)電影C的打分。分三步:(先只做這個(gè))
1)用戶U過去X天看過的電影。
2)利用加權(quán)去中心化公式預(yù)測(cè)用戶U對(duì)電影C的打分.
"""
#日期處理: -3天,然后轉(zhuǎn)換為uinxtime
def timePro(last_rat_time,UserU):
lastDate= datetime.datetime.fromtimestamp(last_rat_time[UserU]) #unix轉(zhuǎn)為日期
date_sub3=lastDate+datetime.timedelta(days=-3)#減去3天
unix_sub3=time.mktime(date_sub3.timetuple())#日期轉(zhuǎn)為unix
return unix_sub3
#取用戶最后一次評(píng)分前3天評(píng)估的電影進(jìn)行預(yù)測(cè)
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
#預(yù)測(cè)用戶U對(duì)電影C的打分
def hadSeenMovieByUser(UserUID,MovieA,ratings,pc_dic,movies_mean):
pre_rating=0.0
last_rat_time=ratings['Timestamp'].groupby([ratings['UserID']]).max()#獲取用戶U最近一次評(píng)分日期
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#當(dāng)前用戶看過的電影
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對(duì)看過電影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#控制電影數(shù),只針對(duì)電影ID在該范圍的數(shù)據(jù)進(jìn)行計(jì)算,否則數(shù)據(jù)量太大
ratings=all_ratings[all_ratings['MovieID']<=movie_num]
movies_id,movies_avg_rating,movies_mean=avgRating(ratings)
pc_dic=calculatePC(ratings)#電影相似度矩陣
#預(yù)測(cè)
UserUID=10#當(dāng)前數(shù)據(jù)集只看過電影4,7,
MovieA=6
pre_rating,flag=hadSeenMovieByUser(UserUID,MovieA,ratings,pc_dic,movies_mean)
"-----------------測(cè)試ID提取------------------"
#選取UserUID
ratings.head(10)#從前10行中隨機(jī)選取一個(gè)用戶ID,例如:UserID=10
#查看該用戶在當(dāng)前數(shù)據(jù)集中看過那些電影,方便選取新電影(防止選擇的是用戶已經(jīng)看過的電影)
ratings[ratings['UserID']==10]#該用戶在當(dāng)前數(shù)據(jù)集中,只看過電影MovieID in(4,7),則可選擇不是4,7的電影ID進(jìn)行預(yù)測(cè),例如6.
運(yùn)行結(jié)果:
-flag:0---User:10 rating movie:6 with 4.115996 score----
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
跟老齊學(xué)Python之私有函數(shù)和專有方法
這篇文章是老齊學(xué)Python系列文章的一篇,主要介紹了跟私有函數(shù)和專有方法,需要的朋友可以參考下2014-10-10
Python模擬鼠標(biāo)點(diǎn)擊實(shí)現(xiàn)方法(將通過實(shí)例自動(dòng)化模擬在360瀏覽器中自動(dòng)搜索python)
這篇文章主要介紹了Python模擬鼠標(biāo)點(diǎn)擊實(shí)現(xiàn)方法(將通過實(shí)例自動(dòng)化模擬在360瀏覽器中自動(dòng)搜索python),需要的朋友可以參考下2017-08-08
python機(jī)器學(xué)習(xí)之隨機(jī)森林(七)
這篇文章主要為大家詳細(xì)介紹了python機(jī)器學(xué)習(xí)之隨機(jī)森林,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
Python關(guān)于抽獎(jiǎng)系統(tǒng)的思考與設(shè)計(jì)思路
這篇文章主要介紹了Python關(guān)于抽獎(jiǎng)系統(tǒng)的思考與設(shè)計(jì)思路,本文通過一些簡單的例子來說一說抽獎(jiǎng)系統(tǒng)背后的邏輯,看看究竟是你運(yùn)氣不好還是系統(tǒng)邏輯在作怪,需要的朋友可以參考下2023-03-03
selenium動(dòng)態(tài)數(shù)據(jù)獲取的方法實(shí)現(xiàn)
本文主要介紹了selenium動(dòng)態(tài)數(shù)據(jù)獲取的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07

