简介
NFM全称为:Neural Factorization Machines for Sparse Predictive Analytics
论文地址为:https://arxiv.org/pdf/1708.05027.pdf
特点及简介
(1)是第一个在神经网络模型中引入双向交互池化操作的,并且由此提出了一种新的神经网络方法。
(2)本方法加深神经网络框架下的FM使之能够面对高阶和非线性特征。
(3)该方法能够在稀疏数据集上使用神经网络进行预测,并且效果较好。
该模型是通过新的将FM融入到DNN的方法,通过引入一个新的特征交叉池化层的结构,使得FM能够与DNN完美的进行衔接,这就组合了FM的低阶特征交互能力和DNN学习高阶特征交互和非线性能力。
首先在这里我们有必要了解在FM中的两个公式的推导过程:
接下来将正式介绍NFM
NFM
算法流程图如下:
整个算法框架可以分为输入,嵌入层,池化层,隐藏层和最终预测层。与其他算法算法不同的是在获取完新的嵌入表示后并没有将新的新的表示直接放进到DNN中,而是将这个表示进行了池化。
接下来将逐一介绍:
输入:输入的是一个k维的稀疏特征向量,表示的是某一项目的特征。
Embedding layer: 这一层是将稀疏矩阵中的非0特征提取,做嵌入的。但是在这一层中会有这样的一个问题在输入的稀疏矩阵中每一个向量中的非0元素个数不同,所以我需要通过直接设置一个固定的n的值。
B-Interaction Layer: 池化层的作用是将嵌入后的特征进一步进行交互,得到更加丰富的表示。
通过以上三个步骤最终得到了新的特征表示,我们再将上面的表示输入到DNN中。
下面是我自己对于这个算法流程的理解:
有错误的地方还希望大家能够帮忙指正。
NFM的完整公式:
代码实现
def NFM(linear_feature_columns, dnn_feature_columns):
"""
搭建NFM模型,上面已经把所有组块都写好了,这里拼起来就好
:param linear_feature_columns: A list. 里面的每个元素是namedtuple(元组的一种扩展类型,同时支持序号和属性名访问组件)类型,表示的是linear数据的特征封装版
:param dnn_feature_columns: A list. 里面的每个元素是namedtuple(元组的一种扩展类型,同时支持序号和属性名访问组件)类型,表示的是DNN数据的特征封装版
"""
# 构建输入层,即所有特征对应的Input()层, 这里使用字典的形式返回, 方便后续构建模型
# 构建模型的输入层,模型的输入层不能是字典的形式,应该将字典的形式转换成列表的形式
# 注意:这里实际的输入与Input()层的对应,是通过模型输入时候的字典数据的key与对应name的Input层
dense_input_dict, sparse_input_dict = build_input_layers(linear_feature_columns+dnn_feature_columns)
input_layers = list(dense_input_dict.values()) + list(sparse_input_dict.values())
# 线性部分的计算 w1x1 + w2x2 + ..wnxn + b部分,dense特征和sparse两部分的计算结果组成,具体看上面细节
linear_logits = get_linear_logits(dense_input_dict, sparse_input_dict, linear_feature_columns)
# DNN部分的计算
# 首先,在这里构建DNN部分的embedding层,之所以写在这里,是为了灵活的迁移到其他网络上,这里用字典的形式返回
# embedding层用于构建FM交叉部分以及DNN的输入部分
embedding_layers = build_embedding_layers(dnn_feature_columns, sparse_input_dict, is_linear=False)
# 过特征交叉池化层
pooling_output = get_bi_interaction_pooling_output(sparse_input_dict, dnn_feature_columns, embedding_layers)
# 加个BatchNormalization
pooling_output = BatchNormalization()(pooling_output)
# dnn部分的计算
dnn_logits = get_dnn_logits(pooling_output)
# 线性部分和dnn部分的结果相加,最后再过个sigmoid
output_logits = Add()([linear_logits, dnn_logits])
output_layers = Activation("sigmoid")(output_logits)
model = Model(inputs=input_layers, outputs=output_layers)
return model
代码框架
NFM和FM的区别在公式表达上并没有太大区别但是,NFM的池化过程中不仅仅奖特征向量进行了嵌入同时还将最开始输入的特征向量再次引入到了池化过程中,这不仅仅极大的丰富了特征的表示,还能使得池化过程中能够更好的使特征进行交叉表示。