FM系列

非 Y 不嫁゛ 提交于 2020-02-14 04:28:01

在计算广告中,CTR是非常重要的一环。对于特征组合来说,业界通用的做法主要有两大类:FM系列和Tree系列。这里我们来介绍一下FM系列。
在传统的线性模型中,每个特征都是独立的,如果需要考虑特征与特征之间的相互作用,可能需要人工对特征进行交叉组合。非线性SVM可以对特征进行核变换,但是在特征高度稀疏的情况下,并不能很好的进行学习。现在有很多分解模型可以学习到特征之间的交互隐藏关系,基本上每个模型都只适用于特定的输入和场景。推荐系统是一个高度稀疏的数据场景,由此产生了FM系列算法。
本文主要涉及四种FM系列算法:FM,FFM,DeepFM,DeepFFM

因子分解机 (Factorization Machine,简称FM)

FM算法用于解决大规模稀疏数据下的特征组合问题。FM可以看做带特征交叉的LR。
考虑两阶多项式模型,也就是特征两两组合的问题,模型表达如下:
\[ \hat y(x) = w_0+\sum_{i=1}^n w_i x_i +\sum_{i=1}^n \sum_{j=i+1}^n w_{ij}x_i x_j \]
其中\(n\)表示样本的特征数量,这里的特征是离散化后的特征。
然而,在数据稀疏性普遍存在的实际应用场景中,二次项参数的训练是很困难的。其原因是,每个参数 \(w_ij\) 的训练需要大量 \(x_i\)\(x_j\) 都非零的样本;由于样本数据本来就比较稀疏,满足“\(x_i\)\(x_j\) 都非零”的样本将会非常少。训练样本的不足,很容易导致参数 \(w_{ij}\) 不准确,最终将严重影响模型的性能。
为了解决二阶交叉项参数的学习问题,把多项式模型中二阶交叉项参数\(w_{ij}\)组成一个对称矩阵\(W\)(对角元素设为正实数),那么这个矩阵就可以分解。

将每个交叉项参数\(w_{ij}\)用隐向量的内积\(⟨vi,vj⟩\)表示,是FM模型的核心思想。

以二阶为例,FM模型表达式:
\[ \hat y(x) = w_0+\sum_{i=1}^n w_i x_i +\sum_{i=1}^n \sum_{j=i+1}^n ⟨vi,vj⟩ x_i x_j \]
其中\(v_i\)表示第\(i\)特征的隐向量,\(<\cdot,\cdot>\)表示两个长度为\(k\)的向量的内积,计算公式为:
\[ ⟨vi,vj⟩:=\sum_{f=1}^k v_{i,f} \cdot v_{j,f} \]
参数因子化表示后,使得\(x_h x_i\)的参数与\(x_i x_j\)的参数不再相互独立。这样我们就可以在样本稀疏情况下相对合理的估计FM模型交叉项的参数。
FM模型的复杂度为\(O(kn^2)\),但是通过下面的等价转换,可以将FM的二次项化简,其复杂度可优化到\(O(kn)\)。即:
\[ \sum_{i=1}^{n} \sum_{j=i+1}^{n} {\langle \mathbf{v}_i, \mathbf{v}_j \rangle} x_i x_j = \frac{1}{2} \sum_{f=1}^{k} {\left \lgroup \left(\sum_{i=1}^{n} v_{i,f} x_i \right)^2 - \sum_{i=1}^{n} v_{i,f}^2 x_i^2\right \rgroup} \qquad \]
详细推导如下:
\[ \begin{aligned} & \sum_{i=1}^{n} \sum_{j=i+1}^{n} {\langle \mathbf{v}_i, \mathbf{v}_j \rangle} x_i x_j \qquad\qquad\qquad\qquad\qquad\qquad(1)\\ = & \frac{1}{2} \sum_{i=1}^{n} \sum_{j=1}^{n} {\langle \mathbf{v}_i, \mathbf{v}_j \rangle} x_i x_j - \frac{1}{2} \sum_{i=1}^{n} {\langle \mathbf{v}_i, \mathbf{v}_i \rangle} x_i x_i \qquad\qquad\;\;(2)\\ = & \frac{1}{2} \left(\sum_{i=1}^{n} \sum_{j=1}^{n} \sum_{f=1}^{k} v_{i,f} v_{j,f} x_i x_j - \sum_{i=1}^{n} \sum_{f=1}^{k} v_{i,f} v_{i,f} x_i x_i \right) \qquad\,(3) \\ = & \frac{1}{2} \sum_{f=1}^{k} {\left \lgroup \left(\sum_{i=1}^{n} v_{i,f} x_i \right) \cdot \left(\sum_{j=1}^{n} v_{j,f} x_j \right) - \sum_{i=1}^{n} v_{i,f}^2 x_i^2 \right \rgroup} \quad\;\;\,(4) \\ = & \frac{1}{2} \sum_{f=1}^{k} {\left \lgroup \left(\sum_{i=1}^{n} v_{i,f} x_i \right)^2 - \sum_{i=1}^{n} v_{i,f}^2 x_i^2\right \rgroup} \qquad\qquad\qquad\;\;(5) \end{aligned} \]
解读第(1)步到第(2)步,这里用\(A\)表示系数矩阵\(V\)的上三角元素,\(B\)表示对角线上的交叉项系数。由于系数矩阵\(V\)是一个对称阵,所以下三角与上三角相等,有下式成立:
\[ A = \frac{1}{2} (2A+B) - \frac{1}{2} B. \quad \underline{ A=\sum_{i=1}^{n} \sum_{j=i+1}^{n} {\langle \mathbf{v}_i, \mathbf{v}_j \rangle} x_i x_j } ; \quad \underline{ B = \frac{1}{2} \sum_{i=1}^{n} {\langle \mathbf{v}_i, \mathbf{v}_i \rangle} x_i x_i } \quad \]
如果用随机梯度下降(Stochastic Gradient Descent)法学习模型参数。那么,模型各个参数的梯度如下:
\[ \frac{\partial}{\partial \theta} y(\mathbf{x}) = \begin{cases} 1, & \text{if}\; \theta\; \text{is}\; w_0 \text{(常数项)} \\ x_i & \text{if}\; \theta\; \text{is}\; w_i \text{(线性项)} \\ x_i \sum_{j=1}^{n} v_{j,f} x_j - v_{i,f} x_i^2, & \text{if}\; \theta\; \text{is}\; v_{i,f} \text{(交叉项)} \end{cases} \]

由于\(\sum_{j=1}^{n} v_{j,f} x_j\)只与\(f\)有关,在参数迭代过程中,只需要计算第一次所有\(f\)\(\sum_{j=1}^{n} v_{j,f} x_j\),就能够方便地得到所有\(v_{i,f}\)的梯度。显然,计算所有\(f\)\(\sum_{j=1}^{n} v_{j,f} x_j\)的复杂度是\(O(kn)\);已知\(\sum_{j=1}^{n} v_{j,f} x_j\)时,计算每个参数梯度的复杂度是\(O(n)\);得到梯度后,更新每个参数的复杂度是 \(O(1)\);模型参数一共有\(nk+n+1\)个。因此,FM参数训练的时间复杂度为\(O(kn)\)
综上可知,FM算法可以在线性时间内完成模型训练,以及对新样本做出预测,所以说FM是一个非常高效的模型。

损失函数

  • 回归问题
    对于回归问题,损失函数可取为最小平方误差,即
    \[ loss(\hat y,y) = (\hat y -y)^2 \]

  • 二分类问题
    对于二分类问题(其中标签$y \in {+1,-1} $),损失函数可取为hinge loss函数 或 logit loss函数
  1. hinge loss函数
    \[ loss(\hat y,y) = max \{ 0,1-y \hat y \}, \]
    \(y=+1\)时,
    \[ loss(\hat y,y) = max \{ 0,1- \hat y \}= \begin{cases} 0,\ \ \ \ \ \ \ \ \ \ \ \ \hat y \geq 1; \\ 1-\hat y,\ \ \ \ \ \hat y < 1; \end{cases} \]
    \(y=-1\)时,
    \[ loss(\hat y,y) = max \{ 0,1+ \hat y \}= \begin{cases} 0,\ \ \ \ \ \ \ \ \ \ \ \ \hat y \leq -1; \\ 1+\hat y,\ \ \ \ \ \hat y > -1; \end{cases} \]
    模型训练好后,就可以利用\(\hat y(x)\)的正负符号来预测\(x\)的分类了。

  2. logit loss函数
    \[ loss(\hat y,y) = - \ln \sigma (\hat y y) \]
    其中\(\sigma(x)=\frac{1}{1+e^{-x}}\)\(sigmoid\)函数,可见\(\hat y\)\(y\)越接近,损失$loss(\hat y,y) $就越小。

此外,为了防止过拟合,我们通常会在优化目标函数中加入正则项(如L2正则)。

总结:

  1. FM降低了交叉项参数学习不充分的影响
    one-hot编码后的样本数据非常稀疏,组合特征更是如此。为了解决交叉项参数学习不充分、导致模型有偏或不稳定的问题。作者借鉴矩阵分解的思路:每一维特征用\(k\)维的隐向量表示,交叉项的参数\(w_{ij}\)用对应特征隐向量的内积表示,即\(⟨v_i,v_j\)(也可以理解为平滑技术)。这样参数学习由之前学习交叉项参数\(w_{ij}\)的过程,转变为学习\(n\)个单特征对应\(k\)维隐向量的过程。
    很明显,单特征参数(\(k\)维隐向量\({v_i}\))的学习要比交叉项参数\(wij\)学习得更充分。

  2. FM提升了模型预估能力
    由于FM学习的参数就是单特征的隐向量,那么交叉项的预估结果可以用隐向量内积得到。这样,即便训练集中没有出现交叉项的样本,FM模型仍然可以用来预估,提升了预估能力。

  3. FM提升了参数学习效率
    这个显而易见,参数个数由\((n^2+n+1)\)变为\((nk+n+1)\)个,模型训练复杂度也由\(O(mn^2)\))变为\(O(mnk)\)\(m\)为训练样本数。对于训练样本和特征数而言,都是线性复杂度。
    此外,就FM模型本身而言,它是在多项式模型基础上对参数的计算做了调整,因此也有人把FM模型称为多项式的广义线性模型,也是恰如其分的。

FM模型对稀疏数据有更好的学习能力,通过交互项可以学习特征之间的关联关系,并且保证了学习效率和预估能力。

FM vs SVM

SVM和FM的主要区别在于:

  • SVM的二元特征交叉参数是独立的,而FM的二元特征交叉参数是两个k维的向量\(v_i\)\(v_j\),交叉参数就不是独立的,而是相互影响的。
  • FM可以在原始形式下进行优化学习,而基于kernel的非线性SVM通常需要在对偶形式下进行
  • FM的模型预测是与训练样本独立,而SVM则与部分训练样本有关,即支持向量

FM vs LR

Fm学习的是特征的隐向量,没有出现的特征也可以通过隐向量内积得到,打破了特征之间的独立性。LR学习的是组合特征的权重,没有出现的组合特征,权重无法学习。简单理解就是数据太稀疏了,\(x_i*x_j\)的样本不一定存在,LR就无法学习\(w_{ij}\)

场感知分解机(Field-aware Factorization Machine ,简称FFM)

在CTR预估中,通常会遇到one-hot类型的变量,会导致数据特征的稀疏。未解决这个问题,FFM在FM的基础上进一步改进,在模型中引入类别的概念,即field。将同一个field的特征单独进行one-hot,因此在FFM中,每一维特征都会针对其他特征的每个field,分别学习一个隐变量,该隐变量不仅与特征相关,也与field相关。假设样本的n个特征属于f个field,那么FFM的二次项有nf个隐向量。而在FM模型中,每一维特征的隐向量只有一个。FM可以看做FFM的特例,把所有特征都归属到一个field的FFM模型。通过引入field的概念,FFM把相同性质的特征归于同一个field。
同一个categorical特征可以包括用户属性信息(年龄、性别、职业、收入、地域等),用户行为信息(兴趣、偏好、时间等),上下文信息(位置、内容等)以及其它信息(天气、交通等)。

其模型表达式为:
\[ \hat{y}(\mathbf{x}) := w_0 + \sum_{i=1}^{n} w_i x_i + \sum_{i=1}^{n} \sum_{j=i+1}^{n} \langle \mathbf{v}_{i,\,f_j}, \mathbf{v}_{j,\,f_i} \rangle x_i x_j \qquad \]
其中,\(fj\)是第\(j\)个特征所属的field。如果隐向量的长度为\(k\),那么FFM的二交叉项参数就有n\(fk\)个,远多于FM模型的\(nk\)个。此外,由于隐向量与field相关,FFM的交叉项并不能够像FM那样做化简,其预测复杂度为\(O(kn^2)\)

FFM应用

在DSP或者推荐场景中,FFM主要用来评估站内的CTR和CVR,即一个用户对一个商品的潜在点击率和点击后的转化率。
CTR和CVR预估模型都是在线下训练,然后线上预测。两个模型采用的特征大同小异,主要分三类:

  • 用户相关的特征
    年龄、性别、职业、兴趣、品类偏好、浏览/购买品类等基本信息,以及用户近期点击量/购买量/消费额等统计信息

  • 商品相关的特征
    商品所属品类、销量、价格、评分、历史CTR/CVR等信息

  • 用户-商品匹配特征
    浏览/购买品类匹配、浏览/购买商家匹配、兴趣偏好匹配等

为了使用FFM方法,所有的特征必须转换成“field_id:feat_id:value”格式,field_id代表特征所属field的编号,feat_id是特征编号,value是特征的值。数值型的特征比较容易处理,只需分配单独的field编号,如用户评论得分、商品的历史CTR/CVR等。categorical特征需要经过One-Hot编码成数值型,编码产生的所有特征同属于一个field,而特征的值只能是0或1,如用户的性别、年龄段,商品的品类id等。除此之外,还有第三类特征,如用户浏览/购买品类,有多个品类id且用一个数值衡量用户浏览或购买每个品类商品的数量。这类特征按照categorical特征处理,不同的只是特征的值不是0或1,而是代表用户浏览或购买数量的数值。按前述方法得到field_id之后,再对转换后特征顺序编号,得到feat_id,特征的值也可以按照之前的方法获得。

实践注意项

  • 样本归一化:FFM默认是进行样本数据的归一化,即 为真;若此参数设置为假,很容易造成数据inf溢出,进而引起梯度计算的nan错误。因此,样本层面的数据是推荐进行归一化的。
  • 特征归一化:CTR/CVR模型采用了多种类型的源特征,包括数值型和categorical类型等。但是,categorical类编码后的特征取值只有0或1,较大的数值型特征会造成样本归一化后categorical类生成特征的值非常小,没有区分性。例如,一条用户-商品记录,用户为“男”性,商品的销量是5000个(假设其它特征的值为零),那么归一化后特征“sex=male”(性别为男)的值略小于0.0002,而“volume”(销量)的值近似为1。特征“sex=male”在这个样本中的作用几乎可以忽略不计,这是相当不合理的。因此,将源数值型特征的值归一化到 是非常必要的。
  • 省略零值特征:从FFM模型的表达式可以看出,零值特征对模型完全没有贡献。包含零值特征的一次项和组合项均为零,对于训练模型参数或者目标值预估是没有作用的。因此,可以省去零值特征,提高FFM模型训练和预测的速度,这也是稀疏样本采用FFM的显著优势。

实现FM & FFM的最流行的python库有:LibFM、LibFFM、xlearn和tffm。其中,xLearn是一款高性能,易于使用且可扩展的机器学习软件包,包括FM和FFM模型,可用于大规模解决机器学习问题。xlearn比libfm和libffm库快得多,并为模型测试和调优提供了更好的功能。

DeepFM

FM通过对于每一位特征的隐变量内积来提取特征组合,最后的结果也不错,虽然理论上FM可以对高阶特征组合进行建模,但实际上因为计算复杂度原因,一般都只用到了二阶特征组合。对于高阶特征组合来说,我们很自然想到多层神经网络DNN。
DeepFM目的是同时学习低阶和高阶的特征交叉,主要由FM和DNN两部分组成,底部共享同样的输入。模型可以表示为:
\[ \hat{y} = sigmoid(y_{FM}+y_{DNN}) \]

DeepFM

  1. FM部分
    数学表达为:
    \[ y_{FM} = w_0+\sum_{i=1}^n w_i x_i +\sum_{i=1}^n \sum_{j=i+1}^n ⟨vi,vj⟩ x_i x_j \]
    FM模型可以用神经网络进行表示,模型输入\(x=[x_{field1},x_{field2},⋯,x_{fieldm}]\),这是一个\(d\)维的向量,其中\(x_{fieldi}\)即为第\(i\)\(field\)的特征表示,如果是类别,则为one-hot编码后的向量,连续值则为它本身。然后对每个field分别进行embedding
    DeepFM FM部分
    值得注意的是,即使各个field的维度是不一样的,但是它们embedding后长度均为k。
    接着FM层即为embedding后结果的内积和一次项的和,最后一层sigmoid后再输出结果。

  2. 深度部分
    是一个前馈神经网络,与图像或语音类的输入不同,CTR的输入一般是极其稀疏的,因此需要重新设计网络结构。在第一层隐藏层之前,引入一个嵌入层来完成输入向量压缩到低位稠密向量:

嵌入层的输出为\(a(0)=[e1,e2,...,em]\),其中\(e_i\)是嵌入的第i个filed,m是field的个数,前向过程将嵌入层的输出输入到隐藏层为
\[ a(l+1)=σ(W^{(l)}a^{(l)}+b^{(l)}) \]
其中\(l\)是层数,\(σ\)是激活函数,\(W(l)\)是模型的权重,\(b(l)\)\(l\)层的偏置
因此,DNN得预测模型表达为:
\[ y_{DNN} = W^{|H|+1} \cdot a^{|H|} + b^{|H|+1} \]
\(|H|\)为隐藏层层数

有两个有趣的特性:
1) 尽管不同field的输入长度不同,但是embedding之后向量的长度均为k
2) 在FM中得到的隐变量\(V_{ik}\)现在作为嵌入层网络的权重

Embedding层的隐式向量在(残差反向传播)训练时可以同时接受到深度部分和FM部分的信息,从而使Embedding层的信息表达更加准确而最终提升推荐效果。
需要指出的是,FM部分与深度部分共享相同的embedding带来了两个好处:
1.从原始数据中同时学习到了低维与高维特征
2.不再需要特征工程。而Wide&Deep Model需要

DeepFFM

类似于FFM对于FM模型来说,划分了field,对于不同的field内积时采用对应的隐向量。同样可以把DeepFM进行进化为DeepFFM,即将每一个field embedding为m个维度为k的隐向量(m为field的个数)

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!