前言
上篇文章中我们引入了推荐系统中特征交叉的概念,以及介绍了一些常见的特征交叉方法,这篇文章我们将详细地讨论一下推荐系统中特征交叉地模型,他们的特点,以及他们为什么会这样。本文中介绍的模型有Wide & Deep,deepFM,NFM,以及AFM和相应地拓展。
Wide & Deep 首先附上Wide&deep的模型结构,看起来很简单,左边时一个线性模型,右边时一个DNN模型。该模型采用线性部分提升模型的记忆能力,同时采用DNN部分提升模型的泛化能力。
与DNN部分相比,Wide部分更是这个模型的核心。它是一个使用L1正则化的FTLR模型,该模型之前被广泛地应用于推荐系统中,主要的一个特点就是稀疏化,模型的特征都是0,1。同时采用L1正则化训练,可以将最后参数W中0的取值尽可能地多(关于逻辑回归中L1正则,L2正则中w参数地变化大家应该都了解吧)。第二个特点就是特征高度交叉,交叉的方式与我上篇文章中第一种交叉方式相同。 与wide部分的结构相比,wide部分采用的特征也十分重要,谷歌在这篇论文中wide部分的特征是怎么选取的呢?下面这张图片是谷歌在他们系统中使用的模型(以谷歌商店APP推荐为例): 左边是DNN部分,其中**User Installed App(用户已经安装APP)和Impression App(曝光APP)**产生的Cross Product Transformation就是wide部分(这里其实还是有点误导,大家可以认为曝光APP其实就是我们常说的target app(即目标item)。在训练过程中,如果target后来被安装了,那么label为1,没有被安装则label为0)。Cross Product Transformation其实就是将用户已经安装的app和待预测的app进行交叉。由于app的数量很多,交叉起来会直接爆炸,因此采用了FTLR来过滤一些稀疏特征。
为了防止大家对交叉和训练的方式有疑惑,我这里详细介绍一下: 假如FTLR中只有app交叉特征,app总数量为26个(用A-Z表示),那么FTLR中W的维度为676(26x26)。如果某个用户已经安装的app为(A,B),待预测的app为(E),那么交叉得到的特征为(A&E,B&E)两个特征,这时候我们找出这两个特征对应的w进行梯度下降。模型训练完成后我们只需要保存每个特征(676维)和对应的w值。线上通过特征交叉我们可以得分相应的特征,直接取w进行相加就可以得到wide侧的值了(或许再加上一个sigmoid)。
总结与展望:wide&deep在DNN的基础上引入了wide侧进行联合优化,在DNN的高拟合基础上增加了模型的记忆能力。wide侧的模型是一个使用L1正则化的FTLR模型,主要用于记忆用户已安装app和target app之间的关联。
看完这个wide侧之后,我想了又想,虎躯一震,觉得将FTLR变为DNN不就是YoutubeDNN的核心部分吗,都是通过挖掘用户已经产生行为的item和target Item之间的关联来优化目标,只是者采用了相对古老的FTLR,一种采用了相对比较新的embedding。
DeepFM
如果说选择一个深度模型做推荐的话,DeepFM真的就是强烈推荐了。话不多说,我们直接看DeepFM的模型结构。 模型左侧是FM,模型右侧是DNN。FM模型的结构很简单,我在之前的文章也介绍过了,大家感兴趣的话可以看:。除了这个模型优美的结构之外,还有一些有意思的地方。 我之前在脉脉上看到一个问题:**deepFM和wide&deep模型中DNN模块有什么不一样的地方。**这个问题看的我虎躯一震。之前根本没有注意到这个问题。其实就我的感觉其实这里涉及一个DNN模型的转化,目前推荐模型中现在很少会直接将连续值输入到模型中(直接category类的一直是one-hot)。 上图的wide&deep模型将用户的年纪,安装的App数量等特征直接输入到了模型之中(可能经过归一化),但是DeepFM模型中所有Field都进行了embedding,目前我所接触到的推荐模型中,也全都是将数值型进行了embedding。举个例子,用户年龄0-100,我们可以划为[0-7,7-14,14-19,19-25,25-35,35-50,50-60,60-75,75-10,其余]9个区间再加一个填充值(防止用户年龄缺失)。如果某个用户的年纪是22,那么我们可以将该用户进行embedding,结果是[0,0,0,1,0,0,0,0,0,0]。然后按照下面的方法就可以直接得到用户在年龄这个Field的embedding。但是更常见的做法是,将年龄为22的用户该特征的映射为4,年龄为10岁映射为1,然后直接查表进行embedding。 至于为什么大家现在都全部embedding,而不输入数值,我没有找到具体的解释,如果有大佬了解的话可以介绍下。
总结:DeepFM模型是将全部的特征分别进行FM和DNN,并且两边模型中的特征embedding都是共享的。不过在我看来,没必要将所有的特征都输入到FM和DNN中,两者如果可以进行特征分配可能会好一些,让更需要交叉的特征输入放入FM侧。
NFM
FM终究是一阶的交叉,如果要进行二阶三阶甚至更高阶的交叉的话是无法做到的。如果可以放入DNN中进行更高阶的交叉可能会有更好的效果。NFM就是一个这样的模型。 从上图中好像并没有看到FM的结构,只是有个奇怪的Bi-interaction Pooling。这是一个什么东西呢?
f
B
i
(
V
x
)
=
∑
i
=
1
n
∑
j
=
i
+
1
n
x
i
v
i
?
x
j
v
j
f_{Bi}(V_x)=\sum_{i=1}^{n}\sum_{j=i+1}^{n}x_iv_i*x_jv_j
fBi?(Vx?)=i=1∑n?j=i+1∑n?xi?vi??xj?vj? 其中
(
V
i
?
V
j
)
k
=
v
(
i
k
)
v
(
j
k
)
(V_i*V_j)_k=v_{(ik)} v_{(jk)}
(Vi??Vj?)k?=v(ik)?v(jk)?。 我们把FM模型拿出来看看:
F
M
:
y
=
w
0
+
∑
i
=
1
n
w
i
x
i
+
∑
i
=
1
n
∑
j
=
i
+
1
n
<
v
i
,
v
j
>
x
i
x
j
FM:y=w_0+\sum_{i=1}^{n}w_ix_i+\sum_{i=1}^{n}\sum_{j=i+1}^{n}<v_i,v_j>x_ix_j
FM:y=w0?+i=1∑n?wi?xi?+i=1∑n?j=i+1∑n?<vi?,vj?>xi?xj? 可以发现
v
i
,
v
j
v_i,v_j
vi?,vj?的向量乘法变成了点乘法,最终导致
f
B
i
(
V
x
)
f_{Bi}(V_x)
fBi?(Vx?)不再像FM结果那样是一个数值,从而变成了一个
k
k
k维的向量。用一句话表示就是Bi-interaction Pooling是在特征embedding后的每一个维度上进行了一次特征交叉。 讲述完最核心的部分之后,我们发现input Feature vector那里和上面我们介绍的deepFM的特征输入好像有点不一样,出现了一个0.2的数值型。那么它是怎么转化成上面的
v
7
v_7
v7?呢?其实是这样的,我们在对用户爱好进行embedding的时候,可能将爱好足球和游戏进行了embdeding,但是一个用户有多个爱好,对每个爱好的喜爱程度也不一样,这时候就会出现一个爱好得分,比如足球:0.2。这样将0.2乘以足球的embedding就是用户爱好足球的embedding。
以上就是NFM的核心部分了,论文模型也比较简单。论文说NFM的方式实现了更加维度的交叉,其实我内心是有点拒绝的,因此我认为特征与特征的交叉从始至终都只发生在Bi-interaction Pooling阶段。在这个阶段我们得到了一个在特征embedding后的每一个维度上进行了一次特征交叉的k维的embedding。所有特征的交叉都通过sum累计到了这个k维embedding中,后续将这个embedding输入到DNN模型中,也只是这个embedding内部的交叉,特征之间的差异信息已经全部通过sum全部掩盖了。当然我只是我从直观上来说,可能DNN大力出奇迹,真的学习到了多层交叉呢。
在我内心,其实还有一个别的Bi-interaction Pooling方法: 这个是常规的FM方法,正常情况下我们将m(m-1)/2个向量乘相加起来,但是如果我们不想加,直接再后面再加两层DNN网络的话,是不是可以将特征继续实现更高维度的交叉?我个人感觉从直观上来说是要比NFM说的高维度交叉更加合理的,可能计算的复杂度会高上不少。
总结:本文主要介绍了推荐系统中wide&deep,deepFM和NFM模型,重点在于介绍各个模型中的特征交叉,wide&deep中特征交叉部分主要使用带L1正则化的FTLR实现,DeepFM主要是使用FM进行实现特征交叉,而NFM采用了Bi-interaction Pooling方法将原本输出为数值的FM变为输出为一个k维的embedding,然后放入DNN中进行更高维度的交叉。此外,由于论文是各个不同的研究机构在不同时间发表的,在特征的处理或者说embedding方便有着一些区别。
|