基于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

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