实现了一个基于矩阵分解的推荐系统,用于预测用户对电影的评分。具体来说,该程序通过TensorFlow构建和训练一个模型,来学习用户和电影之间的隐含特征,并根据这些特征预测评分。以下是代码的主要功能和步骤的详细描述:
1. 数据加载与预处理
- 数据加载:通过
get_data_pd
函数从指定路径加载电影评分数据集(CSV文件),并将其存储在Pandas DataFrame中。 - 用户和电影数量统计:统计数据集中唯一用户和电影的数量,为后续模型的构建提供基础。
def get_data_pd(datapath):
with open(datapath, 'r') as f:
df = pd.read_csv(f)
return df
df = get_data_pd(datapath)
u_num = df.userId.nunique() # 用户数量
i_num = df.movieId.nunique() # 电影数量
print("用户有{0}位, 共有电影{1}部".format(u_num, i_num))
df.head()
2. 数据集划分
- 训练集与测试集划分:通过打乱数据集,使数据随机化,接着将90%的数据用于训练,10%用于测试,以评估模型的性能。
def get_data(datapath):
df = get_data_pd(datapath)
rows = len(df)
# 打乱索引
df = df.iloc[np.random.permutation(rows)].reset_index(drop=True)
# 90%的训练集与10%的测试集
split_index = int(rows * 0.9)
df_train = df[0:split_index]
df_test = df[split_index:].reset_index(drop=True)
return df_train, df_test
df_train, df_test = get_data(datapath)
3. 模型构建
- 模型定义:使用TensorFlow定义矩阵分解模型。模型包括用户和电影的嵌入层,以及全局偏置、用户偏置和电影偏置。通过用户和电影的隐含特征向量计算预测评分。
- 损失函数:定义L2损失函数用于训练,包括预测评分与实际评分之间的差异,以及正则化项以防止过拟合。
def model(user_batch, item_batch, user_num, item_num, dim=5, device="/cpu:0"):
with tf.device(device):
with tf.variable_scope('lsi', reuse=tf.AUTO_REUSE):
bias_global = tf.get_variable("bias_global", shape=[])
w_bias_user = tf.get_variable(name="embd_bias_user", shape=[user_num])
w_bias_item = tf.get_variable(name="embd_bias_item", shape=[item_num])
bias_user = tf.nn.embedding_lookup(w_bias_user, user_batch, name="bias_user")
bias_item = tf.nn.embedding_lookup(w_bias_item, item_batch, name="bias_item")
w_user = tf.get_variable("embd_user", shape=[user_num, dim],
initializer=tf.truncated_normal_initializer(stddev=0.02))
w_item = tf.get_variable("embd_item", shape=[item_num, dim],
initializer=tf.truncated_normal_initializer(stddev=0.02))
embd_user = tf.nn.embedding_lookup(w_user, user_batch, name="embedding_user")
embd_item = tf.nn.embedding_lookup(w_item, item_batch, name="embedding_item")
with tf.device(device):
# 估分 = 矩阵相乘 + 全局偏差 + 用户偏差 + 电影偏差
infer = tf.reduce_sum(tf.multiply(embd_user, embd_item), 1)
infer = tf.add(infer, bias_global)
infer = tf.add(infer, bias_user)
infer = tf.add(infer, bias_item, name="svd_inference")
regularizer = tf.add(tf.nn.l2_loss(embd_user), tf.nn.l2_loss(embd_item),
name="svd_regularizer")
return infer, regularizer
4. 模型训练
- 训练过程:在训练过程中,使用样本数据进行多次迭代训练。每次迭代会获取一批用户和电影的评分数据,计算模型的预测评分,并更新模型参数以最小化损失。
- 输出训练信息:每经过一定的样本批次,打印当前的训练错误和经过的时间,以便监控训练进度。
with tf.Session() as sess:
sess.run(init_op)
print("%s\t%s\t%s\t%s" % ("Epoch", "Train Error", "Val Error", "Elapsed Time"))
errors = deque(maxlen=samples_per_batch)
start = time.time()
for i in range(max_epochs * samples_per_batch):
users, items, rates = (iter_train.userId.values, iter_train.movieId.values, iter_train.rating.values)
_, pred_batch = sess.run([train_op, infer], feed_dict={user_batch: users,
item_batch: items,
rate_batch: rates})
pred_batch = clip(pred_batch)
if i % samples_per_batch == 0:
train_err = np.sqrt(np.mean(errors))
end = time.time()
print("%02d\t\t\t\t%.3f secs" % (i // samples_per_batch, end - start))
start = end
5. 模型保存与恢复
- 模型保存:训练完成后,模型的权重和结构会被保存,以便后续可以加载和复用。
- 模型恢复:在后续阶段,可以通过加载保存的模型来进行评分预测,而不需重新训练模型。
6. 评分预测与评估
- 测试集评估:从测试集中取样本进行评分预测,并与实际评分进行比较,计算均方根误差(RMSE),以评估模型的性能。
- 结果展示:打印预测评分与实际评分的对比,方便分析模型的准确性。