由于之前没有看过NFM,这里先把.md文件进行了阅读、理解并将其复制到了笔记里,然后就是整体的tf的实现及结果的展示
WideNDeep、DeepFm、NFM代码演示中的区别
- 线性部分
- 一阶线性部分相同
- DeepFm多了个二阶特征交叉,内积得到了一个数
- nfm元素积操作,得到的是向量,在进行两两Embedding元素积之后,对交叉特征向量取和, 得到该层的输出向量, 很显然, 输出是一个 𝑘 维的向量。
- deep部分
- widendeep在演示的代码中是对数值型特征和类别型特征都进行了deep
- DeepFm和nfm都是对类别型特征进行了deep
1. 动机
NFM(Neural Factorization Machines)是2017年由新加坡国立大学的何向南教授等人在SIGIR会议上提出的一个模型,传统的FM模型仅局限于线性表达和二阶交互, 无法胜任生活中各种具有复杂结构和规律性的真实数据, 针对FM的这点不足, 作者提出了一种将FM融合进DNN的策略,通过引进了一个特征交叉池化层的结构,使得FM与DNN进行了完美衔接,这样就组合了FM的建模低阶特征交互能力和DNN学习高阶特征交互和非线性的能力,形成了深度学习时代的神经FM模型(NFM)。
那么NFM具体是怎么做的呢? 首先看一下NFM的公式:
y ^ N F M ( x ) = w 0 + ∑ i = 1 n w i x i + f ( x ) \hat{y}_{N F M}(\mathbf{x})=w_{0}+\sum_{i=1}^{n} w_{i} x_{i}+f(\mathbf{x}) y^NFM(x)=w0+i=1∑nwixi+f(x)
我们对比FM, 就会发现变化的是第三项,前两项还是原来的, 因为我们说FM的一个问题,就是只能到二阶交叉, 且是线性模型, 这是他本身的一个局限性, 而如果想突破这个局限性, 就需要从他的公式本身下点功夫, 于是乎,作者在这里改进的思路就是用一个表达能力更强的函数来替代原FM中二阶隐向量内积的部分。
![](http://ryluo.oss-cn-chengdu.aliyuncs.com/图片1.png)
而这个表达能力更强的函数呢, 我们很容易就可以想到神经网络来充当,因为神经网络理论上可以拟合任何复杂能力的函数, 所以作者真的就把这个 f ( x ) f(x) f(x)换成了一个神经网络,当然不是一个简单的DNN, 而是依然底层考虑了交叉,然后高层使用的DNN网络, 这个也就是我们最终的NFM网络了:
![](http://ryluo.oss-cn-chengdu.aliyuncs.com/图片2.png)
这个结构,如果前面看过了PNN的伙伴会发现,这个结构和PNN非常像,只不过那里是一个product_layer, 而这里换成了Bi-Interaction Pooling了, 这个也是NFM的核心结构了。这里注意, 这个结构中,忽略了一阶部分,只可视化出来了 f ( x ) f(x) f(x), 我们还是下面从底层一点点的对这个网络进行剖析。
2. 模型结构与原理
2.1 Input 和Embedding层
输入层的特征, 文章指定了稀疏离散特征居多, 这种特征我们也知道一般是先one-hot, 然后会通过embedding,处理成稠密低维的。 所以这两层还是和之前一样,假设 v i ∈ R k \mathbf{v}_{\mathbf{i}} \in \mathbb{R}^{k} vi∈Rk为第 i i i个特征的embedding向量, 那么 V x = { x 1 v 1 , … , x n v n } \mathcal{V}_{x}=\left\{x_{1} \mathbf{v}_{1}, \ldots, x_{n} \mathbf{v}_{n}\right\} Vx={ x1v1,…,xnvn}表示的下一层的输入特征。这里带上了 x i x_i xi是因为很多 x i x_i xi转成了One-hot之后,出现很多为0的, 这里的 { x i v i } \{x_iv_i\} { xivi}是 x i x_i xi不等于0的那些特征向量。
2.2 Bi-Interaction Pooling layer
在Embedding层和神经网络之间加入了特征交叉池化层是本网络的核心创新了,正是因为这个结构,实现了FM与DNN的无缝连接, 组成了一个大的网络,且能够正常的反向传播。假设 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=1∑nj=i+1∑nxivi⊙xjvj
⊙ \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}