首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如何知道喜欢的人ta喜欢什么?

这几天在看《推荐系统实践》,说实话看完以后我整个人的三观都崩塌了,现在只要拿起手机刷一刷B站或者酷狗,我就会去想他们是怎么做推荐的……

书中介绍了一种基于协同过滤算法的推荐系统,讲到推荐算法的话,书中提到了ItemCFUserCF算法两种,当然还有机器学习的图运算,然后基于此对算法进行了改进和升级。

我们今天主要来尝试一下用tensorflow来给电影视频做推荐。我们采用的数据集来源自MovieLens:https://grouplens.org/datasets/movielens/

我们的目的其实就是基于用户或者是基于物品给用户推荐物品,或者是把新物品推荐给可能感兴趣的用户。用数据来量化呢,就是要去寻找两个物品/用户之间的相似度。

主要的方法有三种:

基于欧氏距离——

相似度公式就是——

也可以使用余项相似度——

或者是皮尔逊相似度——

其实无论哪种公式,都会有在位置0处值为1且为最大值。

那么有了理论基础之后,我们就要开始用机器学习的方式来尝试一下推荐算法。

1.准备数据集

首先把之前的数据集给下载了。

数据格式解析

movieLens20M使用了CSV格式存储数据列表,代替了10M和1M、100K的DAT格式,可以直接可视化分析。

文件列表:

genome_scores.csv、genome-tags.csv、links.csv、movies.csv、ratings.csv、tags.csv。

movies.csv:MovieId+title+geners。以此表示电影ID、电影名称、电影流派/种类。其中电影流派具有多个标签,即可以表示电影的多个属性。用以生成电影属性矩阵。

Rating.csv:userId+movieId+rating+timestamp。分别表示用户ID、电影ID、评分,以及截至时间戳。给出了用户对电影的评分列表。用以生成用户-电影评分矩阵。

Trgs.csv: userId+ movieId+tag+timestamp。分别表示用户ID、电影ID、用户对电影的标签、时间戳。给出了用户对电影的标签列表。用以生成用户-电影标签矩阵。

Links.csv:moviesId+imdeId+tmdbId。IMDB为互联网电影资料库。tMDB为电影数据集。给出了电影ID和两个数据标记ID的对应关系。

genome_tags.csv:电影标签 DNA标记,唯一标识符。

genome_scores.csv: movieId+tagId+relevance。分别表示电影ID、电影标签ID、官方标签相关性。给出了电影的官方标签。用以生成电影的标签相关性矩阵。

2.数据的清洗

先导入库

importpandasaspd

importnumpyasnp

importtensorflowastf

读取电影评分的ratings.csv文件

ratings_df = pd.read_csv('Desktop/ml-latest-small/ratings.csv')

我们来看一下这个表中最后几行的内容

ratings_df.tail()

同理读取电影库的.csv文件

movies_df = pd.read_csv('Desktop/ml-latest-small/movies.csv')

movies_df.tail()

可以看到最后是

增加一列名为movieRow的索引值,内容为行号:

movies_df['MovieRow'] = movies_df.index

movies_df.tail()

3.特征提取

首先提取我们需要的特征

movies_df = movies_df[['MovieRow','movieId','title']]

movies_df.tail()

然后我们将这个列表作为处理好的数据储存起来方便后面用到:

movies_df.to_csv('Desktop/ml-latest-small/moviesProcessed.csv',index=False, header =True, encoding ='utf-8')

储存好了特征提取之后的数据之后,我们将评分列表和电影列表合并,并对其movieId这一列。

ratings_df = pd.merge(ratings_df, movies_df,on='movieId')

ratings_df.head()

合并两张表之后,我们将合并好的表再来提取特征:

ratings_df = ratings_df[['userId','MovieRow','rating']]

ratings_df.head()

4.创建电影评分矩阵rating和评分记录矩阵record

特征提取完成之后,首先我们来获取评分的用户和电影的数量:

userNo = ratings_df['userId'].max()+1

movieNo = ratings_df['MovieRow'].max()+1

接下来创建一个movieNo行,userNo列,内容是0的矩阵:

rating = np.zeros((movieNo,userNo))

但是有一个错误…

内…内存不足……

计算了一下大概是一个27278x138494的零矩阵,也就大概40TB吧………玩数据挖掘的估计家里有矿吧

所以我们换了ml-latest-small…小一点吧,重新前面的操作

设置一个标签位flag,然后获取合并之后列表的列数,然后遍历rating矩阵每一个位置,将电影的评分填入矩阵中:

#标志位

flag = 0

#获取合并表中的列数

ratings_df_length = np.shape(ratings_df)[0]

#遍历矩阵,将电影的评分填入表中

for index,row in ratings_df.iterrows():

rating[int(row['MovieRow']), int(row['userId'])] = row['rating']

flag += 1

print('processed %d, %d left' %(flag,ratings_df_length-flag))

然后我们来获取一个电影是否被用户评分的列表,其中1代表该电影已经被用户评分,0是用户没有对该电影评分:

record = rating > 0

record = np.array(record, dtype = int)

record

可以得到结果矩阵:

同时我们也可以得到评分的矩阵:

5.构建模型

构建模型之前,我们将nan的地方转成数字0:

rating_norm = np.nan_to_num(rating_norm)

然后我们来定义一个标准化评分表的方法:

def normalizeRatings(rating, record):

#获取电影的数量m和用户的数量n

m,n = rating.shape

#rating_mean-电影平均分 rating_norm-标准化后的电影得分

rating_mean = np.zeros((m,1))

#rating_norm = np.zeros((m,n))

#rating_norm = np.nan_to_num(rating_norm)

rating_norm = np.nan_to_num(np.zeros((m,n)))

fori in range(m):

idx = record[i,:]!=0

rating_mean[i] = np.mean(rating[i,idx])

rating_norm[i,idx] -= rating_mean[i]

rating_mean = np.nan_to_num(rating_mean)

returnrating_norm, rating_mean

可以得到标准化后的矩阵:

接下来就是用TensorFlow来构建模型:

num_features =10

X_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,就做不了TFboy了~

基于内容推荐算法的损失函数公式:

在这个公式中,r(x,y)是评分记录表,u是用户数量,θ(j)是j用户的喜好,y(i,j)是i用户对j电影的评分,xi表示电影的内容,n是特征数量,最后一部分是正则化项。我们后续的目的就是来最小化这个损失函数,接下来就是优化J(θ),使其最小化。

optimizer = tf.train.AdamOptimizer(1e-4)

train = optimizer.minimize(loss)

最后的步骤就是训练模型了:

结果:

#merge_all可以将所有summary全部保存到磁盘,以便tensorboard显示。

filename ='./movie_tensorborad'

writer = tf.summary.FileWriter(filename)

#指定一个文件用来保存图。

sess = tf.Session()

#定义一个session

init = tf.global_variables_initializer()

sess.run(init)

#运行session

接下来就是递归5000次,直到收敛:

for iinrange(5000):

_, movie_summary = sess.run([train, summaryMerged])

writer.add_summary(movie_summary, i)

模型训练完成之后,我们再来评估一下我们训练的模型:

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

errors = np.sqrt(np.sum((predicts - rating)**2))

# sqrt(arr) ,计算各元素的平方根

Errors

userId = input('您要向哪位用户进行推荐呢?请输入用户编号:(smaller than672)')

sortedResult = predicts[:,int(userId)].argsort()[::-1]

idx =

print('为该用户推荐的评分最高的20部电影是:'.center(80,'='))

foriinsortedResult:

print('score: %.3f, movie name: %s'% (predicts[i,int(userId)], movies_df.iloc[i]['title']))

idx +=1

ifidx ==20:break

我们可以输入用户的ID,然后就可以得到如下的电影推荐输出:

好了,这样我们就可以实现基于数据的简单挖掘了~

我是垚垚,我们下期再见:)

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180807G0C6F400?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券