提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
本次实验类同于Python推荐系统算法实现---------基于用户协同过滤算法(不包含构建模型),不同于本次时间复杂度更低,并且内容更加细致。故加更。
一、读入数据 + 数据预处理
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from math import sqrt,pow
data = pd.read_csv('ml-100k/u.data' ,sep = '\t' ,header = None)
display(data.sample(5))
data.rename(columns = {0:'用户ID' ,1:'电影ID' ,2:'电影评分' ,3:'时间戳'} ,inplace = True)
display(data.info())
display(data.describe())
display(data.isnull().sum())
#电影详细信息
data_item = pd.read_csv('ml-100k/u.item' ,sep = '|' ,header = None ,encoding = 'ISO-8859-1')
data_item.rename(columns = {0:'电影ID',1:'电影标题',2:'上映日期',3:'视频上映日期', 4:'URL',
5:'未知',6:'动作',7:'冒险',8:'动画',9:'儿童',
10:'喜剧',11:'犯罪',12:'纪录片',13:'戏剧',14:'奇幻',
15:'黑色电影',16:'恐怖',17:'音乐剧',18:'神秘',19:'浪漫',
20:'科幻',21:'惊悚',22:'战争',23:'西部'} ,inplace = True)
display(data_item.head())
#将用户ID、电影ID、电影评分转换为矩阵
movie_matrix = data.pivot_table(index = '用户ID' ,columns = '电影ID' ,values = '电影评分')
display(movie_matrix.head())
#计算用户之间的相关性
user_similar = movie_matrix.T.corr().round(4)
display(user_similar.head())
二、推荐分计算
#推荐分计算
def score_count(number):
#获得用户number与其它用户之间的相似度>0.7的相关系数列
x0 = user_similar[number][user_similar[number] >0.7].drop([number])
x_index = list(x0.index) #获取相关系数列的索引
x = x0[: ,np.newaxis] #将一维数组转变为二维,否则无法进行score的运算
#获得与用户number与其它相关用户的电影评分矩阵movie_matrix_x
movie_matrix_x = pd.DataFrame()
for i in range(1,944):
if i in x_index:
movie_matrix_x = pd.concat([movie_matrix_x ,movie_matrix.loc[i ,:]] ,axis = 1)
#计算加权评分矩阵
score = x * movie_matrix_x.T
#计算各部电影的用户总权重 weight_sum
weight_sum = []
for m in range(1 ,1683):
y = list(movie_matrix_x.T[m].dropna().index)
y_sum = 0
for i in y:
y_sum = y_sum + x0[i]
weight_sum.append(y_sum)
#计算电影加权平均分
score_avg = score.sum()/weight_sum
#分组
s = pd.DataFrame()
s['电影推荐分'] = score_avg
s['推荐程度'] = pd.cut(s['电影推荐分'] ,bins = [-float('inf') ,1 ,2 ,3 ,4 ,float('inf')] ,
labels = ['不推荐' ,'一般推荐' ,'比较推荐' ,'非常推荐','极力推荐'])
return(s)
#调出电影详细信息
def display_movie(s ,number ,level):
mov = list(data[data['用户ID'] == number]['电影ID'])#获得用户number所观看过的电影
#去掉用户number所看过的电影
dis_mov = []
for i in range(1,1682):
if i not in mov:
dis_mov.append(i)
dis_s = s.iloc[dis_mov]
dis_s.sort_values('电影推荐分' ,ascending = False ,inplace = True)
if level == '不推荐':
if not dis_s[dis_s['推荐程度'] == '不推荐'].empty:
x = dis_s[dis_s['推荐程度'] == '不推荐'].index
n = len(dis_s[dis_s['推荐程度'] == '不推荐'])
print(f'为您列举了{n}部不推荐的电影')
for i in x:
a = data_item.iloc[i-1]
print(f'电影名:{a[1]} 推荐分:{s.iloc[i-1,0]}\n播放地址:{a[4]}\n')
else :
print(f'数据库暂时没有[不推荐]的电影,请您试试其它推荐等级')
else :
if not dis_s[dis_s['推荐程度'] == level].empty :
x = dis_s[dis_s['推荐程度'] == level].index
n = len(dis_s[dis_s['推荐程度'] == level])
print(f'按照推荐分从高到低的排序,{level}您{n}部电影')
print('*--------------------------------------------------------------------------------*')
for i in x:
a = data_item.iloc[i-1]
print(f'电影名:{a[1]} 推荐分:{s.iloc[i-1,0]}\n播放地址:{a[4]}\n')
else :
print(f'数据库暂时没有[{level}]的电影,请您试试其它推荐等级')
结果: