[CTR预估] xDeepFM模型

xDeepFM 模型看作者邮箱应该中科大、北邮、微软合作发表的,发表在kdd2018
看这个模型的原因是因为最近在写Deep Cross Network的时候感觉总是怪怪的,因为DCN对同一个特征的embedding内部都做了特征的交叉,这个和我们正常直观的特征交叉会有明显的出入,虽然DCN模型在实践中确实会好于正常的wide&deep,说明显式的特征交叉是有意义的,但是有没有办法不对这些自身内部的bit进行交叉,来减少不必要的交叉次数,也可以一定程度上减少自身的冗余对模型效果的影响。搜索来一些发现了这篇文章,所以读了一下。
下载地址《xDeepFM: Combining Explicit and Implicit Feature Interactions for Recommender Systems》
作者开源了论文代码: https://github.com/Leavingseason/xDeepFM

1.Overview

文章提出一个新的模型eXtreme Deep Factorization Machine 。算法提出的目的是为了解决特征交互的问题。DNN有能力学习出任意的函数,但是学习到的特征交互都是隐式的,并且都是基于bit-wise level。所谓的隐式指的是我们并不知道模型所做的特征交叉是在做哪些特征的交叉,所谓的bit-wise level的特征交互,这里作者提出了两个概念,一个是bit-wise level的特征交叉,一个是vector-wise level。意思其实就是字面意思,bit-wise level的特征交叉就是指神经网络中节点之间的交互,如DCN中的crossNet就是bit-wise的交互。vector-wise的特征交互指的是将每个特征embedding后的整个embedding vector作为一个域,然后对域和域之间进行特征交叉,如FMDeepFMPNN中的特征交叉。
那么怎么在神经网络中做特征交互呢?
1.隐式的高阶特征交互其实可以使用DNN模块,而且基本在现在一些经典的基于深度学习的ctr预估模型中都会使用到该部分,如PNN,Wide&Deep,FNN,DeepFM,DCN等。但是DNN虽然可以拟合出任意的函数,却没有理论结论,而且无法知道特征交叉到了什么程度,基于DNN的特征交叉完全是在bit-wise level下进行,和传统的FM基于vector-wise的交叉完全不同。
2.显式的特征交交叉。文章基于DCN算法思想提出了一种新的模型结构CIN用来代替DCN模型中的cross net。使得模型可以显式的学习特征在vector-wise的交叉。并结合隐式的特征交互,提出了一个新模型 xDeepFM而且作者认为DCN的学习交叉能力有限,因为DCN的crossNet每一层的输出其实对最原始输入X_0的一个标量倍数。
如果k为第k层cross net,那么当k=1的时候,有
x1=x0(x0Tw1)+x0=x0(x0Tw1+1)=α1x0\begin{aligned} \mathbf{x}_{1} &=\mathbf{x}_{0}\left(\mathbf{x}_{0}^{T} \mathbf{w}_{1}\right)+\mathbf{x}_{0} \\ &=\mathbf{x}_{0}\left(\mathbf{x}_{0}^{T} \mathbf{w}_{1}+1\right) \\ &=\alpha^{1} \mathbf{x}_{0} \end{aligned}
那么其实标量 α1=x0Tw1+1\alpha^{1}=\mathbf{x}_{0}^{T} \mathbf{w}_{1}+1就是关于x0x_0的一个线性回归。同理,当k=i+1的时候,也能得到
xi+1=x0xiTwi+1+xi=x0((αix0)Twi+1)+αix0=αi+1x0\begin{aligned} \mathbf{x}_{i+1} &=\mathbf{x}_{0} \mathbf{x}_{i}^{T} \mathbf{w}_{i+1}+\mathbf{x}_{i} \\ &=\mathbf{x}_{0}\left(\left(\alpha^{i} \mathbf{x}_{0}\right)^{T} \mathbf{w}_{i+1}\right)+\alpha^{i} \mathbf{x}_{0} \\ &=\alpha^{i+1} \mathbf{x}_{0} \end{aligned}
其中 αi+1=αi(x0Twi+1+1)\alpha^{i+1}=\alpha^{i}\left(\mathbf{x}_{0}^{T} \mathbf{w}_{i+1}+1\right) 也是一个标量。
所以xkx_kx0x_0的一个标量倍数。
但是标量倍数并不意味着xkx_kx0x_0的线性函数,只是模型中特征交叉会相对比较有限。

2.Model Architecture

[CTR预估] xDeepFM模型
首先,模型的结构如图所示。底部是embedding layer。这个现在主流模型都一样,没啥好说的。然后往上走是对embedding layer的特征处理。主要分三块。

一、Linear模块

[CTR预估] xDeepFM模型
就是直接把原始特征提取出one-hot特征直接作为模型的输入。

二、DNN全连接模块

把embedding layer作为输入做MLP。用来学习高阶隐式特征交叉。
[CTR预估] xDeepFM模型

三、算法核心改进的模块(CIN)。

用来学习显式的特征交叉,如图所示。
[CTR预估] xDeepFM模型
下面对CIN模块详细展开描述一下。

3.Compressed Interaction Network(CIN)

CIN模块的目的是做显式的vector-wise特征交互,所以所有的特征交互都是在vector维度进行,所以需要和FM一样将每个特征embedding到相同的维度,假设我们有m个特征,将每个特征映射到D维的embedding向量,那么经过lookup后,我们可以获取到总长度为m*D的embedding向量层。当然我们也可以把这些向量按矩阵的形式写出来,转化成矩阵
X0Rm×D\mathbf{X}^{0} \in \mathbb{R}^{m \times D} 其中每一行表示一个特征,长度为D。
然后CIN层每一层的输出,如第k层的输出也是一个矩阵XkRHk×D\mathrm{X}^{k} \in \mathbb{R}^{H_{k} \times D}。其中HkH_k是第k测光输出的特征向量的个数,也就是XkX_k中输出的一行。另外定义H0=mH_0 = m
那么CIN中XkX_k的每一行的计算公式如下
Xh,k=i=1Hk1j=1mWijk,h(Xi,k1Xj,0)\mathrm{X}_{h, *}^{k}=\sum_{i=1}^{H_{k-1}} \sum_{j=1}^{m} \mathrm{W}_{i j}^{k, h}\left(\mathrm{X}_{i, *}^{k-1} \circ \mathrm{X}_{j, *}^{0}\right)
这里的Xh,k\mathrm{X}_{h, *}^{k}代表的是XkX_k的一行, ◦指的是点积。具体如下:
⟨a1,a2,a3⟩◦⟨b1,b2,b3⟩ = ⟨a1b1,a2b2,a3b3⟩.
可以看到,第k层CIN的输出XkX_k每一行都是需要所有的特征进行交互,然后不同行做相同的交叉,只是他们之间学习出的参数不同。
文章还专门画了图来帮助大家理解。
[CTR预估] xDeepFM模型
图a中的Zk+1Z^{k+1}是计算Xk+1X_{k+1}中一行的一个中间结果。
因为HkH_k和m中的每行都需要交互,所以不做求和的话,其实就是类似一个外积操作。然后再对这个外积形成的矩阵进行按权重W求和。看上去就有点像CNN结构,如图b所示。
这就可以理解为一个CIN的块,那么CIN是怎么输出的呢?
首先CIN是可以正常的堆叠的,但是CIN模块的输出并不只单单使用了最后一个CIN块的输出,而是使用了每个CIN块的输出。每个CIN块的输出XkX_k是个HkDH_{k}*D的矩阵,然后作者这里将每行D维的向量压缩到一维,做了一个pooling操,如
pik=j=1DXi,jkp_{i}^{k}=\sum_{j=1}^{D} \mathrm{X}_{i, j}^{k}
那么每一层的CIN块就可以输出一个向量pk=[p1k,p2k,,pHkk]\mathbf{p}^{k}=\left[p_{1}^{k}, p_{2}^{k}, \ldots, p_{H_{k}}^{k}\right],最后把每一个CIN块的输出concate起来作为CIN结构的输出。类似这样:
[CTR预估] xDeepFM模型
最后就是把上面三块的输出合并在一起输出一个预测值y。如
y^=σ(wlinearTa+wdnnTxdnnk+wcinTp++b)\hat{y}=\sigma\left(\mathbf{w}_{\text {linear}}^{T} \mathbf{a}+\mathbf{w}_{d n n}^{T} \mathbf{x}_{d n n}^{k}+\mathbf{w}_{c i n}^{T} \mathbf{p}^{+}+b\right)

以上基本就是xDeepFM的全部思路,文章的思路基本解决了我最开始对神经网络中特征交叉的一些疑惑,而且从实验中发现,模型的效果要好于DCN模型。
完。