基於MoviesLens 1M數據集的電影推薦——協同過濾推薦算法

基於用戶的協同過濾推薦:

目標:針對任意用戶,爲其推薦沒有看過但是可能想看的電影(其他物品)

協同過濾推薦過程:

假設我們要爲用戶甲推薦電影

Step1 - 找到與阿具有相同電影偏好的用戶集合S.

  1. 對一個與除一個以外的所有用戶進行相似度計算
  2. 對計算結果進行排序,選取相似度排名前Ñ的Ñ位用戶構成電影偏好相同的用戶集合小號

Step2--基於用戶集合小號進行加權推薦

  1. 將用戶集合小號中甲看過的電影刪除,僅考慮一個沒有看過的電影
  2. 用戶集合小號中每個用戶的硅的權重的無線網絡爲硅與甲的相似度
  3. 計算電影狄加權得分 - 用戶集合小號中每個用戶的Si對電影迪的評分乘以權重無線,然後求和(沒有評分則評分置0)
  4. 對電影的加權得分進行排序,選取得分排名前Ñ的Ñ部電影構成電影推薦集合

具體的協同推薦算法講解可以參考博客:https//blog.csdn.net/yimingsilence/article/details/54934302

基於MoviesLens 1M數據集的電影推薦python源程序:

實現第一步的準備

由於數據比較大,爲了使推薦程序運行速度快,我們事先建立一個每個用戶所看電影類型頻數的統計表:

用戶身份 戲劇 記錄 驚悚 戰爭 兒童 恐怖 幻想 西 行動 浪漫 冒險 犯罪 神祕 科幻 黑色電影 喜劇 音樂 動畫
1 37 0 2 三十 0 3 0 12 10 4 0 6 0 28 26 27
2 121 0 31 17 0 3 1 4 58 37 37 23 3 34 2 49 0 0
3 13 0 2 4 4 3 8 23 8 49 0 1 12 0 60 2 4
4 8 0 3 1 2 2 21 3 11 2 0 18 0 0 0 0

建立頻數表的蟒蛇源代碼:

"""
Created on Tue Oct 23 15:16:02 2018
將所有的用戶喜歡看的電影類型統計成表
生成文件——User_M.csv
"""
import time
import copy
import pandas as pd
import numpy as np
S1=time.clock()
#1.讀入電影數據集的數據
unames = ['user_id', 'gender', 'age', 'occupation', 'zip'] 
users = pd.read_table('users.dat', sep='::', header=None,names=unames)
rnames = ['user_id', 'movie_id', 'rating', 'timestamp']
ratings = pd.read_table('ratings.dat', sep='::', header=None,names=rnames)
mnames = ['movie_id', 'title', 'genres']
movies = pd.read_table('movies.dat', sep='::', header=None,names=mnames)
#將電影數據合併
data=pd.merge(pd.merge(ratings,users),movies)
a = copy.deepcopy(data['genres'])#選取電影類型列
Gl=pd.value_counts(a.values, sort=False)#統計電影類別詞頻

#選取用戶id與電影類型
col=['user_id','genres']
a1= copy.deepcopy(data[col])
#生產一個dataframe
L=len(Gl)#將電影類型作爲列
data2=np.zeros((6040,L))
User_Movie=pd.DataFrame(data2,columns=Gl.index)
User_Movie.index=range(1,6041)
#將每個用戶的喜歡看的電影類別選出來

for i in range(1000209):
    S=a1['genres'].ix[i]
    User_Movie[S].ix[a1['user_id'].ix[i]]= User_Movie[S].ix[a1['user_id'].ix[i]]+1
#切割:因爲有許多電影的類別是混合類別
for i in range(len(Gl)):
    Column_S=str(Gl.index[i])
    A=Column_S.split('|')
    for j in range(len(A)):
        User_Movie[A[j]].ix[:]=User_Movie[A[j]].ix[:]+User_Movie[Gl.index[i]].ix[:]
#求出所有的18種電影類別
data2=np.zeros((1500,1))
B=pd.DataFrame(data2,columns=['genres'])
k=0
for i in range(len(Gl)):
    S=str(Gl.index[i])
    A=S.split('|')
    for j in range(len(A)):
        B['genres'].ix[k]=A[j]
        k=k+1        
GLL=pd.value_counts(B['genres'].values, sort=False)
GG=GLL.index[GLL.index[:]!=0.0]#存放的各種電影類型

#真正的電影用戶集合
User_M= copy.deepcopy(User_Movie[GG])
print(User_M)
User_M.to_csv('User_M.csv')#電影用戶集合CSV文件
D1=time.clock()
print('運行總時間:',(D1-S1))

實現第二步的準備

爲了使推薦程序運行速度快,事先建立一個電影ID與電影名稱對應的查找表

movie_id 電影標題
1 玩具總動員(1995)
2 勇敢者的遊戲(1995)
3 脾氣暴躁的老人(1995年)
4 等待呼氣(1995)

建立查找表的蟒蛇源代碼:

"""
Created on Mon Oct 22 19:29:31 2018
建立電影ID與電影名稱的對應CSV文件
生成文件——Movie_idTo_title.csv
"""
import copy
import pandas as pd
data=pd.read_csv('use_data.csv')
data.sort_values('user_id',inplace=True)#排序
data.index=range(1000209)#將下標改爲0~1000209
col=['movie_id','title']
data1=copy.deepcopy(data[col])
data2=data1.drop_duplicates(subset=['movie_id'],keep='first')
data2.sort_values(by='movie_id',inplace=True,ascending=True)
data2.index=data2['movie_id']
data2.to_csv('Movie_idTo_title.csv')

實現推薦算法程序:

其中FUNC4(USER_ID,數字,皮爾遜,data_use)函數是實現給用戶推薦電影的函數

USER_ID:表示被推薦用戶的ID;編號:表示希望推薦的電影的數量;皮爾森:表示用戶相似度表; data_use:表示實際使用的原始數據

蟒蛇源代碼:

"""
Created on Thu Oct 25 15:56:34 2018
主程序:
導入的數據:
    1.所有的電影數據 2.每個用戶的電影類型偏好表 3.電影的id與title對照表
實現功能:
    輸出對任意用戶推薦的電影
"""
import copy
import pandas as pd
import numpy as np
from pandas import DataFrame
import wx

#1.讀入電影數據集的數據
unames = ['user_id', 'gender', 'age', 'occupation', 'zip'] 
users = pd.read_table('users.dat', sep='::', header=None,names=unames)
pd.read_table('User_M.csv',sep=',')
rnames = ['user_id', 'movie_id', 'rating', 'timestamp']
ratings = pd.read_table('ratings.dat', sep='::', header=None,names=rnames)
mnames = ['movie_id', 'title', 'genres']
movies = pd.read_table('movies.dat', sep='::', header=None,names=mnames)
#將電影數據合併
data=pd.merge(pd.merge(ratings,users),movies)
columns=['movie_id','user_id','title','rating']
data_use=copy.deepcopy(data[columns])

#計算每個用戶之間的相關係數,使用User_M.csv文件
User_M=pd.read_csv('User_M.csv')
User=User_M.T#轉置數據
User.columns=list(range(1,6041))
Pearson=User.corr()#各個用戶之間的相關係數矩陣
"""
主要的功能函數
"""
#輸入用戶,輸出推薦電影
def func4(user_Id,Number,Pearson,data_use):
    Pearson_Id=copy.deepcopy(Pearson[user_Id])
    Pearson_Id.sort_values(inplace=True,ascending=False)
    #獲取相似度前5的用戶
    U_Id=Pearson_Id.index[1:6]
    U_Vl=Pearson_Id.values[1:6]
    p=np.zeros((1,5))
    p_num=pd.DataFrame(p,columns=list(range(5)))
    for i in range(5):
        p_num[i]=U_Vl[i]
    #選取此用戶沒看過,但是相似度前五的用戶看過的電影
    #構建電影矩陣
    like_user=np.zeros((5,4000))
    lu_movie=pd.DataFrame(like_user,columns=list(range(1,4001)))
    lu_movie.index=U_Id

    #使用加權推薦
    final_data=data_use.loc[data_use['user_id']==Pearson_Id.index[1]]
    for id in U_Id[1:5]:
        Like_data=data_use.loc[data_use['user_id']==id]
        final_data=final_data.append(Like_data)
    final_data.index=range(1,len(final_data)+1)
    for i in range(1,len(final_data)):
        lu_movie[final_data['movie_id'].iloc[i]].loc[final_data['user_id'].iloc[i]]=final_data['rating'].iloc[i]

    #求出user_Id看過的電影,然後將lu_movie中user_id看過的電影評分置零  
    User_see=data_use.loc[data_use['user_id']==user_Id]
    col=User_see['movie_id']
    for m_id in col:
        lu_movie[m_id].loc[:]=0
    result=np.dot(p_num.values,lu_movie.values)#計算加權值
    result=pd.DataFrame(result,columns=list(range(1,4001)))
    result=result.T
    result.sort_values(by=0,inplace=True,ascending=False)#對計算結果排序
    #建立一個電影id與title對照表,使用Movie_idTo_title.csv文件
    movie_data=pd.read_csv('Movie_idTo_title.csv')
    #輸出排名前N的推薦電影
    result1='爲用戶'+str(user_Id)+'推薦的'+str(Number)+'部電影是:\n'
    for i in range(Number):
        str1='得分排名第'+str(i+1)+'的電影——'+str(movie_data['title'].values[movie_data['movie_id']==result.index[i]])+'\n'
        result1=result1+str1
    return result1

關於python中pandas的一些基礎知識用法可以參考我的另一篇博客:https://mp.csdn.net/postedit/83388026

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章