计算广告CTR预估系列(四)-Wide&Deep理论与实践

计算广告CTR预估系列(四)—Wide&Deep理论与实践

今天的主角是Wide & Deep Model,在推荐系统和CTR预估中都有应用。万字长文,墙裂推荐!

1. 名词解释

1.1 Memorization 和 Generalization

Google Wide&Deep论文中,通篇都是这两个词,必须搞懂是怎么回事!

这个是从人类的认知学习过程中演化来的。人类的大脑很复杂,它可以记忆(memorize)下每天发生的事情(麻雀可以飞,鸽子可以飞)然后泛化(generalize)这些知识到之前没有看到过的东西(有翅膀的动物都能飞)。

但是泛化的规则有时候不是特别的准,有时候会出错(有翅膀的动物都能飞吗)。那怎么办那,没关系,记忆(memorization)可以修正泛化的规则(generalized rules),叫做特例(企鹅有翅膀,但是不能飞)。

这就是Memorization和Generalization的来由或者说含义。

Wide&Deep Mode就是希望计算机可以像人脑一样,可以同时发挥memorization和generalization的作用。—Heng-Tze Cheng(Wide&Deep作者)

1.2 Wide 和 Deep

同样,这两个词也是通篇出现,究竟什么意思你明白了没?

其实,Wide也是一种特殊的神经网络,他的输入直接和输出相连。属于广义线性模型的范畴。Deep就是指Deep Neural Network,这个很好理解。Wide Linear Model用于memorization;Deep Neural Network用于generalization。

左侧是Wide-only,右侧是Deep-only,中间是Wide & Deep:

1.3 Cross-product transformation

Wide中不断提到这样一种变换用来生成组合特征,也必须搞懂才行哦。它的定义如下:

k表示第k个组合特征。i表示输入X的第i维特征。C_ki表示这个第i维度特征是否要参与第k个组合特征的构造。d表示输入X的维度。那么到底有哪些维度特征要参与构造组合特征那?这个是你之前自己定好的,在公式中没有体现。

饶了一大圈,整这么一个复杂的公式,其实就是我们之前一直在说的one-hot之后的组合特征:仅仅在输入样本X中的特征gender=female和特征language=en同时为1,新的组合特征才为1。所以只要把两个特征的值相乘就可以了。

Cross-product transformation 可以在二值特征中学习到组合特征,并且为模型增加非线性

2. Wide & Deep Model

Memorization:

之前大规模稀疏输入的处理是:通过线性模型 + 特征交叉。所带来的Memorization以及记忆能力非常有效和可解释。但是Generalization(泛化能力)需要更多的人工特征工程。

Generalization:

相比之下,DNN几乎不需要特征工程。通过对低纬度的dense embedding进行组合可以学习到更深层次的隐藏特征。但是,缺点是有点over-generalize(过度泛化)。推荐系统中表现为:会给用户推荐不是那么相关的物品,尤其是user-item矩阵比较稀疏并且是high-rank(高秩矩阵)

两者区别:

Memorization趋向于更加保守,推荐用户之前有过行为的items。相比之下,generalization更加趋向于提高推荐系统的多样性(diversity)。

Wide & Deep:

Wide & Deep包括两部分:线性模型 + DNN部分。结合上面两者的优点,平衡memorization和generalization。

原因:综合memorization和generalizatio的优点,服务于推荐系统。相比于wide-only和deep-only的模型,wide & deep提升显著(这么比较脸是不是有点大。。。)

2.1 推荐系统

2.1.1 介绍

推荐系统分为两种: CF-Based(协同过滤)、Content-Based(基于内容的推荐)

协同过滤(collaborative filtering)就是指基于用户的推荐,用户A和B比较相似,那么A喜欢的B也可能喜欢

基于内容推荐是指物品item1和item2比较相似,那么喜欢item1的用户多半也喜欢item2

2.1.2 线性模型

大规模的在线推荐系统中,logistic regression应用非常广泛,因为其简单、易扩展、可解释性。LR的输入多半是二值化后的one-hot稀疏特征。Memorization可以通过在稀疏特征上来实现,比如: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。

推荐系统可以看成是一个search ranking问题,根据query得到items候选列表,然后对items通过ranking算法排序,得到最终的推荐列表。Wide & Deep模型是用来解决ranking问题的。

如果仅仅使用线性模型:无法学习到训练集中没有的query-item特征组合。

Embedding-based Model可以解决这个问题。

2.1.3 Embedding-Based

FM和DNN都算是这样的模型,可以在很少的特征工程情况下,通过学习一个低纬度的embedding vector来学习训练集中从未见过的组合特征。

FM和DNN的缺点在于:当query-item矩阵是稀疏并且是high-rank的时候(比如user有特殊的爱好,或item比较小众),很难非常效率的学习出低维度的表示。这种情况下,大部分的query-item都没有什么关系。但是dense embedding会导致几乎所有的query-item预测值都是非0的,这就导致了推荐过度泛化,会推荐一些不那么相关的物品。

相反,linear model却可以通过cross-product transformation来记住这些exception rules,而且仅仅使用了非常少的参数。

总结一下:

线性模型无法学习到训练集中未出现的组合特征;

FM或DNN通过学习embedding vector虽然可以学习到训练集中未出现的组合特征,但是会过度泛化。

Wide & Deep Model通过组合这两部分,解决了这些问题。

2.1.4 工作流程

总的来说, 推荐系统 = Retrieval + Ranking

推荐系统工作流程如下:

想象这样一个实际情况:我们打开Google APP store,首页展示给我们一些APP,我们点击或者下载或者购买了其中一个APP。在这样一个流程中,推荐系统是如何工作的那?

我们对比上面的图一点点来说:

Query:
当我们打开APP Store的时候,就产生了一次Query,它包含两部分的特征:User features, contextual features。UserFeatures包括性别、年龄等人口统计特征,ContextualFeatures包括设备、时间等上下文特征。

Items:

APP store接着展示给我们一系列的app,这些app就是推荐系统针对我们的Query给出的推荐。这个也被叫做impression

User Actions:

针对推荐给你的任何一个APP,我们都可以点击、下载、购买等操作。也就是说推荐给你的APP,你产生了某种行为。这不正是我们的最终目的吗!

Logs:

查询、展示列表、操作会被记录到logs中作为训练数据给Learner来学习。

Retrieval:

假如让你来想一个最简单的推荐系统,针对这一次Query,来给出推荐列表。你能想到的最简单,最暴力的做法是什么那?

给数据库中所有的APP都打一个分数,然后按照分数从高到低返回前N个(比如说前100个)

但是有个问题,这样数据库中的APP实在是太多了,为了保证响应时间,这样做太慢了!Retrieval就是用来解决这个问题的。它会利用机器学习模型和一些人为定义的规则,来返回最匹配当前Query的一个小的items集合,这个集合就是最终的推荐列表的候选集。

Ranking:

今天的主角Wide&Deep Model就是用来做这个事情的啦。

前面Learner学习到了一个Model,利用这个Model对Retrieval给出的候选集APP打分!并按照打分从高到低来排序,并返回前10个APP作为最终的推荐结果展示给用户。

Retrieval system完了之后,就是Ranking system。Retrieval减小了候选items池,Ranking system要做的就是对比当前的Query,对Candidate pool里面的所有item打分!

得分score表示成P(y|x), 表示的是一个条件概率。y是label,表示user可以采取的action,比如点击或者购买。x表示输入,特征包括:

User features(年龄、性别、语言、民族等)

Contextual features(上下文特征:设备,时间等)

Impression features(展示特征:app age、app的历史统计信息等)

2.2 Wide Part

Wide Part其实是一个广义的线性模型

使用特征包括:

raw input 原始特征

cross-product transformation 组合特征

接下来我们用同一个例子来说明:你给model一个query(你想吃的美食),model返回给你一个美食,然后你购买/消费了这个推荐。 也就是说,推荐系统其实要学习的是这样一个条件概率:P(consumption | query, item)

Wide Part可以对一些特例进行memorization。比如AND(query=”fried chicken”, item=”chicken fried rice”)虽然从字符角度来看很接近,但是实际上完全不同的东西,那么Wide就可以记住这个组合是不好的,是一个特例,下次当你再点炸鸡的时候,就不会推荐给你鸡肉炒米饭了。

2.3 Deep Part

Deep Part通过学习一个低纬度的dense representation(也叫做embedding vector)对于每一个query和item,来泛化给你推荐一些字符上看起来不那么相关,但是你可能也是需要的。比如说:你想要炸鸡,Embedding Space中,炸鸡和汉堡很接近,所以也会给你推荐汉堡。

Embedding vectors被随机初始化,并根据最终的loss来反向训练更新。这些低维度的dense embedding vectors被作为第一个隐藏层的输入。隐藏层的激活函数通常使用ReLU。

2.4 模型训练

原始的稀疏特征,在两个组件中都会用到,比如:

在训练的时候,根据最终的loss计算出gradient,反向传播到Wide和Deep两部分中,分别训练自己的参数。也就是说,两个模块是一起训练的,注意这不是模型融合。

Wide部分中的组合特征可以记住那些稀疏的,特定的rules

Deep部分通过Embedding来泛化推荐一些相似的items

Wide模块通过组合特征可以很效率的学习一些特定的组合,但是这也导致了他并不能学习到训练集中没有出现的组合特征。所幸,Deep模块弥补了这个缺点。

另外,因为是一起训练的,wide和deep的size都减小了。wide组件只需要填补deep组件的不足就行了,所以需要比较少的cross-product feature transformations,而不是full-size wide Model。

论文中的实现:

训练方法是用mini-batch stochastic optimization。

Wide组件是用FTRL(Follow-the-regularized-leader) + L1正则化学习。

Deep组件是用AdaGrad来学习。

3. 系统实现

3.1 训练数据生成

请大家一定格外的关注训练数据到底是什么?这对于理解推荐系统到底是怎么回事很重要。

先给出结论:

一次展示中的一个Item就是一条样本。

样本的label要根据实际的业务需求来定,比如APP Store中想要提高APP的下载率,那么就以这次展示的这个Item中用户有没有下载,作为label。下载了label为1,否则为0.

说白了,模型需要预测,在当前Query的条件下,对于这个Item,用户下载的条件概率。

离散特征map成id

过滤掉出现次数少于设定阈值的离散特征取值,然后把这些全部map成一个ID。离散特征取值少,就直接编号。多的话可能要Hash

连续特征通过分位数规范化到[0,1]

先把所有的值分成n份,那么属于第i部分的值规范化之后的值为 (i - 1)/(n - 1)。

3.2 模型训练

Deep部分使用的特征:

连续特征

Embedding后的离散特征,Item特征

Wide部分使用的特征:

Cross Product Transformation生成的组合特征

但是,官方给出的示例代码中,Wide部分还使用了离散特征(没有one-hot)。也有大佬说不用特征交叉效果也很好,这个大家在实际项目中就以实验为准吧。

每当有新的数据到达的时候,就要重新训练。如果每次都从头开始会非常耗时,Google给出的解决办法是:实现了warm-starting system, 它可以用之前模型的embeddings 和 线性模型的weights来初始化新的模型。

Embedding维度大小的建议:

Wide&Deep的作者指出,从经验上来讲Embedding层的维度大小可以用如下公式来确定:

n是原始维度上特征不同取值的个数;k是一个常数,通常小于10.

3.3 线上使用

模型被部署之后。每一次请求,服务器会收到一系列的app候选集(从app retrival system输出的)以及user features(用于为每一个app打分)。然后,模型会把APP按照score排序,并展示给user,按照这个顺序展示。score就是对于wide & deep模型的一次 forward pass。为了控制每一次request响应时间在10ms内,引入了并行化技术。将app候选集分成多个小的batches,并行化预测score。

4. 适用范围

Wide & Deep Model适用于输入非常稀疏的大规模分类或回归问题。比如推荐系统、search、ranking问题。

输入稀疏通常是由离散特征有非常非常多个可能的取值造成的,one-hot之后维度非常大。

5. 优缺点

缺点:Wide部分还是需要人为的特征工程。

优点:实现了对memorization和generalization的统一建模。

6.代码实践

代码放到github上了: https://github.com/gutouyu/ML_CIA/tree/master/Wide%26Deep

数据集:https://archive.ics.uci.edu/ml/machine-learning-databases/adult

代码主要包括两部分:Wide Linear Model 和 Wide & Deep Model。

数据集长这样,最后一行是label,预测收入是否超过5万美元,二分类问题。

6.1 Wide Linear Model

离散特征处理分为两种情况:

知道所有的不同取值,而且取值不多。

不知道所有不同取值,或者取值非常多。

原始连续特征

规范化到[0,1]的连续特征

组合特征/交叉特征

组装模型:这里主要用了离散特征 + 组合特征

训练 & 评估

运行截图

6.2 Wide & Deep Model

Deep部分用的特征: 未处理的连续特征 + Embedding(离散特征)

在Wide的基础上,增加Deep部分:

离散特征embedding之后,和连续特征串联。

组合Wide & Deep

训练 & 评估

运行结果

Reference

Wide & Deep Learning for Recommender Systems

Google AI Blog Wide & Deep Learning: Better Together with TensorFlow https://ai.googleblog.com/2016/06/wide-deep-learning-better-together-with.html

TensorFlow Linear Model Tutorialhttps://www.tensorflow.org/tutorials/wide

TensorFlow Wide & Deep Learning Tutorialhttps://www.tensorflow.org/tutorials/wide_and_deep

TensorFlow 数据集和估算器介绍 http://developers.googleblog.cn/2017/09/tensorflow.html

absl https://github.com/abseil/abseil-py/blob/master/smoke_tests/sample_app.py

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180521G1TR4F00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券