学习资料
- Paper:《Wide & Deep Learning for Recommender Systems》
- ⭐⭐⭐ [blog] Wide & Deep算法介绍(文章风格幽默风趣,“Wide & Deep,直译为又深又宽,又名又长又宽,从名字里我们就隐约觉得它的背景不简单,是的,它竟是谷歌提出来的!不仅背景不简单,内涵也很不简单”)
- ⭐ [blog] AI上推荐 之 Wide&Deep与Deep&Cross模型(记忆与泛化并存的华丽转身)
一、背景知识
Wide&Deep模型是谷歌于2016年提出的,自提出以来在业界发挥着巨大的影响力。
Wide&Deep模型的最大价值在于同时具备较强的“记忆能力”和“泛化能力”。
Wide侧:让模型具有较强的“记忆能力”(memorization),单层Linear
Deep侧:让模型具有较强的“泛化能力”(generalization),多层MLP
这样的结构特点使模型兼具了逻辑回归和神经网络的优点——能够快速记忆大量历史行为数据,并且具有强大的表达能力。
在之后衍生出了大量以Wide&Deep为基础架构的混合模型。
1.1 问题:特征(属性)和特征取值的区别是什么?
在我的理解里颜色是一个特征,而{黄色,绿色,红色}这些都是颜色特征的取值!所以《深度学习推荐系统》P71里面应该这样去理解组合特征是user&impression,而netflix&pandora是这个组合特征的某个取值。因此书上说 netflix&pandora 是一个“强特征”,你应该理解成是一个“强特征取值”
再比如西瓜书上讲决策树的时候就把色泽当做是属性,然后“褐色”当做是属性的取值,所以是支持我的观点的。
在实际生活中,如果有人问你小明长什么样?我会问你想从哪些方面描述了解这个人,他说从身高,性别这两个方面(特征)吧,我说,“小明的这两个特征取值是身高很高,男的”
1.2 如何理解记忆性Memorization和泛化性Generalization
Google Wide&Deep这篇论文通篇都是这两个词,我们必须搞懂是怎么回事!
记忆和泛化是从人类的认知学习过程中演化来的。
人类的大脑很复杂,它可以记忆 (memorize) 下每天发生的事情(麻雀可以飞,鸽子可以飞),然后泛化 (generalize) 这些知识到之前没有看到过的东西(有翅膀的动物都能飞)。
-
记忆性的缺点:记忆的规则比较死板,不能处理没记过的东西,比如你知道麻雀可以飞,但是鹦鹉你从来没见过,你就不知道会不会飞了(泛化能力不够)
-
泛化性的缺点:泛化的规则有时候不是特别的准,有时候会出错(有翅膀的动物都能飞吗),也就是所谓的过度泛化。那怎么办呢?没关系,记忆 (memorization) 可以修正泛化的规则 (generalized rules),叫做特例(企鹅有翅膀,但是不能飞)。
《深度学习在美团推荐平台排序中的运用》https://tech.meituan.com/2017/07/28/dl.html
从下图我们可以看到,系统在非常靠前的位置推荐了一些远距离的商户,因为这些商户曾经被用户点过,其本身点击率较高,那么就很容易被系统再次推荐出来。但这种推荐并没有结合当前场景给用户推荐出一些有新颖性的Item。
在实际的运用当中,我们根据Google在2016年提出的Wide & Deep Learning模型,并结合自身业务的需求与特点,将线性模型组件和深度神经网络进行融合,形成了在一个模型中实现记忆和泛化的宽深度学习框架。
排序是一个非常经典的机器学习问题,实现模型的记忆和泛化功能是推荐系统中的一个挑战。记忆可以被定义为在推荐中将历史数据重现,而泛化是基于数据相关性的传递性,探索过去从未或很少发生的Item。
这就是 Memorization 和 Generalization 的来由或者说含义。
Wide&Deep就是希望计算机可以像人脑一样,可以同时发挥 memorization 和 generalization 的作用。
逻辑回归具有很强的记忆性
- 例如只要样本的特征3(交叉特征)的取值是netflix&pandas,那这个样本的标签大概率是1,也就是netflix&pandas进行one-hot编码后1所在的index对应的参数,如 ω 8 \omega_8 ω8设得很大。(就像一个深刻的记忆点一样印在脑海里)
- 相反,多层神经网络由于会将特征进行多层处理,不断与其他特征进行交叉,因此对这个强特征取值netflix&pandas反而没有简单模型那么深刻。
多层神经网络具有很强的泛化性
- Generalization是基于相关性之间的传递的
- 进行深层的特征交叉,挖掘藏在特征背后的数据模式(只要有翅膀的动物就能飞,鹦鹉我没之前没见过,但是它有翅膀,就能飞。说明我找到了数据的模式)。
二、Wide&Deep模型
经典的W&D的模型如下面中间的图所示(左边的是wide部分, 也就是一个简单的线性模型, 右边是deep部分, 一个经典的DNN模型)
Wide处理低阶特征交叉,Deep处理高阶特征交叉
2.1 Wide侧如何处理低阶特征交叉(请有经验的人员帮忙设计)
那Wide部分是怎么对低阶特征交叉做处理的呢?
Wide侧的输入是 raw input features或者transformed features
其中一种transformation是cross-product transformation,谷歌默默扔出如下公式:
ϕ
k
(
x
)
=
∏
i
=
1
d
x
i
c
k
i
c
k
i
∈
{
0
,
1
}
\phi_{k}(\mathbf{x})=\prod_{i=1}^{d} x_{i}^{c_{k i}} \quad c_{k i} \in\{0,1\}
ϕk(x)=i=1∏dxickicki∈{0,1}
看着花里胡哨, x i x_i xi是特征,那么多个特征连乘?那还叫低阶特征交叉吗?所谓低阶通常不应该是指两个特征交叉么?谷歌高冷地说,你没看到我还有个上标 c k i c_{ki} cki吗?哦,那我懂了, ϕ k ( x ) \phi_{k}(\mathbf{x}) ϕk(x)表示第k个组合特征,当基础特征 x i x_i xi属于第k个组合特征时,则 c k i = 1 c_{ki}=1 cki=1,否则为0。例如,我们可以设第k个组合 ϕ k ( x ) = x 3 ∗ x 8 \phi_{k}(\mathbf{x})=x_3*x_8 ϕk(x)=x3∗x8,只有当 x 3 x_3 x3和 x 8 x_8 x8都为1时,这个组合特征的取值才为1。谷歌给这种操作起了个牛逼的名字,叫Cross Product。
那你又要问了,这连乘式到底要取哪几个呢?每个组合特征该怎么设置呢?如果排列组合每种情况,那碰到稀疏数据,有些特征由于数据量过少没法有效训练到参数怎么办?谷歌给的说法是,Wide&Deep的Wide侧是需要比较由经验的人员帮忙设计这些连乘式的!也就是说要帮忙选取和设计组合特征 x 3 ∗ x 8 , x 1 ∗ x 7 x_3*x_8,x_1*x_7 x3∗x8,x1∗x7等等。所以说嘛这个模型还是有一定门槛的,如果你想要让模型自己设计组合特征,那可以去看看DeepFM的工作。
容易看出,左边的部分就是Deep,右边的那孤零零的部分就是wide,上面标着Cross Product的操作在上面已经说明了
2.2 Wide&Deep和DeepFM的区别
下图来自论文 https://arxiv.org/pdf/1804.04950v1.pdf
容易看到,两个模型除了低阶特征交叉处理不同之外(一个用Cross Product,一个用FM),还有一个重要的区别,DeepFM的Deep部分和FM部分共享了底下两层(Wide&Deep只使用了相同的原始特征,然后就分道扬镳了),这使得DeepFM可以同时从embedding向量中学习低阶和高阶的特征交叉,两部分结合得更加紧密写,这或许是DeepFm表现得更好的原因吧,谁又知道呢?
当然关于模型权重的计算,跟DeepFM一样,Wide&Deep也是用SGD就完事了。至此,Wide&Deep模型也就介绍完了。
从DeepCTR的代码实现上来说,DeepFM和Wide&Deep的区别好像就是多了一个FM的二阶部分(一阶部分Wide&Deep也是有的)。所以说这里它Wide&Deep就是纯用的原始特征,没有请教专家设计几个组合特征,而DeepFM则因为模型原因可以自己学习高低阶特征,并且低阶特征中包含了组合特征,且是端到端的学习。
三、Wide&Deep代码实战(以deepctr库为例,对比DeepFM代码)
- deepctr - wide&deep (浅梦)
- https://github.com/zhongqiangwu960812/AI-RecommenderSystem/blob/master/Rank/WideDeep/Wide%26Deep%20Model.ipynb (Miracle8070)
- https://github.com/ugirc/wechat_big_data_challenge_semi/blob/master/src/src_shwei/train/shwei_nn/semi_deepctr.py (DeepFM)
# Wide&Deep的forward函数
def forward(self, X):
sparse_embedding_list, dense_value_list = self.input_from_feature_columns(X, self.dnn_feature_columns,
self.embedding_dict)
# wide部分直接使用原始特征X(因为没有专家帮我构造组合特征,呜呜)
logit = self.linear_model(X)
# deep部分使用了原始特征X的embedding向量+dense特征
if self.use_dnn:
dnn_input = combined_dnn_input(sparse_embedding_list, dense_value_list)
dnn_output = self.dnn(dnn_input)
dnn_logit = self.dnn_linear(dnn_output)
logit += dnn_logit
y_pred = self.out(logit)
return y_pred
从DeepCTR的代码实现上来说,DeepFM和Wide&Deep的区别好像就是多了一个FM的二阶部分(一阶部分Wide&Deep也是有的)。所以说这里它Wide&Deep就是纯用的原始特征,没有请教专家设计几个组合特征,而DeepFM则因为模型原因可以自己学习高低阶特征,并且低阶特征中包含了组合特征,且是端到端的学习。
附:FM模型的公式: y ( x ) = w 0 + ∑ i = 1 n w i x i + ∑ i = 1 n ∑ j = i + 1 n ⟨ v i , v j ⟩ x i x j y(\mathbf{x})=w_{0}+\sum_{i=1}^{n} w_{i} x_{i}+\sum_{i=1}^{n} \sum_{j=i+1}^{n}\left\langle\mathbf{v}_{i}, \mathbf{v}_{j}\right\rangle x_{i} x_{j} y(x)=w0+∑i=1nwixi+∑i=1n∑j=i+1n⟨vi,vj⟩xixj,一阶+二阶
# DeepFM的forward函数
def forward(self, X):
sparse_embedding_list, dense_value_list = self.input_from_feature_columns(X, self.dnn_feature_columns,
self.embedding_dict)
# 对应模型图中FM层的addition(FM一阶部分,第一层作为输入)
logit = self.linear_model(X)
# 对应模型图中FM层的Inner Product(FM二阶部分,第二层作为输入)
if self.use_fm and len(sparse_embedding_list) > 0:
fm_input = torch.cat(sparse_embedding_list, dim=1)
logit += self.fm(fm_input)
if self.use_dnn:
dnn_input = combined_dnn_input(
sparse_embedding_list, dense_value_list)
dnn_output = self.dnn(dnn_input)
dnn_logit = self.dnn_linear(dnn_output)
logit += dnn_logit
y_pred = self.out(logit)
return y_pred
四、Wide&Deep常见面试题
问题1:DeepFM就是把Wide & Deep中的Wide部分改成了FM喽?
对!也不对!
- 两者对低阶特征交叉处理不同,一个Wide侧是Cross Product,一个Wide侧是FM
- 还有一点是,Wide&Deep两部分只使用了相同的原始特征,然后就分道扬镳了,Wide部分Cross Product出组合特征、Deep部分的Embedding层都是互不相关的。而DeepFM模型中两部分是共享底下两层的,embedding向量是共享的。
- 从DeepCTR的代码实现上来说,DeepFM和Wide&Deep的区别好像就是多了一个FM的二阶部分(一阶部分Wide&Deep也是有的)
问题2:Wide&Deep的Wide部分有什么缺陷?如何改进?
Wide&Deep的Wide侧是需要比较由经验的人员帮忙设计这些连乘式的!也就是说要帮忙选取和设计组合特征 x 3 ∗ x 8 , x 1 ∗ x 7 x_3*x_8,x_1*x_7 x3∗x8,x1∗x7等等。所以说嘛这个模型还是有一定门槛的,如果你想要让模型自己设计组合特征,那可以去看看DeepFM的工作。
DeepFM模型主要是针对Wide&Deep模型的Wide部分不具备自动的特征组合能力的缺陷进行改机的。