python电影推荐系统_电影推荐系统---协同过滤算法(SVD,NMF)
SVD
1 推荐系统概述
1.1 项目安排
1.2 三大协同过滤
1.3 项目开发工具
2 Movielens数据集简介
MovieLens是推荐系统常用的数据集;
MovieLens数据集中,用户对自己看过的电影进行评分,分值为1~5;
MovieLens包括两个不同大小的库,适用于不同规模的算法;
·小规模的库事943个独立用户对1682部电影做的10000次评分的数据;
·大规模的库事6040个独立用户对3900部电影做的100万次评分的数据;
3 数据探索
3.1 导入小规模的库数据
importnumpy asnp
importpandas aspd
importmatplotlib.pyplot asplt
data=pd.read_csv('ml-100k/u.data',sep='\t',names=['user_id','item_id','rating','timestamp'])
data.head()
3.2 数据探索及发现
# 数据信息查看
data.info()
# 数据描述
data.describe()
data.user_id.nunique()# nunique() --> 返回不重复user_id的个数,统计用户的个数
data.item_id.nunique()# 统计被评价电影的个数
>> 943
>> 1682
data.duplicated(subset=['user_id','item_id']).sum()# 查看user_id与item_id是否有重复的情况
>> 0
从导入的数据可以看出,user_id共有943个,item_id共有1682个,与数据对于的user_id及item_id的编号刚好是1~943和1~1682,可见数据已经清洗好的,不需要重新处理
然后将数据集拆分为训练集和测试集,分别进行处理
且user_id与item_id均不存在重复的情况,数据可以直接使用。
3.3 数据检查
3.3.1 查看每个物品对应用户的数量
a. 根据item_id分类聚合
# 统计每个物品对应的用户数
item_id_usercnt =train_data.groupby('item_id').count().user_id
item_id_usercnt[:5]
b. 直方图展示
# 展示分类聚合结果
plt.hist(item_id_usercnt.values)
plt.show()
c. 查看十分位数
# 分别查看每一物品对应的用户的十分位数(十分位数、二十分位数...一百分位数)
item_id_usercnt.quantile(q=np.arange(0,1.1,0.1))
d. 物品对应用户数量数据查看发现
约有30%左右的物品对应的用户数少于10个,对这部分物品计算与其他物品的相似度不会太准确
3.3.2 查看每个用户对应物品的数量
a. 根据user_id分类聚合
# 统计每个用户对应的物品数
user_id_itemcnt =train_data.groupby('user_id').count().item_id
user_id_itemcnt[:5]
b. 直方图展示
# 展示分类聚合结果
plt.hist(user_id_itemcnt.values)
plt.show()
c. 查看十分位数
# 分别查看每一用户对应的物品的十分位数(十分位数、二十分位数...一百分位数)
user_id_itemcnt.quantile(q=np.arange(0,1.1,0.1))
d. 物品对应用户数量数据查看发现
从每个用户对应的物品数量至少为20个的情况来看,基于用户相似度的准确度会比基于物品要好
3.4 构建用户-物品矩阵
3.4.1 获取矩阵行数m、列数n
# 通过nunique()方法分别获得user_id、item_id的去重计数
m_users =train_data.user_id.nunique()#
n_items =train_data.item_id.nunique()
3.4.2 创建一个全是0的m*n的矩阵并向矩阵中填充对应数据
user_item_matrix =np.zeros((m_users,n_items))# 创建一个全是0的m*n的矩阵
'''
itertuples() 将每一行转换为对应的元组,且数据一一对应
for line in data.head().itertuples():
print(line)
>> Pandas(Index=0, user_id=196, item_id=242, rating=3, timestamp=881250949)
>> Pandas(Index=1, user_id=186, item_id=302, rating=3, timestamp=891717742)
>> Pandas(Index=2, user_id=22, item_id=377, rating=1, timestamp=878887116)
>> Pandas(Index=3, user_id=244, item_id=51, rating=2, timestamp=880606923)
>> Pandas(Index=4, user_id=166, item_id=346, rating=1, timestamp=886397596)
'''
forline indata.itertuples():
user_item_matrix[line[1]-1,line[2]-1]=line[3]
'''
因为user_id 和 item_id都是从1开始编号的,而矩阵的索引是从零开始
data数据的第二列为user_id,第三列为item_id,第三列则为对应user对item的评分
'''
user_item_matrix #展示一下用户物品矩阵
3.4.3 查看用户-物品矩阵的稀疏性
# 统计矩阵中非0值的个数与矩阵总元素个数的比值,保留3位小数
sparsity =round(len(user_item_matrix.nonzero()[1])/float(m_users*n_items),3)
sparsity
>> 0.063
发现:用户-物品 矩阵非常稀疏,只有6%的用户物品有互动记录
4 基于item的协同过滤推荐系统
4.1 物品相似度矩阵
4.2 基于item的协同过滤推荐 - 预测原理
4.3 代码实现
importnumpy asnp
importpandas aspd
# 导入数据
data=pd.read_csv('ml-100k/u.data',sep='\t',names=['user_id','item_id','rating','timestamp'])
# 用户物品统计
n_users =data.user_id.nunique()
n_items =data.item_id.nunique()
# 拆分数据集
fromsklearn.model_selection importtrain_test_split
train_data,test_data =train_test_split(data,test_size=0.3)#按照训练集70%,测试集30%的比例对数据进行拆分
# 训练集 用户-物品 矩阵
user_item_matrix =np.zeros((n_users,n_items))
forline intrain_data.itertuples():
user_item_matrix[line[1]-1,line[2]-1]=line[3]
# 构建物品相似矩阵 - 使用sklearn.metrics.pairwise中的cosine计算余弦距离
'''
采用余弦距离计算相似度
如果两个物品在同一条水平线上,则其夹角为零,对应的余弦值为1,代表完全相似
如果两个物品处于垂直的方向上,其夹角为90度,那么其余弦值为0,代表毫不相干
'''
fromsklearn.metrics.pairwise importpairwise_distances
# 相似度计算定义为余弦距离
item_similarity_m =pairwise_distances(user_item_matrix.T,metric='cosine')
# 物品相似矩阵探索
'''
item_similarity_m.shape >> (1682, 1682)
item_similarity_m[0:5,0:5].round(2) # 取5*5的矩阵查看其保留两位小数的数据
# pairwise_distances模块在计算物品相似性时,不会计算自己与自己的相似性,所以所以对角线的值都为0
>> array([[0. , 0.67, 0.73, 0.7 , 0.81],
[0.67, 0. , 0.84, 0.64, 0.82],
[0.73, 0.84, 0. , 0.8 , 0.85],
[0.7 , 0.64, 0.8 , 0. , 0.76],
[0.81, 0.82, 0.85, 0.76, 0. ]])
'''
# 现在我们只分析上三角,得到等分位数
item_similarity_m_triu =np.triu(item_similarity_m,k=1)# 取得上三角数据
item_sim_nonzero =np.round(item_similarity_m_triu[item_similarity_m_triu.nonzero()],3)
'''
# 上三角矩阵
arr=np.linspace(1,9,9).reshape(3,3)
arr
>> array([[1., 2., 3.],
[4., 5., 6.],
[7., 8., 9.]])
np.triu(arr,k=1) # 默认k=0,k的值正数表示向右上角移对应个单位,把对应位置全部变为0
>> array([[0., 2., 3.],
[0., 0., 6.],
[0., 0., 0.]])
'''
# 查看十分位数
np.percentile(item_sim_nonzero,np.arange(0,101,10))
>> array([0. , 0.829, 0.884, 0.919, 0.948, 0.976, 1., 1.,1. , 1. , 1. ])
可以看出相似性得分普遍偏大,相似度没有比较好的可区分性。
4.4 训练集预测
user_item_precdiction =user_item_matrix.dot(item_similarity_m)/np.array([np.abs(item_similarity_m).sum(axis=1)])
# 除以np.array([np.abs(item_similarity_m).sum(axis=1)]是为了可以使评分在1~5之间,使1~5的标准化
# 只取数据集中有评分的数据集进行评估
fromsklearn.metrics importmean_squared_error
frommath importsqrt
prediction_flatten =user_item_precdiction[train_item_matrix.nonzero()]
user_item_matrix_flatten =train_item_matrix[train_item_matrix.nonzero()]
error_train =sqrt(mean_squared_error(prediction_flatten,user_item_matrix_flatten))# 均方根误差计算
print('训练集预测均方根误差:',error_train)
>> 训练集预测均方根误差:3.4714925320107684
4.5 测试集预测
test_data_matrix =np.zeros((n_users,n_items))
forline intest_data.itertuples():
test_data_matrix[line[1]-1,line[2]-1]=line[3]
# 预测矩阵
item_prediction =test_data_matrix.dot(item_similarity_m)/np.array(np.abs(item_similarity_m).sum(axis=1))
# 只取数据集中有评分的数据集进行评估
prediction_flatten =user_item_precdiction[test_data_matrix.nonzero()]
test_data_matrix_flatten =test_data_matrix[test_data_matrix.nonzero()]
error_test =sqrt(mean_squared_error(prediction_flatten,test_data_matrix_flatten))# 均方根误差计算
print('测试集预测均方根误差:',error_test)
>> 测试集预测均方根误差:3.4645810277607487
4.6 单模型结果提示思路
4.6.1 改变相似度算法 - 采用欧式距离
# 相似度计算定义为欧式距离
item_similarity_m =pairwise_distances(user_item_matrix.T,metric='euclidean')
>> 训练集预测均方根误差:3.3818902386408056
>> 测试集预测均方根误差:3.3763275676001396
4.6.2 增加训练集比例
fromsklearn.model_selection importtrain_test_split
train_data,test_data =train_test_split(data,test_size=0.2)
>> 训练集预测均方根误差:3.4464124130045506
>> 测试集预测均方根误差:3.4247175440782516
4.6.3 增加训练集的同时采用欧式距离
>> 训练集预测均方根误差:3.3395618010919823
>> 测试集预测均方根误差:3.339569787071282
4.7 基于item协同过滤推荐系统结果分析
1、通过改变物品矩阵相似度(采用欧式距离)的计算方法可以看出预测效果略有提升;
2、通过增加训练集的方法对预测结果略有提升,但并不明显;
3、在增加训练集的同时采用欧式距离计算相似度发现预测效果提升最好,但均方根误差依然很大,与之前预测(物品是分位数查看结果,其区分性并不是很好)相符;
4、因而在此例中使用基于item的协同过滤推荐系统并不理想。
5 基于user的协同过滤的推荐系统
5.1 用户相似矩阵
5.2 基于user的协同过滤的推荐系统 - 预测原理
5.3 代码实现
# 导入数据
importnumpy asnp
importpandas aspd
data=pd.read_csv('ml-100k/u.data',sep='\t',names=['user_id','item_id','rating','timestamp'])
# 用户物品统计
n_users =data.user_id.nunique()
n_items =data.item_id.nunique()
# 拆分数据集
fromsklearn.model_selection importtrain_test_split
# 按照训练集70%,测试集30%的比例对数据进行拆分
train_data,test_data =train_test_split(data,test_size=0.3)
# 训练集 用户-物品 矩阵
user_item_matrix =np.zeros((n_users,n_items))
forline intrain_data.itertuples():
user_item_matrix[line[1]-1,line[2]-1]=line[3]
# 构建用户相似矩阵 - 采用余弦距离
fromsklearn.metrics.pairwise importpairwise_distances
# 相似度计算定义为余弦距离
user_similarity_m =pairwise_distances(user_item_matrix,metric='cosine')# 每个用户数据为一行,此处不需要再进行转置
user_similarity_m[0:5,0:5].round(2)# 取5*5的矩阵查看其保留两位小数的数据
'''
>> array([[0. , 0.85, 0.96, 0.96, 0.74],
[0.85, 0. , 0.99, 0.84, 0.93],
[0.96, 0.99, 0. , 0.77, 0.97],
[0.96, 0.84, 0.77, 0. , 0.97],
[0.74, 0.93, 0.97, 0.97, 0. ]])
'''
# 现在我们只分析上三角,得到等分位数
user_similarity_m_triu =np.triu(user_similarity_m,k=1)# 取得上三角数据
user_sim_nonzero =np.round(user_similarity_m_triu[user_similarity_m_triu.nonzero()],3)
np.percentile(user_sim_nonzero,np.arange(0,101,10))
>> array([0.266,0.752,0.804,0.842,0.871,0.896,0.919,0.941,0.962,0.991, 1. ])
可以看出用户矩阵的相似性区分性还是比较好的
5.4 训练集预测
mean_user_rating =user_item_matrix.mean(axis=1)
rating_diff =(user_item_matrix -mean_user_rating[:,np.newaxis])# np.newaxis作用:为mean_user_rating增加一个维度,实现加减操作
user_precdiction =mean_user_rating[:,np.newaxis]+user_similarity_m.dot(rating_diff)/np.array([np.abs(user_similarity_m).sum(axis=1)]).T
# 处以np.array([np.abs(item_similarity_m).sum(axis=1)]是为了可以使评分在1~5之间,使1~5的标准化
# 只取数据集中有评分的数据集进行评估
fromsklearn.metrics importmean_squared_error
frommath importsqrt
prediction_flatten =user_precdiction[user_item_matrix.nonzero()]
user_item_matrix_flatten =user_item_matrix[user_item_matrix.nonzero()]
error_train =sqrt(mean_squared_error(prediction_flatten,user_item_matrix_flatten))# 均方根误差计算
print('训练集预测均方根误差:',error_train)
>> 训练集预测均方根误差:3.165938175006113
5.5 测试集预测
test_data_matrix =np.zeros((n_users,n_items))
forline intest_data.itertuples():
test_data_matrix[line[1]-1,line[2]-1]=line[3]
# 预测矩阵
rating_diff =(test_data_matrix -mean_user_rating[:,np.newaxis])# np.newaxis作用:为mean_user_rating增加一个维度,实现加减操作
user_precdiction =mean_user_rating[:,np.newaxis]+user_similarity_m.dot(rating_diff)/np.array([np.abs(user_similarity_m).sum(axis=1)]).T
# 只取数据集中有评分的数据集进行评估
prediction_flatten =user_precdiction[user_item_matrix.nonzero()]
user_item_matrix_flatten =user_item_matrix[user_item_matrix.nonzero()]
error_test =sqrt(mean_squared_error(prediction_flatten,user_item_matrix_flatten))# 均方根误差计算
print('测试集预测均方根误差:',error_test)
>> 测试集预测均方根误差:3.393103348518984
5.6 单模型结果提示思路
5.6.1 改变相似度算法 - 采用欧式距离
# 相似度计算定义为欧式距离
item_similarity_m =pairwise_distances(user_item_matrix.T,metric='euclidean')
>> 训练集预测均方根误差:3.1190848133071603
>> 测试集预测均方根误差:3.3913121798056123
5.6.2 减少训练集比例 / 增加测试集比例
fromsklearn.model_selection importtrain_test_split
train_data,test_data =train_test_split(data,test_size=0.4)
>> 训练集预测均方根误差:3.237884760612846
>> 测试集预测均方根误差:3.34890617988761
5.6.2 增加训练集比例
fromsklearn.model_selection importtrain_test_split
train_data,test_data =train_test_split(data,test_size=0.2)
>> 训练集预测均方根误差:3.094954182470391
>> 测试集预测均方根误差:3.435958471375406
5.6.3 增加测试集的同时采用欧式距离
>> 训练集预测均方根误差:3.1925775976328934
>> 测试集预测均方根误差:3.330738557937318
5.7 基于user协同过滤推荐系统结果分析
1、采用欧式距离的情况下,训练集数据预测效果提升较测试集明显;
2、运行结果显示基于user的预测结果在测试集上普遍不如在训练集上的预测结果。分析其原因:a.user相似矩阵本身太小(943*943),远小于item相似矩阵的(1682*1682);b.在原因a的基础上,测试集的矩阵就更小;
2、因而基于user协同过滤系统中,分别采用了减小/增大训练集两种优化方法对模型进行了测试,发现只要数据集增大,其预测效果就有提升;
3、在减小训练集并采用欧式距离的情况下,模型在测试集的预测效果有所提升,但依然不理想;
4、与基于item的协同过滤系统相比,基于user协同过滤系统模型预测效果明显略微优秀。
6 基于SVD协同过滤推荐系统
6.1 SVD协同推荐系统原理
6.2 代码实现
# 导入数据
importnumpy asnp
importpandas aspd
data=pd.read_csv('ml-100k/u.data',sep='\t',names=['user_id','item_id','rating','timestamp'])
# 拆分数据集并分别构建用户-物品矩阵
# 用户物品统计
n_users =data.user_id.nunique()
n_items =data.item_id.nunique()
fromsklearn.model_selection importtrain_test_split
# 按照训练集70%,测试集30%的比例对数据进行拆分
train_data,test_data =train_test_split(data,test_size=0.3)
# 训练集 用户-物品 矩阵
train_data_matrix =np.zeros((n_users,n_items))
forline intrain_data.itertuples():
train_data_matrix[line[1]-1,line[2]-1]=line[3]
# 测试集 用户-物品 矩阵
test_data_matrix =np.zeros((n_users,n_items))
forline intrain_data.itertuples():
test_data_matrix[line[1]-1,line[2]-1]=line[3]
# SVD矩阵
importscipy.sparse assp
fromscipy.sparse.linalg importsvds
# 奇异值分解,超参数k的值就是设定要留下的特征值的数量
u,s,vt =svds(train_data_matrix,k=20)
s_diag_matrix =np.diag(s)
svd_prediction =np.dot(np.dot(u,s_diag_matrix),vt)
'''
print(u.shape) >> (943, 20)
print(s.shape) >> (20,)
print(vt.shape) >> (20, 1682)
print(s_diag_matrix.shape) >> (20, 20)
print(svd_prediction.shape) >> (943, 1682)
'''
# 预测值限定最小值和最大值
# 预测值小于0的均设置为0,大于5的均设置为5
svd_prediction[svd_prediction <0]=0
svd_prediction[svd_prediction >5]=5
6.3 训练集预测
# 只取预测数据中有评分的数据,进行评估
fromsklearn.metrics importmean_squared_error
frommath importsqrt
prediction_flatten =svd_prediction[train_data_matrix.nonzero()]
train_data_matrix_flatten =train_data_matrix[train_data_matrix.nonzero()]
error_train =sqrt(mean_squared_error(prediction_flatten,train_data_matrix_flatten))
print('训练集预测均方根误差:',error_train)
>> 训练集预测均方根误差:2.440629842312816
6.4 测试集预测
prediction_flatten =svd_prediction[test_data_matrix.nonzero()]
test_data_matrix_flatten =test_data_matrix[test_data_matrix.nonzero()]
error_test =sqrt(mean_squared_error(prediction_flatten,test_data_matrix_flatten))
print('测试集预测均方根误差:',error_test)
>> 测试集预测均方根误差:2.440629842312816
7 三大协同过滤推荐系统总结分析
1、总体而言,基于小规模MovieLens数据集的本案例中的三大协同过滤推荐系统,其预测的效果总体上可以表示为:推荐系统预测效果:SVD > user > item。
2、根据基于user系统过滤推荐系统的情况可以看出,协同过滤推荐系统的数据越多,且数据之间互动越多,则推荐效果越好,然而一般情况下正是因为互动不够充分才会需要推荐系统,所以,收集尽可能多的数据,基于大数据的分析就显的相对比较重要;
3 在三大推荐系统中,SCD奇异值推荐系统表现尤为突出,预测的结果相对于其他两个推荐系统而言有非常大的提升,唯一的缺点就是其难以加以解释,但不失为是一种非常好的推荐系统。
NMF
参考
python电影推荐系统_电影推荐系统---协同过滤算法(SVD,NMF)相关推荐
- 推荐系统--基于用户的协同过滤算法
1. 概述 和搜索引擎一样,推荐系统是为了帮助人们更快速的获得对自己有用的信息. 和搜索引擎不同,推荐系统是人们被动的获取,由系统根据用户行为或其他的信息推荐给用户的,儿搜索引擎是用户 ...
- 推荐系统user-based和item-based协同过滤算法定性比较
研究生期间做了两年的推荐系统.数据挖掘方面的学术研究,因为工作的原因,近期正在整理当初的学习资料和代码,本篇主要参考资料为项亮的<推荐系统实践>. 在现实的情况中,往往物品的个数是远远小于 ...
- 推荐系统-基于领域的协同过滤算法选择(一文足矣)
1.基于用户的协同过滤算法(UserCF) 1.1. 基本思想 该算法主要用于计算两个用户之间的相似度,这里的相似度指的是两个用户之间的兴趣相似度.假设存在用户u和用户v,N(u)和N(v)分别是他们 ...
- ncf 推荐系统_浅析神经协同过滤NCF在推荐系统的应用
NCF在推荐领域应用背景 CF,也就是协同过滤,在推荐领域有极其广泛的应用,应该没有谁的智能推荐系统是没用到过CF的.CF其实就是挖掘user和item的交互关系,然后生成I2I或者U2I表示向量.传 ...
- 《推荐系统》基于用户和Item的协同过滤算法的分析与实现(Python)
1:协同过滤算法简介 2:协同过滤算法的核心 3:协同过滤算法的应用方式 4:基于用户的协同过滤算法实现 5:基于物品的协同过滤算法实现 一:协同过滤算法简介 关于协同过滤的一个最经典的例子就是看电影 ...
- 【4】协同过滤算法的原理与实现
一:协同过滤算法简介 关于协同过滤的一个最经典的例子就是看电影,有时候不知道哪一部电影是我们喜欢的或者评分比较高的,那么通常的做法就是问问周围的朋友,看看最近有什么好的电影推荐.在问的时候,都习惯于问 ...
- 基于Spark MLlib平台的协同过滤算法---电影推荐系统
协同过滤算法概述 基于模型的协同过滤应用---电影推荐 实时推荐架构分析 一.协同过滤算法概述 本人对算法的研究,目前还不是很深入,这里简单的介绍下其工作原理. 通常,协同过滤算法按照数据使用 ...
- spark MLlib平台的协同过滤算法---电影推荐系统
又好一阵子没有写文章了,阿弥陀佛...最近项目中要做理财推荐,所以,回过头来回顾一下协同过滤算法在推荐系统中的应用. 说到推荐系统,大家可能立马会想到协同过滤算法.本文基于Spark MLlib平台实 ...
- java计算机毕业设计基于ssm的协同过滤算法的电影推荐系统(源代码+数据库+Lw文档)
项目介绍 "互联网+"的战略实施后,很多行业的信息化水平都有了很大的提升.但是目前很多行业的管理仍是通过人工管理的方式进行,需要在各个岗位投入大量的人力进行很多重复性工作,使得对人 ...
- 基于协同过滤算法的电影推荐系统
目录 前言 R语言 电影推荐系统 案例及代码 数据准备 数据预处理 建立模型 前言 电影推荐系统是数学建模培训中一次例题,网上对相同类型的模型已有答案,但相关代码跑起来仍然存在些许bug,本文基于同类 ...
最新文章
- 如何用SPY++工具查看窗体的句柄
- MongoDB整理笔记の管理Replica Sets
- bottle中文文档
- 腾讯天美六位TA:技术美术这份职业会长期存在吗?
- 在线课程学习、科研科技视频网站
- What means the error-message 'java.lang.OutOfMemoryError: GC overhead limit exceeded' in Java?
- (2)连续存储数组的方法
- 【剑指offer】面试题24:反转链表(Java 实现)
- 谈谈社区、产品和新Dubbo | 从Dubbo 的社区star 数突破 2 万说起
- Vijos 1603 ----迷宫(矩阵乘法,矩阵快速幂)
- lightroom手机版下载_vnc控制手机版下载,vnc控制手机版下载的使用教程
- 计算机专业大学四年应该怎么过才有意义?
- kd树介绍(KNN算法引出)
- 删除android电视软件下载,安卓智能电视必装工具没有之一,进程管理备份清理全靠它!...
- Page Cache(页面缓存)
- 用python把视频转换为图片
- 马斯克血洗推特!传机器学习裁员90%,团队直接解散
- Stored Outline
- 利用Scrapy编写“1024网站种子吞噬爬虫”,送福利
- python基础—列表解析式简单应用