● 数据获取
将数据集下载并保存在本地
http://files.grouplens.org/datasets/movielens/ml-100k.zip 解压到项目文件下
其中u.data文件包含完整的数据集,README 是对整个数据文件的介绍,从中可以得知u.data中的列依次为:
user id|item id|rating|timestamp 这里的物品是指电影
二、完整代码
◆ 导入机器学习库
from IPython.core.intersectiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all'
%matplotlib inline
import numpy as np
import pandas as pd
header = ['user_id','item_id','rating','timestamp']
src_data = pd.read_csv('./u.data',nep = '\t',names = header) #读取文件路径
src_data.head() #查看文件
● 1 查看数据总体情况
src_data.discribe()
src_data.user_id.nuinique() #查看用户去重个数
src_data.item_id.nuinique() #查看物品去重个数
src_data.duplicated(subset = ['user_id','item_id']).sum()
#检查是否有重复的用户物品打分记录
● 2.1 每个用户对应的客户数
item_id_userent = src_data.groupby('item id').count()['user_id']
import matplotlib.pyplot as plt
plt.hist(item_id_userent.values) #通过直方图观看
plt.plot()
● 2.2 每个物品对应的用户数(10分位,20分位。。。100分位数)
np.arange(0,1.1,0.1)
item_id_userent.quantile(q = np.arange(0,1.1,0.1))
● 3 观察用户-物品矩阵
n_users = src_data.user_id.nuinique()
n_items = src_data.item_id.nuinique()
src_data_matrix = np.zeros({n_users,n_items}) #构建用户物品矩阵
for line in src_data.itertuples():
src_data_matrix[line[1]-1,line[2]-1 = line[3]]
sparsity = round(len(src_data_matrix.nonzore()\
[1])/float(n_users*n_items),3) #矩阵稀疏性
sparsity
————————- 基于item的协同过滤推荐原理 ———————-
● 1 数据导入
from IPython.core.intersectiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all'
%matplotlib inline
import numpy as np
import pandas as pd
header = ['user_id','item_id','rating','timestamp']
src_data = pd.read_csv('./u.data',nep = '\t',names = header) #读取文件路径
src_data.head() #查看文件
● 2 构建用户-物品数据统计
n_users = src_data.user_id.nuinique()
n_items = src_data.item_id.nuinique()
#训练集-测试集分离
from sklearn.model_selection import train_test_split
train_data,test_data = train_test_split(src_data,test_size = 0.3) #拆分训练集-测试集
#训练集-用户-物品矩阵
user_item_matrix = np.zeros(n_users,n_items)
for line in train_data.itertuples():
user_item_matrix[line[1]-1,line[2]-1 = line[3]]
#用户相似度矩阵(相似度算法采用余弦算法)
#使用 sklearn.metrics.pairwise 中的 cosine
from sklearn.metrics.pairwise import pairwise_distances
item_similarity_m = pairwise_distances(user_item_matrix.T,metric = 'cosine')
item_similarity_m.shape #物品相似度矩阵 行列
round(np.sum(item_similarity_m > 0)/float(item_similarity_m.shape[0]*\
item_similarity_m.shape[1]),3) #非0值比例
item_similarity_m[0:5,0:5],round(2) #相似度矩阵为对称矩阵
#现在只分析上三角 得到等分位数
item_similarity_m_triu = np.triu(item_similarity_m,k = 1) #对角线0右边的三角矩阵
item_sim_nonzero = np.round(item_similarity_m_triu(item_similarity_m_triu.nonzore()),3)
np.percentile(item_sim_nonzero,np.arange(0,101,10)) #得出相似度大,没有区分性
#知识讲解:上三角函数 np.triu
arr = np.linspace(1,9,9).reshape(3,3)
np.triu(arr,k = 1)
● 3 训练集预测
3.1得到预测矩阵
user_item_prediction = user_item_matrix.dot(item_similarity_m)/np.array([item_similarity_m).sum(axis=1)])
#只取预测数据集中有评分的数据集,进行评估
from sklearn.metrics import mean_squared_error
from math import sqrt
prediction_flatten = user_item_prediction[user_item_matrix.nonzore()]
user_item_matrix_flatten = user_item_matrix[user_item_matrix.nonzore()]
sqrt(mean_squared_error(prediction_flatten,user_item_matrix_flatten))
3.2 测试集预测
test_data_matrix = np.zeros(n_users,n_items) #测试数据集构建
for line in test_data.itertuples():
test_item_matrix[line[1]-1,line[2]-1 = line[3]]
#预测矩阵
item_prediction = user_item_matrix.dot(item_similarity_m)/np.array\
([item_similarity_m).sum(axis=1)])
#只取预测数据集中有评分的数据集评估
from sklearn.metrics import mean_squared_error
from math import sqrt
prediction_flatten = item_prediction[test_data_matrix.nonzore()]
test_data_matrix_flatten = test_data_matrix[test_data_matrix.nonzore()]
sqrt(mean_squared_error(prediction_flatten,test_data_matrix_flatten))
3.3 单模型结果提升思路
#改变相似度算法--余弦近距离->欧式距离
item_similarity_m = pairwise_distances(user_item_matrix.T,metric = 'euclidean')
#增加训练数据
train_data,test_data = train_test_split(src_data,test_size = 0.2)
——————– 基于SVD的协同过滤推荐原理 ———————-
● 1.数据导入
from IPython.core.intersectiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all'
%matplotlib inline
import numpy as np
import pandas as pd
header = ['user_id','item_id','rating','timestamp']
src_data = pd.read_csv('./u.data',nep = '\t',names = header) #读取文件路径
src_data.head() #查看文件
● 2 构建用户-物品数据统计
n_users = src_data.user_id.nuinique()
n_items = src_data.item_id.nuinique()
#训练集-测试集分离
from sklearn.model_selection import train_test_split
train_data,test_data = train_test_split(src_data,test_size = 0.3) #拆分训练集-测试集
#训练集-用户-物品矩阵
train_data_matrix = np.zeros(n_users,n_items)
for line in train_data.itertuples():
train_data_matrix[line[1]-1,line[2]-1 = line[3]]
● 3 SVD矩阵
import scipy.sparse as sp
from scipy.sparse.linalg import svds
#get SVD components from train matrix.Choose 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)
● 3.1 查看数据
u.shape
s.shape
vt.shape
s_diag_matrix
svd_prediction.shape
#查看-预测矩阵值分布
pd.Series(np.precentile(svd_prediction,np.arange(0,101,10))).map('{:.2f}'.format)
#查看--训练数据-矩阵值分布
pd.Series(np.precentile(train_data_matrix,np.arange(0,101,10))).map('{:.2f}'.format)
#查看--训练数据-矩阵-非0值分布
pd.Series(np.precentile(train_data_matrix[train_data_matrix,nonzore()]np.arange(0,101,10))).map('{:.2f}'.format)
● 3.2 预测值-限定最大值和最小值
svd_prediction[svd_prediction < 0] = 0 #预测值小于0 则为0
svd_prediction[svd_prediction > 5] = 5 #预测值大于5 则为5
● 3.3 RMSE评估--训练集预测
#只取预测数据集中有评分的数据集,进行评估
from sklearn.metrics import mean_squared_error
from math import sqrt
prediction_flatten = svd_prediction[train_data_matrix.nonzore()]
train_data_matrix_flatten = train_data_matrix[train_data_matrix.nonzore()]
sqrt(mean_squared_error(prediction_flatten,train_data_matrix_flatten))
● 3.4 测试集预测
#只取预测数据集中有评分的数据集评估
from sklearn.metrics import mean_squared_error
from math import sqrt
prediction_flatten = svd_prediction[test_data_matrix.nonzore()]
test_data_matrix_flatten = test_data_matrix[test_data_matrix.nonzore()]
sqrt(mean_squared_error(prediction_flatten,test_data_matrix_flatten))
● 3.5 单模型结果提升思路
#1 改变相似度算法--余弦近距离->欧式距离
item_similarity_m = pairwise_distances(user_item_matrix.T,metric = 'euclidean')
#2 增加训练数据
train_data,test_data = train_test_split(src_data,test_size = 0.2)