在计算广告中,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的个数)

FM系列的更多相关文章

  1. 推荐系统实践 0x0c FM系列

    逻辑回归(LR) 在介绍FM系列之前,我想首先简单介绍一下逻辑回归.通常来说,逻辑回归模型能够综合利用更多的信息,如用户.物品.上下文等多种不同的特征,生成更为全面的结果.另外,逻辑回归将推荐问题看成 ...

  2. FM算法

    1.FM背景 在计算广告中,CTR预估(click-through rate)是非常重要的一个环节,因为DSP后面的出价要依赖于CTR预估的结果.在前面的相关博文中,我们已经提到了CTR中相关特征工程 ...

  3. 个性化排序算法实践(一)——FM算法

    因子分解机(Factorization Machine,简称FM)算法用于解决大规模稀疏数据下的特征组合问题.FM可以看做带特征交叉的LR. 理论部分可参考FM系列,通过将FM的二次项化简,其复杂度可 ...

  4. 大厂技术实现 | 腾讯信息流推荐排序中的并联双塔CTR结构 @推荐与计算广告系列

    作者:韩信子@ShowMeAI,Joan@腾讯 地址:http://www.showmeai.tech/article-detail/tencent-ctr 声明:版权所有,转载请联系平台与作者并注明 ...

  5. FFM算法解析及Python实现

    1. 什么是FFM? 通过引入field的概念,FFM把相同性质的特征归于同一个field,相当于把FM中已经细分的feature再次进行拆分从而进行特征组合的二分类模型. 2. 为什么需要FFM? ...

  6. CTR预估经典模型总结

    计算广告领域中数据特点:    1 正负样本不平衡    2 大量id类特征,高维,多领域(一个类别型特征就是一个field,比如上面的Weekday.Gender.City这是三个field),稀疏 ...

  7. 深度排序模型概述(一)Wide&Deep/xDeepFM

    本文记录几个在广告和推荐里面rank阶段常用的模型.广告领域机器学习问题的输入其实很大程度了影响了模型的选择,因为输入一般维度非常高,稀疏,同时包含连续性特征和离散型特征.模型即使到现在DeepFM类 ...

  8. 个性化排序算法实践(五)——DCN算法

    wide&deep在个性化排序算法中是影响力比较大的工作了.wide部分是手动特征交叉(负责memorization),deep部分利用mlp来实现高阶特征交叉(负责generalizatio ...

  9. 个性化排序算法实践(三)——deepFM算法

    FM通过对于每一位特征的隐变量内积来提取特征组合,最后的结果也不错,虽然理论上FM可以对高阶特征组合进行建模,但实际上因为计算复杂度原因,一般都只用到了二阶特征组合.对于高阶特征组合来说,我们很自然想 ...

随机推荐

  1. React:快速上手(8)——前后端分离的跨域访问与会话保持

    React:快速上手(8)——前后端分离的跨域访问与会话保持 跨域访问 跨域是指从一个域名的网页去请求另一个域名的资源.比如从http://www.baidu.com/ 页面去请求http://www ...

  2. robot:根据条件主动判定用例失败或者通过

    场景: 当用例中的断言部分需要满足特定条件时才会执行,如果不满足条件时,可以主动判定该用例为passed状态,忽略下面的断言语句. 如上图场景,当每月1号时,表中才会生成上月数据,生成后数据不会再有改 ...

  3. Linux18.04换源等等等配置

    root用户 sudo passwd root 安装Tools 文件→其他位置→Vmware Tools→打开终端. 管理员权限→copy→tar -zxvf 文件名解压→打开vmware-tools ...

  4. 【JS】实用/常用函数/Function方法

    1.获取日月 时分秒 //获取 月日 getMonth=(time)=>{ var date = new Date(time) <?):(date.getMonth()+) ?'+date ...

  5. 深入css过渡transition

    通过过渡transition,可以让web前端开发人员不需要javascript就可以实现简单的动画交互效果.过渡属性看似简单,但实际上它有很多需要注意的细节和容易混淆的地方. 过渡transitio ...

  6. php有关类和对象的相关知识2

    与类有关的魔术常量: __CLASS__,:获取其所在的类的类名. __METHOD__:获取其所在的方法的方法名. class A{ function f1(){ echo __CLASS__: / ...

  7. ubuntu gcc 安装 使用

    "人多不足以依赖,要生存只有靠自己." -- 拿破仑 gcc是什么:-------------------------- Linux系统下的Gcc(GNU C Compiler)是 ...

  8. PHP与Memcached服务器交互的分布式实现源码分析

    转自: http://blog.csdn.net/hguisu/article/details/7353595 前段时间,因为一个项目的关系,研究了php通过调用memcache和memcached ...

  9. PB笔记之第一行数据不能删除的解决方法

    如果第一行数据不能删除,则单独写SQL进行删除 window lw_sheet //dw_1.event pfc_deleterow()long i String ls_manidInteger ls ...

  10. Javascritp Array数组方法总结

    合并数组 - concat() 用法一 (合并两个数组) var hege = ["Cecilie", "Lone"]; var stale = [" ...