论文阅读:(NFM)Neural Factorization Machines for Sparse Predictive Analytics

摘要

在很多预测任务中要对特征进行one-hot编码,使得最终的特征向量高度稀疏,因此需要进行特征交互。
FM模型只能表达特征之间两两组合之间的关系,无法建模两个特征之间深层次的关系或者说多个特征之间的交互关系。
因此学者们通过Deep Network来建模更高阶的特征之间的关系。然而Wide&deep和deepcross因为其深度结构而难以训练。
因此 FM和深度网络DNN的结合也就成为了CTR预估问题中主流的方法。有关FM和DNN的结合有两种主流的方法,并行结构和串行结构。两种结构的理解以及实现如下表所示:
在这里插入图片描述
从理论上讲,NFM比FM更有表现力,因为FM可以被看作是没有隐藏层的NFM的一个特例。两个回归任务的实证结果表明,只有一个隐含层时,NFM显著优于FM,改善幅度为7.3%。

关键词:Factorization Machines, Neural Networks, Deep Learning, Sparse
Data, Regression, Recommendation
论文开源代码https://github.com/hexiangnan/neural_factorization_machine

一、Introduction

最近几年,Embedding-based方法开始成为主流,通过把高维稀疏的输入embed到低维度的稠密的隐向量空间中,模型可以学习到训练集中没有出现过的特征组合。

Embedding-based大致可以分为两类:

  1. factorization machine-based linear models
  2. neural network-based non-linear models

而这两者都有其缺陷:

  1. FM还是属于线性模型,它的表达能力受限,而且它只能对二阶组合特征进行建模。
  2. 虽然多层神经网络已经被证明可以有效的学习高阶特征组合。但是DNN的缺点也很明显:网络优化或者说网络学习比较困难。

关于DNN,多说两句:

业内大部分DNN的架构都是:把特征的嵌入向量简单拼接起来,输入到神经网络中学习。这样简单的拼接嵌入向量,因为缺失了很多组合特征的信息(carry too little information about feature interactions in low level)效果并不好,那么只能寄希望于后面的MLP可以弥补不足。

但是为了提高NN的学习能力就需要增加网络层数,复杂的网络结构会收到诸如梯度消失/爆炸、过拟合、degradation(简单说就是:随着网络层数的增加,训练准确率不升反降,非常反常)等问题的困扰,网络的学习或者优化会非常困难。

如下图所示,如果使用FM预训练初始化嵌入层,Wide&Deep和DeepCross性能都提升了,甚至超过了FM。Wide&Deep的degradation问题也解决了,因为训练集的性能得到了提升。但是两者依旧都有过拟合的问题。实验说明DNN的训练学习真的存在困难。
在这里插入图片描述
FM摒弃了直接把嵌入向量拼接输入到神经网络的做法,在嵌入层之后增加了Bi-Interaction操作来对二阶组合特征进行建模。这使得low level的输入表达的信息更加的丰富,极大的提高了后面隐藏层学习高阶非线性组合特征的能力。

二、NFM基本原理

1、系统框架

先来看一下NFM的表达式:
在这里插入图片描述
其中第一项和第二项是与FM相似的线性回归部分,该部分模拟数据的偏差和特征的权重。第三项f (x)是NFM建模特征交互的核心组件,它是一个多层前馈神经网络,如下图所示。
在这里插入图片描述
接下来,我们将对f (x)的设计逐层进行阐述。

1、Embedding Layer

和其他的DNN模型处理稀疏输入一样,Embedding将输入转换到低维度的稠密的嵌入空间中进行处理。作者稍微不同的处理是,使用原始的特征值乘以Embedding vector,使得模型也可以处理real valued feature。

2、Bi-Interaction Layer

其实它就是计算FM中的二次项的过程,因此得到的向量维度就是我们的Embedding的维度

Bi是Bi-linear的缩写,这一层其实是一个pooling层操作,它把将一组嵌入向量转换为一个向量,形式化如下:
在这里插入图片描述
BI的输入是整个的嵌入向量,xi xj是特征取值,vi vj是特征对应的嵌入向量。中间的操作表示对应位置相乘。
这个圆圈符号表示两个向量的元素乘积,例如这个公式
在这里插入图片描述
显然,双向交互池的输出是一个k维向量,它对嵌入空间中特征之间的二阶交互进行编码。

所以原始的嵌入向量任意两个都进行组合,对应位置相乘结果得到一个新的向量;然后把这些新向量相加,就得到了Bi-Interaction的输出。这个输出只有一个向量。

需要说明的是:Bi-Interaction并没有引入额外的参数,而且它的计算复杂度也是线性的,和max/min pooling以及原来的拼接操作复杂度都是相同的。因为上式可以参考FM的优化方法,化简如下(想想一个矩阵):

在这里插入图片描述
它的计算复杂度是O(NK)。其中k是嵌入向量的维度,N是输入x中非零特征的个数。这个公式大家要搞懂是怎么回事哦,代码里面就是按照这个来写的。

总结,Bi-Interaction Layer实现了对二阶组合特征的建模,但是又没有引入额外的开销,包括参数数量和计算复杂度。

3、Hidden Layer

这个跟其他的模型基本一样,堆积隐藏层以期待来学习高阶组合特征。模型结构可以参考Wide&Deep论文的结论,一般选用constant的效果要好一些。
每层的输出为:
在这里插入图片描述

4、Prediction Layer

将最后一个隐藏层的输出变量 z L z_L zL变为一个分数
在这里插入图片描述
其中,向量h表示预测层神经元的权值。综上所述,公式NFM的预测模型为:
在这里插入图片描述
这里的参数为
在这里插入图片描述$θ=({w0,相比于FM其实多出的参数就是隐藏层的参数,所以说FM也可以看做是一个神经网络架构,就是去掉隐藏层的NFM。我们把去掉隐藏层的NFM称为NFM-0,形式化如下:
在这里插入图片描述
如果h为全1向量,那么此时NFM就是FM。
这是第一次把FM看做是神经网络来处理,这样的观点对于优化FM提供了一些新的思路。同时,像NN中常用的技巧也可以应用到这里面来,比如Dropout,实验发现在正则化FM的时候,使用Dropout比传统的L2正则化还要有效。

2、 NFM vs Wide&Deep、DeepCross

如果要求简明扼要说明NFM到底做了什么,就是这一部分内容:

最重要的区别就在于Bi-Interaction Layer。Wide&Deep和DeepCross都是用拼接操作(concatenation)替换了Bi-Interaction。
Concatenation操作的最大缺点就是它并没有考虑任何的特征组合信息,所以就全部依赖后面的MLP去学习特征组合,但是很不幸,MLP的学习优化非常困难。
使用Bi-Interaction考虑到了二阶特征组合,使得输入的表示包含更多的信息,减轻了后面MLP部分的学习压力,所以可以用更简单的模型,取得更好的成绩。

复杂度分析:
上面提到过,NFM相比于FM,复杂度增加在MLP部分。所以NFM的复杂度和Wide&Deep、DeepCross是相同的

三、训练

1、目标函数

NFM可以用于分类、回归、ranking问题,对应着不同的目标函数。

  1. 回归。square loss
  2. 分类。Hinge Loss 或 log loss
  3. ranking。Contrastive max-margin loss

论文中以回归问题为例,使用square loss,形式化如下
在这里插入图片描述
这里并没有正则化项,因为作者发现在NFM中使用Dropout能够得到更好的效果。

2、参数估计

使用mini-batch Adagrad来进行参数估计,Adagrad是SGD的变体,特点是每个参数都有自己的学习速率。然后让参数沿着目标函数负梯度的方向进行更新,是下降最快的方向,形式化如下:
在这里插入图片描述
这里唯一需要指出的是Bi-Interaction在求梯度时是怎么做的:
在这里插入图片描述
所以,NFM的训练依旧可以是端到端的训练,只需要把Bi-Interaction插入到网络中即可。

3、Dropout

Dropout在训练过程中随机丢掉一些神经元,那么再一次参数更新中也就只会更新部分参数。可以理解成是相当于很多个小的NN取平均值。增加了模型的抗过拟合能力。在NFM中,Bi-Interaction的输出后就增加了Dropout操作,随机的丢弃了一部分的输出。随后的MLP同样应用了Dropout。
需要注意的是,在测试阶段,Dropout是不使用的,所有的神经元都会激活。

4、Batch Normalization

DNN的训练面临很多问题。其中一个就是协方差偏移(covariance shift),意思就是:由于参数的更新,隐藏层的输入分布不断的在变化,那么模型参数就需要去学习这些变化,这减慢了模型的收敛速度。
Batch Normalization就是为了解决这个问题的,形式化如下:
在这里插入图片描述
对于隐藏层的输入,BN在mini-batch数据上,把输入转换成均值为0,方差为1的高斯分布。其中的γ,β是两个超参数,为了扩大模型的表达能力,如果模型发现不应用BN操作更好,那么就可以通过学习这两个参数来消除BN的影响。NFM中Bi-Interaction Layer的输出就是MLP的第一个输出,包括后面所有隐藏层的输入都需要进行Batch Normalization。
注意,在测试预测的时候,BN操作同样有效,这时的均值和方差在整个测试集上来进行计算。

四、实验部分

1、数据集

使用了两份公开的数据集:

Frappe。http://baltrunas.info/research-menu/frappe
MovieLens。https://grouplens.org/datasets/movielens/latest/
随机的取70%数据作训练集,20%数据作验证集,10%数据作测试集。

2、实验结果

FM相当于是去掉DNN的NFM,论文中给出的数据是只用了一个隐藏层的NFM,相比于FM性能提升了7.3%;NFM只用了一个隐藏层,相比于3个隐藏层的Wide&Deep,和10个隐藏层的DeepCross,NFM用更简单的模型,更少的参数得到了性能的提升。

论文中对比了FM、Wide&Deep模型,效果不用说肯定是NFM最好,图片有点多就不放了。

此处,只给出一些重要的结论:

  1. Dropout在NFM中可以有效的抑制过拟合
  2. Batch Normalization在NFM中可以加快训练速度
  3. NFM使用一个隐藏层得到了最好的效果
  4. 如果用FM来pre-train嵌入层,NFM会收敛的非常快,但是NFM最终的效果并没有变好。说明NFM对参数有很好的鲁棒性。
  5. 模型性能基本上随着Factor的增加而提升。Factor指Embedding向量的维度。

参考:
https://www.jianshu.com/p/4e65723ee632
https://blog.csdn.net/u010352603/article/details/82670335

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于PyTorch实现的NFM推荐算法代码,供参考: ``` import torch import torch.nn as nn import torch.nn.functional as F class NFM(nn.Module): def __init__(self, feature_dim, embedding_dim, hidden_dim, output_dim, dropout_prob): super().__init__() self.feature_dim = feature_dim self.embedding_dim = embedding_dim self.hidden_dim = hidden_dim self.output_dim = output_dim self.dropout_prob = dropout_prob self.embedding = nn.Embedding(feature_dim, embedding_dim) self.linear1 = nn.Linear(embedding_dim, hidden_dim) self.linear2 = nn.Linear(hidden_dim, output_dim) self.linear3 = nn.Linear(embedding_dim, output_dim) self.dropout = nn.Dropout(dropout_prob) def forward(self, x): # Embedding layer x_emb = self.embedding(x) # Bi-Interaction layer sum_square = torch.sum(x_emb, dim=1) ** 2 square_sum = torch.sum(x_emb ** 2, dim=1) bi_interaction = 0.5 * (sum_square - square_sum) # MLP layer mlp_output = F.relu(self.linear1(self.dropout(bi_interaction))) mlp_output = self.linear2(self.dropout(mlp_output)) # Output layer output = self.linear3(x_emb.mean(dim=1)) + mlp_output return output ``` 其中,`feature_dim`为特征维度,`embedding_dim`为嵌入维度,`hidden_dim`为隐层维度,`output_dim`为输出维度,`dropout_prob`为dropout概率。 在模型的前向传播过程中,首先通过`nn.Embedding`层将输入的离散特征转化为嵌入向量,然后通过Bi-Interaction Layer计算二阶交叉特征,再通过MLP Layer进行非线性变换,最后将MLP输出和原始嵌入向量的平均值相加得到最终输出。 使用时,可以像以下代码一样初始化并训练模型: ``` # 初始化模型 model = NFM(feature_dim, embedding_dim, hidden_dim, output_dim, dropout_prob) # 定义损失函数和优化器 criterion = nn.BCEWithLogitsLoss() optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) # 训练模型 for epoch in range(num_epochs): for inputs, targets in dataloader: optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, targets) loss.backward() optimizer.step() ``` 其中,`feature_dim`、`embedding_dim`、`hidden_dim`、`output_dim`、`dropout_prob`、`learning_rate`、`num_epochs`等参数需要根据具体情况进行设置,`dataloader`是一个PyTorch的`DataLoader`对象,用于加载训练数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值