深度推荐模型之NFM模型

NFM

背景

今天学习深度推荐模型中的NFM(Neural Factorization Machines)模型,该模型是由2017年在SIGIR会议上提出的。CTR预估中,为了解决稀疏特征的问题,学者们提出了FM模型来建模特征之间的交互关系。但是FM模型只能表达特征之间两两组合之间的关系,无法建模两个特征之间深层次的关系或者说多个特征之间的交互关系,所以通过Deep Network来建模更高阶的特征之间的关系,提出了一种将FM融合进DNN的策略,通过引进了一个特征交叉池化层的结构,使得FM与DNN进行了完美衔接,这样就组合了FM的建模低阶特征交互能力和DNN学习高阶特征交互和非线性的能力,形成了深度学习时代的神经FM模型(NFM)。

NFM模型

由上面我们知道NFM模型与DeepFM模型类似,都是与DNN相结合得到的,只是DeepFM模型是并行结构,NFM是串行结构,下面看一下NFM模型的目标函数:

深度推荐模型之NFM模型_第1张图片

之前我们学的FM模型的公式如下:

深度推荐模型之NFM模型_第2张图片

由上面两个公式可以看出,二者在前半部分是一样的,后面在NFM中用一个函数来代替FM中二阶向量交叉,通常将这个函数用一个底层考虑交叉,高层使用的一个DNN,最后得到NFM模型。模型结构如下:

深度推荐模型之NFM模型_第3张图片

由图可以看出,NFM模型即是在Embedding层和Hidden之间加了一个B-Interation(特征交叉池化层)。假设 V x \mathcal{V}_{x} Vx是所有特征embedding的集合, 那么在特征交叉池化层的操作:

f B I ( V x ) = ∑ i = 1 n ∑ j = i + 1 n x i v i ⊙ x j v j f_{B I}\left(\mathcal{V}{x}\right)=\sum_{i=1}^{n} \sum_{j=i+1}^{n} x_{i} \mathbf{v}{i} \odot x{j} \mathbf{v}_{j} fBI(Vx)=i=1nj=i+1nxivixjvj

⊙ \odot 表示两个向量的元素积操作,即两个向量对应维度相乘得到的元素积向量(可不是点乘呀),其中第 k k k维的操作: ( v i ⊙ v j ) k = v i k v j k \left(v_{i} \odot v_{j}\right){k}=\boldsymbol{v}{i k} \boldsymbol{v}_{j k} (vivj)k=vikvjk

NFM实现

NFM模型的实现,把输入分成linear input和dnn input两种情况,所以模型会分为linear 和 dnn两部分,下面分别介绍这两部分:

linear:这部分是有关于线性计算,也就是FM的前半部分 w 1 x 1 + w 2 x 2 . . . w n x n + b w_1x_1+w_2x_2...w_nx_n+b w1x1+w2x2...wnxn+b的计算

dnn:这部分是后面交叉特征的那部分计算,FM的最后那部分公式f(x)。 这一块主要是针对离散的特征,首先过embedding, 然后过特征交叉池化层

模型的最后输出结果,就是把这两个部分的输出结果加和(当然也可以加权),再过一个sigmoid得到

代码参考

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

参考

DataWhale 组队学习

NFM模型理论与实践

推荐系统遇上深度学习(七)–NFM模型理论和实践

论文

你可能感兴趣的:(深度推荐模型)