基於用戶的協同過濾推薦:
目標:針對任意用戶,爲其推薦沒有看過但是可能想看的電影(其他物品)
協同過濾推薦過程:
假設我們要爲用戶甲推薦電影
Step1 - 找到與阿具有相同電影偏好的用戶集合S.
- 對一個與除一個以外的所有用戶進行相似度計算
- 對計算結果進行排序,選取相似度排名前Ñ的Ñ位用戶構成電影偏好相同的用戶集合小號
Step2--基於用戶集合小號進行加權推薦
- 將用戶集合小號中甲看過的電影刪除,僅考慮一個沒有看過的電影
- 用戶集合小號中每個用戶的硅的權重的無線網絡爲硅與甲的相似度
- 計算電影狄加權得分 - 用戶集合小號中每個用戶的Si對電影迪的評分乘以權重無線,然後求和(沒有評分則評分置0)
- 對電影的加權得分進行排序,選取得分排名前Ñ的Ñ部電影構成電影推薦集合
具體的協同推薦算法講解可以參考博客: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