[笔记]推荐系统实战第二课


()12月1日,课程以“协同过滤”为开始讲解到“矩阵分解”,随后对于矩阵分解过程中可以优化的地方扩展到“深度学习”的对于“协同过滤”,“矩阵分解”可能的优化。

课程主要以

MovieLens
​grouplens.org
数据集为例子,代码基于tensorflow实现(自动实现反向传播)。

简单查看一下MovieLens的数据集的字段。

1.movies.dat

电影ID::电影名::电影风格

MovieID::Title::Genres

2.users.dat

用户ID::性别::年龄::职业ID::邮编

UserID::Gender::Age::Occupation::Zip-code

3.ratings.dat

用户ID::电影ID::评分::时间戳

UserID::MovieID::Rating::Timestamp

以上为数据的基本字段介绍,简化问题,仅仅考虑 ratings.dat 文件的信息。

协同过滤算法(CF)

基本思想描述为:通过描述用户的行为对商品的推荐提供建议。基本方法分为:

User-based CF / Item-based CF

1.User-based CF

在 ratings.dat 中的数据选择 UserID-MovieID-Rating 三个字段组成一个矩阵。这里简单模拟一下数据的样式。

请输入图片名称

纵轴A,B,C,D,E为用户的列表,横轴表示商品的列表,用户与商品的交接处表示打分。

通过这张表,我们可以计算不同用户组合之间的相似性,例如以用户A为基准,可以计算出与A相似的用户BCDE的相似的大小。通过计算后,可以得到一个新的矩阵。

请输入图片名称

这样我们既可以得到一个User-based CF的算法对用户进行推荐了。可以找到与A相似的用户,C,B,E,D 为相似度排序,这样我们可以选择【1,max(user)-1】的用户。假设选择2:

相似度AC*(C用户打分的商品)+相似度AC*(B用户打分的商品) / 相似度AC + 相似度AC

得到一个商品打分集合,从该集合去掉用户已经打分过的商品,得到剩下的商品,推荐给用户A。

2.Item-based CF

基本流程与User-based CF 类似,这里是通过用户表示商品,计算出商品的相似度。

例如:用户A看过商品linux入门,假设linux入门与python入门与统计学习方法相似度较高,则可以得到

python入门: 与python入门相似度值 * linux入门打分 / 与统计学习方法相似度值

统计学习方法 : 与统计学习方法相似度值 * linux入门打分 / 与python入门相似度值

这样可以计算出,用户可能对于 python入门和统计学习方法的打分。

3 Model-based CF

由于1,2方法存在复杂度较高,且高度稀疏的特点,大部分的打分都为0,因此需要克服1,2的缺点,从而出现了方法3。

这种方法基本思路为:

请输入图片名称

将原始的用户商品打分矩阵,通过分解为(用户,隐维度)和(商品,隐维度)的表示。

具体理论知识,可以阅读一些矩阵分解的论文,这里直接用代码表示一下

coding:utf-8

七月在线 推荐系统 第二课 课程内容

import pandas as pd
import warnings
warnings.filterwarnings('ignore')

path = './ml-1m/'

users = pd.read_csv(path + 'users.dat',sep='::',header=None)
users.columns = ['UserID','Gender','Age','Occupation','ZipCode']

movies = pd.read_csv(path + 'movies.dat',sep='::',header=None)
movies.columns = ['MovieID','Title','Genres']

ratings = pd.read_csv(path + 'ratings.dat',sep='::',header=None)
ratings.columns = ['UserID','MovieID','Rating','Timestamp']

由于id的开始是从1开始的,需要补充一个0的开始

UserIDCount = max(users['UserID']) + 1
MoviesIDCount = max(movies['MovieID']) + 1

train = ratings[['UserID','MovieID']].values
label = ratings['Rating'].values

划分训练数据和验证数据

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(train,label,test_size=0.2,random_state=42,shuffle=True)

train_users = X_train[:,0]
train_movies = X_train[:,1]
train_ratings = y_train

导入tensorflow的包

import tensorflow as tf

with tf.Session() as sess:

    # 设置占位符
    user_id = tf.placeholder(tf.int32,[None,1],name='user_id')
    movie_id = tf.placeholder(tf.int32,[None,1],name='movie_id')
    ratings = tf.placeholder(tf.float32,[None,1],name='ratings')
    
    # 初始化隐变量,维度 (用户数量,隐维度)(电影数量,隐维度)
    user_embedding = tf.Variable(tf.random_normal([UserIDCount, 5],0,1),name='user_embedding')
    movie_embedding = tf.Variable(tf.random_normal([MoviesIDCount, 5],0,1),name='movie_embedding')
    
    # 这里用到了tensorflow的方法,这里传入两个参数
    # 在当前的代码中,第一个表示 (用户数量,隐维度)的矩阵,第二个为user_id
    # 根据传入的user_id,例如传入的user_id为100,99,123
    # 则,可以从第一个输入矩阵中,选择出index对应为100,99,123的向量
    # 100:[0,0,0,0,0]
    # 99:[0,0,0,0,0]
    # 123:[0,0,0,0,0]
    latent_users = tf.nn.embedding_lookup(user_embedding, user_id)
    # 同 latent_users
    latent_movies = tf.nn.embedding_lookup(movie_embedding, movie_id)
    
    # 这里就是内积计算
    pred_ratings = tf.reduce_sum(tf.multiply(latent_users, latent_movies), 1)

    loss = tf.sqrt(tf.reduce_mean(tf.square(ratings - pred_ratings)))
    
    train_op = tf.train.AdamOptimizer(0.1).minimize(loss)

    sess.run(tf.global_variables_initializer())

    for i in range(10):
        _,loss_val,latentusers,latentmovies,pred = sess.run(
                                [train_op,loss,user_embedding,movie_embedding,pred_ratings],
                            feed_dict={
                                user_id: train_users.reshape(-1,1),
                                movie_id: train_movies.reshape(-1,1),
                                ratings: train_ratings.reshape(-1,1)}
                            )

        print(pred)
        print(pred.shape)
已邀请:

要回复问题请先登录注册

返回顶部