A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

第一步:收集和清洗数据数据链接:https://grouplens.org/datasets/movielens/
下载文件:ml-latest-small


import pandas as pdimport numpy as npimport tensorflow as tf复制代码导入ratings.csv文件
ratings_df = pd.read_csv('./ml-latest-small/ratings.csv')ratings_df.tail()#tail命令用于输入文件中的尾部内容。tail命令默认在屏幕上显示指定文件的末尾5行。复制代码结果:
                userId      movieId      rating      timestamp   
              99999      671      6268      2.5      1065579370   
          100000      671      6269      4.0      1065149201   
          100001      671      6365      4.0      1070940363   
          100002      671      6385      2.5      1070979663   
          100003      671      6565      3.5      1074784724   
导入movies.csv文件
movies_df = pd.read_csv('./ml-latest-small/movies.csv')movies_df.tail()复制代码结果:
                movieId      title      genres   
              9120      162672      Mohenjo Daro (2016)      Adventure|Drama|Romance   
          9121      163056      Shin Godzilla (2016)      Action|Adventure|Fantasy|Sci-Fi   
          9122      163949      The Beatles: Eight Days a Week - The Touring Y...      Documentary   
          9123      164977      The Gay Desperado (1936)      Comedy   
          9124      164979      Women of '69, Unboxed      Documentary   
将movies_df中的movieId替换为行号
movies_df['movieRow'] = movies_df.index#生成一列‘movieRow’,等于索引值indexmovies_df.tail()复制代码结果:
                movieId      title      genres      movieRow   
              9120      162672      Mohenjo Daro (2016)      Adventure|Drama|Romance      9120   
          9121      163056      Shin Godzilla (2016)      Action|Adventure|Fantasy|Sci-Fi      9121   
          9122      163949      The Beatles: Eight Days a Week - The Touring Y...      Documentary      9122   
          9123      164977      The Gay Desperado (1936)      Comedy      9123   
          9124      164979      Women of '69, Unboxed      Documentary      9124   
筛选movies_df中的特征
movies_df = movies_df[['movieRow','movieId','title']]#筛选三列出来movies_df.to_csv('./ml-latest-small/moviesProcessed.csv', index=False, header=True, encoding='utf-8')#生成一个新的文件moviesProcessed.csvmovies_df.tail()复制代码结果:
                movieRow      movieId      title   
              9120      9120      162672      Mohenjo Daro (2016)   
          9121      9121      163056      Shin Godzilla (2016)   
          9122      9122      163949      The Beatles: Eight Days a Week - The Touring Y...   
          9123      9123      164977      The Gay Desperado (1936)   
          9124      9124      164979      Women of '69, Unboxed   
根据movieId,合并rating_df和movie_df
ratings_df = pd.merge(ratings_df, movies_df, on='movieId')ratings_df.head()复制代码结果:
                userId      movieId      rating      timestamp      movieRow      title   
              0      1      31      2.5      1260759144      30      Dangerous Minds (1995)   
          1      7      31      3.0      851868750      30      Dangerous Minds (1995)   
          2      31      31      4.0      1273541953      30      Dangerous Minds (1995)   
          3      32      31      4.0      834828440      30      Dangerous Minds (1995)   
          4      36      31      3.0      847057202      30      Dangerous Minds (1995)   
筛选ratings_df中的特征
ratings_df = ratings_df[['userId','movieRow','rating']]#筛选出三列ratings_df.to_csv('./ml-latest-small/ratingsProcessed.csv', index=False, header=True, encoding='utf-8')#导出一个新的文件ratingsProcessed.csvratings_df.head()复制代码结果:
                userId      movieRow      rating   
              0      1      30      2.5   
          1      7      30      3.0   
          2      31      30      4.0   
          3      32      30      4.0   
          4      36      30      3.0   
第二步:创建电影评分矩阵rating和评分纪录矩阵recorduserNo = ratings_df['userId'].max() + 1#userNo的最大值movieNo = ratings_df['movieRow'].max() + 1#movieNo的最大值复制代码rating = np.zeros((movieNo,userNo))#创建一个值都是0的数据flag = 0ratings_df_length = np.shape(ratings_df)[0]#查看矩阵ratings_df的第一维度是多少for index,row in ratings_df.iterrows():    #interrows(),对表格ratings_df进行遍历    rating[int(row['movieRow']),int(row['userId'])] = row['rating']    #将ratings_df表里的'movieRow'和'userId'列,填上row的‘评分’    flag += 1复制代码record = rating > 0recordrecord = np.array(record, dtype = int)#更改数据类型,0表示用户没有对电影评分,1表示用户已经对电影评分record复制代码结果:
array([[0, 0, 0, ..., 0, 1, 1],       [0, 0, 0, ..., 0, 0, 0],       [0, 0, 0, ..., 0, 0, 0],       ...,       [0, 0, 0, ..., 0, 0, 0],       [0, 0, 0, ..., 0, 0, 0],       [0, 0, 0, ..., 0, 0, 0]])复制代码第三步:构建模型def normalizeRatings(rating, record):    m, n =rating.shape    #m代表电影数量,n代表用户数量    rating_mean = np.zeros((m,1))    #每部电影的平均得分    rating_norm = np.zeros((m,n))    #处理过的评分    for i in range(m):        idx = record[i,:] !=0        #每部电影的评分,[i,:]表示每一行的所有列        rating_mean = np.mean(rating[i,idx])        #第i行,评过份idx的用户的平均得分;        #np.mean() 对所有元素求均值        rating_norm[i,idx] -= rating_mean        #rating_norm = 原始得分-平均得分    return rating_norm, rating_mean复制代码rating_norm, rating_mean = normalizeRatings(rating, record)复制代码结果:
/root/anaconda2/envs/python3/lib/python3.6/site-packages/numpy/core/fromnumeric.py:2957: RuntimeWarning: Mean of empty slice.  out=out, **kwargs)/root/anaconda2/envs/python3/lib/python3.6/site-packages/numpy/core/_methods.py:80: RuntimeWarning: invalid value encountered in double_scalars  ret = ret.dtype.type(ret / rcount)复制代码注:如果数据出现较多的NaNN,对后面的运算影响较大
rating_norm =np.nan_to_num(rating_norm)#对值为NaNN进行处理,改成数值0rating_norm复制代码结果:
array([[ 0.        ,  0.        ,  0.        , ...,  0.        ,        -3.87246964, -3.87246964],       [ 0.        ,  0.        ,  0.        , ...,  0.        ,         0.        ,  0.        ],       [ 0.        ,  0.        ,  0.        , ...,  0.        ,         0.        ,  0.        ],       ...,       [ 0.        ,  0.        ,  0.        , ...,  0.        ,         0.        ,  0.        ],       [ 0.        ,  0.        ,  0.        , ...,  0.        ,         0.        ,  0.        ],       [ 0.        ,  0.        ,  0.        , ...,  0.        ,         0.        ,  0.        ]])复制代码
rating_mean =np.nan_to_num(rating_mean)#对值为NaNN进行处理,改成数值0rating_mean复制代码结果:
array([[3.87246964],       [3.40186916],       [3.16101695],       ...,       [3.        ],       [0.        ],       [5.        ]])复制代码构建模型
num_features = 10X_parameters = tf.Variable(tf.random_normal([movieNo, num_features],stddev = 0.35))Theta_parameters = tf.Variable(tf.random_normal([userNo, num_features],stddev = 0.35))#tf.Variables()初始化变量#tf.random_normal()函数用于从服从指定正太分布的数值中取出指定个数的值,mean: 正态分布的均值。stddev: 正态分布的标准差。dtype: 输出的类型复制代码loss = 1/2 * tf.reduce_sum(((tf.matmul(X_parameters, Theta_parameters, transpose_b = True) - rating_norm) * record) ** 2) + 1/2 * (tf.reduce_sum(X_parameters ** 2) + tf.reduce_sum(Theta_parameters ** 2))#基于内容的推荐算法模型复制代码

# 函数解释:# reduce_sum() 就是求和,reduce_sum( input_tensor, axis=None,  keep_dims=False, name=None, reduction_indices=None)# reduce_sum() 参数解释:# 1) input_tensor:输入的张量。# 2) axis:沿着哪个维度求和。对于二维的input_tensor张量,0表示按列求和,1表示按行求和,[0, 1]表示先按列求和再按行求和。# 3) keep_dims:默认值为Flase,表示默认要降维。若设为True,则不降维。# 4) name:名字。# 5) reduction_indices:默认值是None,即把input_tensor降到 0维,也就是一个数。对于2维input_tensor,reduction_indices=0时,按列;reduction_indices=1时,按行。# 6) 注意,reduction_indices与axis不能同时设置。# tf.matmul(a,b),将矩阵 a 乘以矩阵 b,生成a * b# tf.matmul(a,b)参数解释:# 1) a:类型为 float16,float32,float64,int32,complex64,complex128 和 rank > 1的张量。# 2) b:与 a 具有相同类型和 rank。# 3) transpose_a:如果 True,a 在乘法之前转置。# 4) transpose_b:如果 True,b 在乘法之前转置。# 5) adjoint_a:如果 True,a 在乘法之前共轭和转置。# 6) adjoint_b:如果 True,b 在乘法之前共轭和转置。# 7) a_is_sparse:如果 True,a 被视为稀疏矩阵。# 8) b_is_sparse:如果 True,b 被视为稀疏矩阵。# 9) name:操作名称(可选)复制代码优化算法
optimizer = tf.train.AdamOptimizer(1e-4)# https://blog.csdn.net/lenbow/article/details/52218551train = optimizer.minimize(loss)# Optimizer.minimize对一个损失变量基本上做两件事# 它计算相对于模型参数的损失梯度。# 然后应用计算出的梯度来更新变量。复制代码第四步:训练模型# tf.summary的用法 https://www.cnblogs.com/lyc-seu/p/8647792.htmltf.summary.scalar('loss',loss)#用来显示标量信息复制代码结果:<tf.Tensor 'loss_1:0' shape=() dtype=string>
summaryMerged = tf.summary.merge_all()#merge_all 可以将所有summary全部保存到磁盘,以便tensorboard显示。filename = './movie_tensorborad'writer = tf.summary.FileWriter(filename)#指定一个文件用来保存图。sess = tf.Session()#https://www.cnblogs.com/wuzhitj/p/6648610.htmlinit = tf.global_variables_initializer()sess.run(init)#运行复制代码for i in range(5000):    _, movie_summary = sess.run([train, summaryMerged])    # 把训练的结果summaryMerged存在movie里    writer.add_summary(movie_summary, i)    # 把训练的结果保存下来复制代码查看训练结果:在终端输入 tensorboard --logir=./




第五步:评估模型Current_X_parameters, Current_Theta_parameters = sess.run([X_parameters, Theta_parameters])# Current_X_parameters为用户内容矩阵,Current_Theta_parameters用户喜好矩阵predicts = np.dot(Current_X_parameters,Current_Theta_parameters.T) + rating_mean# dot函数是np中的矩阵乘法,np.dot(x,y) 等价于 x.dot(y)errors = np.sqrt(np.sum((predicts - rating)**2))# sqrt(arr) ,计算各元素的平方根errors复制代码结果:
4037.9002717628305复制代码第六步:构建完整的电影推荐系统user_id = input('您要想哪位用户进行推荐?请输入用户编号:')sortedResult = predicts[:, int(user_id)].argsort()[::-1]# argsort()函数返回的是数组值从小到大的索引值; argsort()[::-1] 返回的是数组值从大到小的索引值idx = 0print('为该用户推荐的评分最高的20部电影是:'.center(80,'='))# center() 返回一个原字符串居中,并使用空格填充至长度 width 的新字符串。默认填充字符为空格。for i in sortedResult:    print('评分: %.2f, 电影名: %s' % (predicts[i,int(user_id)],movies_df.iloc['title']))    # .iloc的用法:https://www.cnblogs.com/harvey888/p/6006200.html    idx += 1    if idx == 20:break复制代码结果:
您要想哪位用户进行推荐?请输入用户编号:123==============================为该用户推荐的评分最高的20部电影是:===============================评分: 5.03, 电影名: Fireworks Wednesday (Chaharshanbe-soori) (2006)评分: 4.88, 电影名: Woman on the Beach (Haebyeonui yeoin) (2006)评分: 4.73, 电影名: Mummy's Ghost, The (1944)评分: 4.66, 电影名: Maborosi (Maboroshi no hikari) (1995)评分: 4.63, 电影名: Boiling Point (1993)评分: 4.60, 电影名: Mala Noche (1985)评分: 4.49, 电影名: All-Star Superman (2011)评分: 4.47, 电影名: Bill Hicks: Relentless (1992)评分: 4.45, 电影名: Something Borrowed (2011)评分: 4.37, 电影名: Box of Moon Light (1996)评分: 4.37, 电影名: Kwaidan (Kaidan) (1964)评分: 4.35, 电影名: Sacrifice, The (Offret - Sacraficatio) (1986)评分: 4.29, 电影名: Hotel de Love (1996)评分: 4.27, 电影名: Aria (1987)评分: 4.23, 电影名: Querelle (1982)评分: 4.22, 电影名: Rocky VI (1986) 评分: 4.21, 电影名: Little Lord Fauntleroy (1936)评分: 4.19, 电影名: Hardcore (1979)评分: 4.16, 电影名: Three of Hearts (1993)评分: 4.15, 电影名: White Stripes Under Great White Northern Lights, The (2009)

作者:Kervin_Chan
链接:https://juejin.im/post/5afbfe316fb9a07aa5427d73



2 个回复

正序浏览
回复 使用道具 举报

奈斯,很赞
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马