19|NeuralCF:如何用深度学习改造协同过滤?
NeuralCF 模型的结构
把矩阵分解神经网络化之后,把它跟 Embedding+MLP 以及 Wide&Deep 模型做对比,我们可以一眼看出网络中的薄弱环节:矩阵分解在 Embedding 层之上的操作好像过于简单了,就是直接利用内积得出最终结果。这会导致特征之间还没有充分交叉就直接输出结果,模型会有欠拟合的风险。针对这一弱点,NeuralCF 对矩阵分解进行了改进,它的结构图是图 3 这样的
NeuralCF 模型的扩展,双塔模型
双塔模型的结构和优势。双塔模型将模型分为用户侧模型和物品侧模型两部分,通过互操作层将两部分联合起来,产生最终的预测得分。用户侧模型和物品侧模型可以分别包含不同的特征,从而让模型能够学到更全面的信息。双塔模型的优势在于能够利用更多特征提高预测精度,同时也更加灵活,能够根据具体任务和数据情况进行灵活调整和扩展。
NeuralCF 的 TensorFlow 实现
# neural cf model arch two. only embedding in each tower, then MLP as the interaction layers
def neural_cf_model_1(feature_inputs, item_feature_columns, user_feature_columns, hidden_units):
# 物品侧特征层
item_tower = tf.keras.layers.DenseFeatures(item_feature_columns)(feature_inputs)
# 用户侧特征层
user_tower = tf.keras.layers.DenseFeatures(user_feature_columns)(feature_inputs)
# 连接层及后续多层神经网络
interact_layer = tf.keras.layers.concatenate([item_tower, user_tower])
for num_nodes in hidden_units:
interact_layer = tf.keras.layers.Dense(num_nodes, activation='relu')(interact_layer)
# sigmoid单神经元输出层
output_layer = tf.keras.layers.Dense(1, activation='sigmoid')(interact_layer)
# 定义keras模型
neural_cf_model = tf.keras.Model(feature_inputs, output_layer)
return neural_cf_model
你可以看到代码中定义的生成 NeuralCF 模型的函数,它接收了四个输入变量。其中 feature_inputs 代表着所有的模型输入, item_feature_columns 和 user_feature_columns 分别包含了物品侧和用户侧的特征。在训练时,如果我们只在 item_feature_columns 中放入 movie_id ,在 user_feature_columns 放入 user_id, 就是 NeuralCF 的经典实现了。通过 DenseFeatures 层创建好用户侧和物品侧输入层之后,我们会再利用 concatenate 层将二者连接起来,然后输入多层神经网络进行训练。如果想要定义多层神经网络的层数和神经元数量,我们可以通过设置 hidden_units 数组来实现。除了经典的 NeuralCF 实现,我还基于双塔模型的原理实现了一个 NeuralCF 的双塔版本。你可以参考下面的模型定义。与上面的经典 NerualCF 实现不同,我把多层神经网络操作放到了物品塔和用户塔内部,让塔内的特征进行充分交叉,最后使用内积层作为物品塔和用户塔的交互层。具体的步骤你可以参考下面代码中的注释,实现过程很好理解,我就不再赘述了。
# neural cf model arch one. embedding+MLP in each tower, then dot product layer as the output
def neural_cf_model_2(feature_inputs, item_feature_columns, user_feature_columns, hidden_units):
# 物品侧输入特征层
item_tower = tf.keras.layers.DenseFeatures(item_feature_columns)(feature_inputs)
# 物品塔结构
for num_nodes in hidden_units:
item_tower = tf.keras.layers.Dense(num_nodes, activation='relu')(item_tower)
# 用户侧输入特征层
user_tower = tf.keras.layers.DenseFeatures(user_feature_columns)(feature_inputs)
# 用户塔结构
for num_nodes in hidden_units:
user_tower = tf.keras.layers.Dense(num_nodes, activation='relu')(user_tower)
# 使用内积操作交互物品塔和用户塔,产生最后输出
output = tf.keras.layers.Dot(axes=1)([item_tower, user_tower])
# 定义keras模型
neural_cf_model = tf.keras.Model(feature_inputs, output)
return neural_cf_model
小结
这节课,我们首先学习了经典推荐算法协同过滤的深度学习进化版本 NerualCF。相比于矩阵分解算法,NeuralCF 用一个多层的神经网络,替代了矩阵分解算法中简单的点积操作,让用户和物品隐向量之间进行充分的交叉。这种通过改进物品隐向量和用户隐向量互操作层的方法,大大增加了模型的拟合能力。利用 NerualCF 的思想,我们进一步学习了双塔模型。它通过丰富物品侧和用户侧的特征,让模型能够融入除了用户 ID 和物品 ID 外更丰富的信息。除此之外,双塔模型最大的优势在于模型服务的便捷性,由于最终的互操作层是简单的内积操作或浅层神经网络。因此,我们可以把物品塔的输出当作物品 Embedding,用户塔的输出当作用户 Embedding 存入特征数据库,在线上只要实现简单的互操作过程就可以了。最后,我们继续使用 TensorFlow 实现了 NerualCF 和双塔模型,相信你能进一步感受到利用 TensorFlow 构建深度学习模型的便捷性,以及它和传统推荐模型相比,在模型结构灵活性上的巨大优势。为了帮助你复习,我把刚才说的这些重点内容总结在了一张图里,你可以看看。
此文章为3月Day25学习笔记,内容来源于极客时间《深度学习推荐系统实战》,强烈推荐该课程!