推荐系统:Wide & Deep模型解析

2023-11-06

1 Wide & Deep模型介绍

经典推荐深度模型 Wide & Deep,对应的论文《Wide & Deep Learning for Recommender Systems》,链接:arxiv
Wide & Deep的模型架构如下图所示:

可以看到Wide & Deep模型分成Wide和Deep两部分。Wide部分就是一个简单的线性模型,Deep部分是一个前馈神经网络模型。将线性模型和前馈神经网络模型合并在一起训练。

2 推荐系统架构

推荐系统
当一个用户请求过来的时候,推荐系统首先会从海量的item里面挑选出O(100) 个用户可能感兴趣的item(召回阶段)。然后这 O(100)个item将会输入到模型里面进行排序。根据模型的排序结果再选择出topN个item返回给用户。同时,用户会对展示的item进行点击,购买等等。最终,用户的feature,上下文feature,item的feature和user action会以log的信息保存起来,经过处理后生成新的训练数据,提供给模型进行训练。paper的重点放在使用wide & deep架构为基础的排序模型。

3 Wide & Deep模型的“记忆能力”与“泛化能力”

Memorization 和 Generalization是推荐系统很常见的两个概念,其中Memorization指的是通过用户与商品的交互信息矩阵学习规则,而Generalization则是泛化规则。我们前面介绍的FM算法就是很好的Generalization的例子,它可以根据交互信息学习到一个比较短的矩阵 V V V,其中 v i v_{i} vi储存着每个用户特征的压缩表示(embedding),而协同过滤与SVD都是靠记住用户之前与哪些物品发生了交互从而推断出的推荐结果,这两者推荐结果当然存在一些差异,我们的Wide&Deep模型就能够融合这两种推荐结果做出最终的推荐,得到一个比之前的推荐结果都好的模型。
可以这么说:Memorization趋向于更加保守,推荐用户之前有过行为的items。相比之下,generalization更加趋向于提高推荐系统的多样性(diversity)。Memorization只需要使用一个线性模型即可实现,而Generalization需要使用DNN实现。

其实wide&deep模型本身的结构是非常简单的,对于有点机器学习基础和深度学习基础的人来说都非常的容易看懂,但是如何根据自己的场景去选择那些特征放在Wide部分,哪些特征放在Deep部分就需要理解这篇论文提出者当时对于设计该模型不同结构时的意图了,所以这也是用好这个模型的一个前提。

如何理解Wide部分有利于增强模型的“记忆能力”,Deep部分有利于增强模型的“泛化能力”?

3.1 Wide部分
  • Wide部分是一个广义的线性模型,输入的特征主要有两部分组成,一部分是原始的部分特征,另一部分是原始特征的交互特征(cross-product transformation),对于交互特征可以定义为:
    ϕ k ( x ) = ∏ i = 1 d x i c k i , c k i ∈ { 0 , 1 } \phi_{k}(x)=\prod_{i=1}^d x_i^{c_{ki}}, c_{ki}\in \{0,1\} ϕk(x)=i=1dxicki,cki{0,1}
    这个式子的大体意思就是两个特征都同时为1这个新的特征才能为1,否则就是0,说白了就是一个特征组合。用原论文的例子举例:

    AND(user_installed_app=QQ, impression_app=WeChat),当特征user_installed_app=QQ,和特征impression_app=WeChat取值都为1的时候,组合特征AND(user_installed_app=QQ, impression_app=WeChat)的取值才为1,否则为0。
    对于wide部分训练时候使用的优化器是带 L 1 L_1 L1正则的FTRL算法(Follow-the-regularized-leader),而L1 FTLR是非常注重模型稀疏性质的,也就是说W&D模型采用L1 FTRL是想让Wide部分变得更加的稀疏,即Wide部分的大部分参数都为0,这就大大压缩了模型权重及特征向量的维度。**Wide部分模型训练完之后留下来的特征都是非常重要的,那么模型的“记忆能力”就可以理解为发现"直接的",“暴力的”,“显然的”关联规则的能力。**例如Google W&D期望wide部分发现这样的规则:用户安装了应用A,此时曝光应用B,用户安装应用B的概率大。

3.2 Deep部分
  • Deep部分是一个馈神经网络模型。对于高维稀疏的分类特征,首先会转化成低维的稠密的向量,然后作为神经网hidden layers的输入进行训练。输入的特征主要分为两大类,一类是数值特征(可直接输入DNN),一类是类别特征(需要经过Embedding之后才能输入到DNN中),Deep部分的数学形式如下:
    a ( l + 1 ) = f ( W l a ( l ) + b l ) a^{(l+1)} = f(W^{l}a^{(l)} + b^{l}) a(l+1)=f(Wla(l)+bl)
    f f f是激活函数(例如ReLu), a a a是上一个hidden layer的输出, W W W是要训练的参数, b b b是偏置项bias。
    我们知道DNN模型随着层数的增加,中间的特征就越抽象,也就提高了模型的泛化能力。对于Deep部分的DNN模型作者使用了深度学习常用的优化器AdaGrad,这也是为了使得模型可以得到更精确的解。

Wide部分与Deep部分的结合
W&D模型是将两部分输出的结果结合起来联合训练,将deep和wide部分的输出重新使用一个逻辑回归模型做最终的预测,输出概率值。联合训练的数学形式如下:
P ( Y = 1 ∣ x ) = δ ( w w i d e T [ x , ϕ ( x ) ] + w d e e p T a ( l f ) + b ) P(Y=1|x)=\delta(w_{wide}^T[x,\phi(x)] + w_{deep}^T a^{(lf)} + b) P(Y=1x)=δ(wwideT[x,ϕ(x)]+wdeepTa(lf)+b)

4 系统实现

推荐系统的实现一共分成了三个阶段:数据生成,模型训练和模型服务。如下图所示:
在这里插入图片描述
(1)数据生成阶段
在这个阶段,最近N天的用户和item将会用来生成训练数据。每条展示过的item将会对应有一个目标label。例如1表示用用户点击过,0表示用户没点击过。图中的Vocabulary Generation主要用来做数据转换。例如需要把分类特征转换成对应的整数Id,连续的实数特征将会按照累积概率分布映射到[0, 1]等等。

(2)模型训练阶段
在数据生成阶段我们产生了包含稀疏特征,稠密特征和label的训练样本,这些样本将作为输入放入到模型里面训练。如下图所示:
在这里插入图片描述
wide的部分包含了经过Cross Product转换的特征。对于deep的部分,分类特征首先会经过一层embedding,然后和稠密的特征concatenate起来后,经过3层的hidden layers,最后和wide部分联合起来通过sigmoid输出。
wide&deep模型尽管在模型结构上非常的简单,但是如果想要很好的使用wide&deep模型的话,还是要深入理解业务,确定wide部分使用哪部分特征,deep部分使用哪些特征,以及wide部分的交叉特征应该如何去选择。
paper中还提到,因为google在训练的时候训练样本数超过5000亿,每次所有样本重新训练的成本和延迟非常大。为了解决这个问题,在初始化一个新的模型的时候,将会使用老模型的embedding参数和线性模型的weight参数初始化新模型。

(3)模型服务阶段
确认训练没问题以后,模型就可以上线。对于用户的请求,服务器首先会选出用户感兴趣的候选集,然后这些候选集将会放入到模型里面进行预测。将预测结果的分数从高到低排序,然后取排序结果的topN返回给用户。

5 代码实战

代码实战主要分为两大部分,第一部分是使用tensorflow中已经封装好的wide&deep模型,这一部分主要是熟悉模型训练的整体结构。第二部分是使用tensorflow中的keras实现wide&deep,这一部分主要是尽可能的看到模型内部的细节并将其实现。
Tensorflow内置的WideDeepModel
在Tensorflow的库中是已经内置了Wide-Deep model的,想要查看源代码了解具体实现过程可以看这里。下面参考Tensorflow官网的示例代码进行讲解。我们用到的数据集下载链接戳这里
首先看全局实现:

tf.keras.experimental.WideDeepModel(
    linear_model, dnn_model, activation=None, **kwargs
)

这一步很容易看出来就是将linear_model与dnn_model拼接在了一起,对应于Wide-Deep FM中的最后一步。比如我们可以将linear_model与dnn_model做一个最简单的实现:

linear_model = LinearModel()
dnn_model = keras.Sequential([keras.layers.Dense(units=64),
                             keras.layers.Dense(units=1)])
combined_model = WideDeepModel(linear_model, dnn_model)
combined_model.compile(optimizer=['sgd', 'adam'], 'mse', ['mse'])
# define dnn_inputs and linear_inputs as separate numpy arrays or
# a single numpy array if dnn_inputs is same as linear_inputs.
combined_model.fit([linear_inputs, dnn_inputs], y, epochs)
# or define a single `tf.data.Dataset` that contains a single tensor or
# separate tensors for dnn_inputs and linear_inputs.
dataset = tf.data.Dataset.from_tensors(([linear_inputs, dnn_inputs], y))
combined_model.fit(dataset, epochs)

这里第一步就是直接调用一个keras.experimental中的linear_model,第二步简单实现了一个全连接神经网络,第三步使用WideDeepModel将前两步产生的两个model拼接在一起,形成最终的combined_model,接着就是常规的compile和fit了。
除此之外线性模型与DNN模型在联合训练之前均可进行分别训练:

linear_model = LinearModel()
linear_model.compile('adagrad', 'mse')
linear_model.fit(linear_inputs, y, epochs)
dnn_model = keras.Sequential([keras.layers.Dense(units=1)])
dnn_model.compile('rmsprop', 'mse')
dnn_model.fit(dnn_inputs, y, epochs)
combined_model = WideDeepModel(linear_model, dnn_model)
combined_model.compile(optimizer=['sgd', 'adam'], 'mse', ['mse'])
combined_model.fit([linear_inputs, dnn_inputs], y, epochs)

这里前三行代码训练了一个线性模型,中间三行代码训练了一个DNN模型,最后三行代码则将两个模型联合训练,以上就完成了对Tensorflow的WideDeepModel的调用,其中每个函数有一些其他参数我们这里不详细说明,读者若有需要可自行在tensorflow官网查询,另外该部分的源代码在Tensorflow的Github上有展示,链接在这

Tensorflow实现wide&deep模型
这一部分对原始特征进行转换,以及deep特征和wide特征的选择,特征的交叉等一系列特征操作,模型也分成了wide部分和deep部分,相比于上述直接使用tensorflow内置的模型,更加的详细,可以对模型理解的更加的深刻。
在这里wide和deep部分的优化,为了简单实现,使用了同一个优化器优化两部分,详细内容参考代码中的注释。
代码参考源代码文档。

深度学习推荐系统的发展
Wide&Deep模型在深度学习发展中起到了非常重要的作用,从下图中我们就可以看到它对后续模型发展的一个影响。
在这里插入图片描述

课后思考:
Wide&Deep模型仍然存在哪些不足,针对这些不足工程师们有哪些改进?
Wide & Deep Model适用于输入非常稀疏的大规模分类或回归问题。比如推荐系统、search、ranking问题。实现了对memorization和generalization的统一建模。
缺点:Wide部分还是需要人为的特征工程。

参考资料

https://github.com/datawhalechina
[深度模型] 经典Wide & Deep模型架构介绍
见微知著,你真的搞懂Google的Wide&Deep模型了吗?
推荐系统CTR实战——Wide & Deep
看Google如何实现Wide & Deep模型(1)
用NumPy手工打造 Wide & Deep
论文原文
https://blog.csdn.net/u010352603/article/details/80590129
https://www.tensorflow.org/api_docs/python/tf/keras/experimental/WideDeepModel
deepctr项目

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

推荐系统:Wide & Deep模型解析 的相关文章

随机推荐