基于用户的协同过滤推荐:
目标:针对任意用户,为其推荐没有看过但是可能想看的电影(其他物品)
协同过滤推荐过程:
假设我们要为用户甲推荐电影
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