实现了一个基于矩阵分解的推荐系统,用于预测用户对电影的评分。具体来说,该程序通过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 dfdf = 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_testdf_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),以评估模型的性能。
- 结果展示:打印预测评分与实际评分的对比,方便分析模型的准确性。