《Practical Lessons from Predicting Clicks on Ads at Facebook》
数字广告(didital advertising)是一个价值数十亿美元的产业,并且每年都在急剧增长。在大多数在线广告平台中,广告的投放是动态的,根据用户的兴趣来个性化投放。机器学习在计算候选广告对用户的预期效用(expected utility)方面发挥着核心作用,并以这种方式提高了市场效率。
Varian (论文 《Position auctions》)和 Edelman 等人(论文 《 Internet advertising and the generalized second price auction: Selling billions of dollars worth of keywords》)在 2007 年发表的开创性论文描述了由 Google 和 Yahoo! 开创的点击出价(bid per click)、点击扣费(pay per click)。同年,微软也在建立一个基于相同拍卖模型(论文《Predicting clicks: Estimating the click-through rate for new ads》)的sponsored search 市场。广告拍卖(auction)的效率取决于点击率预估的准确性(accuracy)和校准(calibration)。点击率预估系统需要健壮性(robust)和适应性(adaptive),并且能够从大量数据中学习。点击率预估系统是大多数在线广告系统的核心。Facebook 拥有超过 7.5 亿的日活用户、超过 100 万的活跃广告主,因此预估广告的点击率是一项具有挑战性的机器学习任务。论文 《Practical Lessons from Predicting Clicks on Ads at Facebook》分享了满足这些要求的、从真实世界数据执行的实验中得出的洞察(insight)。
在 sponsored search 广告中,user query 用于检索和 query 显式或者隐式匹配的候选广告。在 Facebook 中,广告不是与 query 相关,而是指定人口统计特性和兴趣的定向(targeting)。因此,当用户访问 Facebook 时,合格(eligible)的广告数量可能超过 sponsored search 搜索量。为了处理每个请求的大量候选广告(每当用户访问 Facebook 时都会触发广告请求),Facebook 将首先构建一系列计算代价递增的、级联(cascade)的 classifiers (即matching、ranking 等一系列模型)。在本文中,论文关注级联分类器最后阶段的点击率预估模型,即为最终候选广告集合生成预测的模型。
论文发现:将决策树与逻辑回归相结合的混合模型比这两种方法中的任何一个都高出 3%以上。这种提升对于整体系统性能有重大影响。许多基础的超参数会影响系统的最终预测性能。毫不意外,最重要的是拥有正确的特征:比其它特征,那些捕获有关用户历史信息和广告历史信息的特征占统治地位。一旦有了正确的特征和正确的模型(决策树加逻辑回归),其它因素就发挥了很小的作用(即使是很小的改进,在如此规模的任务中也很重要)。针对数据新鲜度(freshness)、学习率模式(schema)、数据采样而选择最佳处理方式会稍微改善模型,尽管改善的幅度远不如添加高价值特征、或者选择正确的模型。
论文从实验设置概述开始,然后评估不同的概率线性分类器(probabilistic linear classifiers)以及不同的在线学习算法。在线性分类的背景下,论文继续评估特征变换和数据新鲜度的影响。
受到实际经验教训的启发,尤其是在数据新鲜度和在线学习方面,论文提出了一个模型架构,该架构包含一个在线学习层(online learning layer),同时生成相当紧凑的模型。接下来描述了在线学习层所需的一个关键组件,即online joiner ,它是一种实验性的基础设施,可以生成实时训练数据(real-time training data)的实时流(live stream)。
最后,论文提出了用内存、计算时间、处理大量数据和准确性进行 tradeoff 的方法。包括为大规模 application 优化内存和延迟的使用方法,以及训练数据规模和准确性之间权衡的研究。
为了实现严格可控的实验,我们选取了 2013 年第四季度的任意一周,从而作为离线训练数据。我们将离线数据划分为训练集和测试集,并使用它们来模拟流式数据 (streaming data),从而进行在线训练和预估。论文中的所有实验都使用相同的训练集/测试集。
评估指标:由于我们最关心的是各个因素(factors)对于机器学习模型的影响,因此我们使用预估的准确性来评估,而不是与利润和收入直接相关的指标。在这里我们使用归一化熵( Normalized Entropy: NE)和校正(calibration)作为我们的主要评估指标。
归一化熵(更准确地讲,归一化交叉熵Normalized Cross-Entropy )等于每次曝光的平均对数损失除以背景熵 (background entropy)。
假设样本集合有 CTR 为
定义背景点击率(background CTR)为样本集合经验 CTR ,它的熵定义为背景熵:
背景熵衡量了样本集合的类别不平衡程度,也间接的衡量了样本集合的预测难度。
类别越不均衡预测难度越简单,因为只需要将所有样本预测为最大的类别即可取得非常高的准确率。
定义模型在样本集合熵的损失函数为:
每个样本的损失为交叉熵。
定义归一化熵 NE 为:模型在所有样本的平均损失函数除以背景熵。
需要除以
NE 相对损失函数的优势在于:NE 考虑了样本集预测的难易程度。在平均损失相同的情况下,样本集越不均衡则越容易预测,此时 NE 越低。
归一化熵可以用于计算相对信息增益(Relative Information Gain: RIG),其中 RIG = 1 - NE 。
校正(Calibration)是平均预估点击率和经验点击率的比值。换句话讲,它是期望点击次数和实际观察到点击次数的比值。calibration 是一个非常重要的指标,因为准确且校准良好的 CTR 预估对于在线竞价和拍卖的成功至关重要。calibration 和 1.0 的差异越小,模型越好。
注意,AUC 也是评估模型能力的一个很好的指标,但是 AUC 反应的模型对样本的排序能力:auc=0.8 表示 80% 的情况下,模型将正样本预测为正类的概率大于模型将负样本预测为正类的概率。
在现实环境中,我们期待预测是准确的,而不仅仅是获得最佳的排序,从而避免潜在的投放不足(under-delivery)、以及投放过度(over-delivery)。
NE 衡量的预估好坏并不隐式地反映 calibration 。例如,如果模型高估了 2 倍,然后我们使用一个全局的因子 0.5 来固定地校准:
因为校准不改变模型的排序能力,所以 AUC 保持不变。
因为校准后的 pCTR 分布与样本的标签分布距离更近,所以NE 会得到改善。
有关这些指标的深入研究,可以参考 《Predictive model performance: Offline and online evaluations》 。
这里我们展示了一个混合模型结构:boosted decision trees: BDT 和概率稀疏线性分类器(probabilistic sparse linear classifier)的拼接,如下图所示。其中输入特征通过 BDT 进行变换,每棵子树的输出都被视为稀疏线性分类器的离散输入特征。 BDT 已经被证明是非常强大的特征变换。
我们首先展示了决策树是非常强大的输入特征变换,可以显著提高概率线性分类器。
然后我们展示了更新鲜(fresher)的训练数据如何导致更准确的预估,这激发了使用在线学习方法来训练线性分类器的思想。
最后我们比较了两个概率线性分类器家族的许多在线学习变体。

有两种最简单的特征转换方式:
连续特征离散化:将连续特征的取值映射到一个个分散的分桶里,从而离散化。这里桶的数量和边界难以确定,通常有两种方法:
通过人工根据经验来设定分桶规则。
利用后续的分类器来显式的学习这个非线性映射,从而学习出有意义的分桶数量和边界。
离散特征交互:类似 FM 模型采用二路特征交互(或者更高阶)来学习高阶非线性特征。
对于连续特征可以先离散化之后再执行特征交互,如 kd 树就是典型的代表。
Boosted decisition tree:BDT 就是结合了上述两种方式的一个强大的特征提取器。对于 BDT,我们将每棵子树视为一个离散特征,其叶结点的编号为特征的取值并执行 one-hot 编码。
假设 BDT 有两棵子树,第一棵有 3 个叶结点,第二棵有2 个叶结点。则样本提取后有两个特征:第一个特征取值为 {1,2,3},第二个特征取值为 {1,2} 。假设某个样本被划分到第一棵子树的叶结点 2,被划分到第二棵子树的叶结点 1,则它被转换后的特征为:[0,1,0,1,0]。其中:前三项对应于第一个离散特征的 one-hot,后两项对应于第二个离散特征的 one-hot 。
我们使用的 BDT 为梯度提升树( Gradient Boosting Machine:GBM),其中使用了经典的 L2-TreeBoost 算法。在每次学习迭代中,都会创建一棵子树对残差进行建模。我们可以将基于 BDT 的变换理解为一种监督特征编码:
它将一组实值向量(real-valued vector)转换为一组二元向量(binary-valued vector)。
每棵子树从根节点到叶节点的遍历表示某些特征转换规则。
在转换后的二元向量上拟合线性分类器本质上是学习每个规则的权重。
我们进行了实验以显示将树特征作为线性模型输入的效果。我们对比了两种逻辑回归模型:一种具有树特征变换,另一种具有普通特征(未变换的)。我们还对比了一个 BDT 模型。对比结果如下表所示,可以看到:
树特征变换有助于将归一化熵降低 3.4% 以上。这是一个非常显著的提升。
有意思的是,单独使用 LR 和单独使用 Tree 模型具有相差无几的预测准确性(实际上 LR 稍微好一点),但是它们的组合使得准确性大幅上升。

点击率预估系统通常部署在数据分布随时间变化的动态环境中。我们研究了训练数据新鲜度(freshness)对于预测性能的影响。为此,我们在某一天训练一个模型并在连续几天内对其进行测试。我们为 BDT 模型、带tree-transformed 的逻辑回归模型进行实验。实验中,我们训练一天的数据,并评估连续六天中每一天的归一化熵。
结果如下图所示,指标是相对于最差的 NE 的比例(最差的 NE 发生在 Trees only 模型延迟 6 天时)。可以看到:
随着训练集和测试集之间延迟的增加,两种模型的预估准确性显著下降。
通过将每周训练改为每天训练,NE 可以减少大约 1% 。
这些发现表明:每天进行重新训练是值得的。

考虑数据新鲜度,我们需要用最新的样本更新模型。有两种更新策略:
每天用最新的数据重新训练模型。重新训练模型所需的时间各不相同,取决于训练样本的数量、子树的数量、每棵子树的叶节点数量、cpu、内存等因素。通常在大规模集群中可以在几个小时内完成训练。
每天或者每隔几天来训练特征提取器 BDT ,但是用最新的数据在线近乎实时地训练 LR 线性分类器。
为了最大限度地提高数据新鲜度,一种选择是在线训练线性分类器,即在带 label 的曝光信息到达时直接训练。这里我们评估了几种为基于 SGD 的逻辑在线学习设置学习率的方法。
per-coordinate 基于特征的学习率:在第
其中:
特征
特征
per-weight 维度加权学习率:在第
其中:
在广告场景中,这些特征在大多数情况下都没有取值,因此对应的权重很难有更新机会。
特征
特征
per-weight square root 基于权重开方的学习率:在第
global 全局学习率:在第
constant 常量学习率:在第
前三种方式针对每个特征都有不同的学习率,最后两种方式对所有特征采用相同的学习率。所有超参数都通过网格搜索来调优,最优值如下表所示。

我们将学习率下限设定为 0.00001 从而用于在线的 continuous learning 。我们使用上述学习率方案在相同数据集上训练和测试 LR 模型,实验结果如下图所示。可以看到:
per-coordinate 方法获得最好的表现,而 per-weight 效果最差。per-weight square root 和 constant 方案具有相似、但是稍差的效果。
全局学习率表现不佳,其主要原因是:每个特征上训练样本数量不平衡。
一些高频特征上(如:“是否男性” 特征)的样本数量较多,而另一些低频特征(如:“是否明星” )上的样本数量较少。在全局学习率策略下,低频特征学习率太快降低到很小的值,使得最优化难以收敛到最优点。
虽然 per-weight 策略解决了该问题,但是它仍然表现不佳。主要原因是:虽然它对低频特征的学习率控制较好,但是它对高频特征的学习率控制较差。它对所有特征的学习率都下降得太快,在算法收敛到最优点之前训练就过早终止了。这解释了为什么该方案是所有学习率方案中最差的。

如前所述,更新鲜的训练数据会提高预估准确性。这里我们介绍一个实验系统,该系统生成用于在线学习训练线性分类器的实时训练数据。我们将这个系统称作 online joiner ,因为它的关键操作是以在线方式将 label (是否点击)和训练数据(广告曝光)进行关联。
在线训练框架最重要的是为模型提供在线学习的标注样本。点击行为比较好标记,但是“不点击”行为难以标记。因为广告并没有一个“不点击”按钮来获取不点击的信息。因此,如果一个曝光在一个时间窗内未发生点击行为,则我们标记该次曝光是未点击的。
之所以要设定一个时间窗,是因为广告曝光和用户点击之间存在时间差。这里有两个原因:
给用户曝光一个广告后,用户不会立即点击。如:用户会简单浏览广告的内容再决定是否点击。对于视频类广告,用户甚至会观看完整视频之后再决定是否点击。
因此曝光事件和点击事件这两个事件存在时间差。
广告系统的曝光日志和点击日志通常都是分开的、独立的实时数据流。这两个数据流回传到在线训练系统可能并不是同步的,存在数据回传时间差。
这个等待时间窗口需要仔细调优:
如果窗口太长,那么会延迟实时训练数据,数据 freshness 较差。同时为了存储更长时间的曝光数据内存代价也较高。
如果窗口太短,那么会导致部分点击丢失,因为相应的曝光可能已经被标记为 no click 并移出内存。这会对点击覆盖率( click coverage)产生不利影响。其中点击覆盖率指的是成功关联曝光的点击占所有点击的比例。
因此,online joiner 必须在新近程度(recency)和点击覆盖率之间取得平衡。点击覆盖率低意味着实时训练集会有 bias:经验 CTR 略低于 ground truth 。这是因为如果等待时间足够长,那么标记为 no click 的部分曝光会被标记为 click。通过挑选合适的时长,可以降低经验的 CTR 偏差到百分之一以下,同时内存代价也可以接受。
Facebook 在线训练框架如下图所示:
用户浏览 Facebook 时向 Ranker 模块发送一个广告请求,请求中包含 request ID 。
Ranker 模块根据在线模型的预测结果,向用户返回一个广告,同时在曝光实时数据流中增加一条曝光日志。
如果用户点击广告,则前端打点系统上报点击事件,在后台点击实时数据流中增加一条点击日志。
通过 Oneline Joiner 模块实时获取最近一个时间窗的曝光、点击日志,并拼接样本特征来构造训练集。
Trainer 模块根据构造的训练集执行在线训练,训练好的模型部署到线上供 Ranker 模块使用。
这会形成一个数据闭环,使得模型能够捕捉到最新的数据分布。

在线训练需要增加对实时训练数据的异常保护。假设实时训练数据出现问题(如:前端打点上报出现异常、Online Joiner 工作异常等),导致大量的点击数据丢失。那么这批实时训练样本存在缺陷,它们的经验 CTR 非常低甚至为 0。如果模型去学习这样一批样本,则模型会被带偏:对任何测试样本,模型都会预测出非常低、甚至为零的点击率。
根据广告点击价值 eCPM = BID x pCTR,一旦预估点击率 pCTR 为零则广告的 eCPM 为零。那么这些广告几乎没有竞争力,竞争失败也就得不到曝光机会。因此需要增加实时训练数据的异常检测机制。如:一旦检测到实时训练数据的分布突然改变,则自动断开online trainer 和 online joiner 的连接。
子树的数量:在 GBDT-LR 模型中子树的数量越大模型表现越好,但是计算代价、内存代价越高。随着子树的增多,每增加一棵子树获得的效益是递减的。这就存在平衡:新增子树的代价和效益的平衡。
我们将子树的数量从 1 增加到 2000,并使用一整天的数据训练模型、第二天的数据测试模型性能。我们限制每棵子树的叶子不超过 12 个。和之前的实验类似,我们使用归一化熵 NE 作为评估指标。
实验如下图所示,其中 NE submodel0, NE submodel1 使用全量训练数据、不同的超参数来训练,而NE submodel2 使用 1/4 的训练数据。可以看到:
NE 随着子树数量的增加而下降,但是最后增加的1000棵子树获得的效益很低。几乎所有的 NE 改善都来自于前 500 棵子树,最后 1000 棵子树得到的 NE 下降不足 0.1% 。
NE submodel2 由于训练数据更少,使得模型在 1000 棵子树之后出现过拟合(NE 增加)。

特征的数量:特征数量是另一个模型属性,可以影响到估计准确性和计算性能之间的 tradeoff。特征越多模型表现越好,但是计算代价、内存代价越高。但是随着特征的增多,尤其是无效特征的增多,每增加一个特征获得的效益是递减的。这就存在平衡:新增特征的代价和效益的平衡。
为了更好地理解特征数量的影响,我们首先评估特征重要性。我们使用统计的 Boosting Feature Importance,有三种统计方法(如 XGBoolst/LightGBM ):
weight:特征在所有子树中作为分裂点的总次数。
gain:特征在所有子树中作为分裂点带来的损失函数降低总数。
cover:特征在所有子树中作为分裂点包含的总样本数。
通常情况下,少数特征贡献了大部分解释,而剩余特征仅具有微小的贡献。如下图所示,top 10 特征贡献了大于一半的重要性,最后 300 个特征贡献了不到 1% 的重要性。下图中,左轴给出了对数尺度的特征重要性,右轴给出了累计特征重要性。

基于这一发现,我们进一步试验仅保留 top10,top20,top50,top100,top200 重要性的特征,并评估模型性能的影响。实验结果如下,可以看到:归一化熵随着我们包含更多特征而具有类似的收益递减特性。

接下来我们将对历史特征(historica features)和上下文特征(contextual features)进行研究。出于数据敏感性和公司政策,我们无法透露我们使用的实际特征的详细信息。上下文特征可以是本地时间、星期几等,历史特征可以是广告累计的点击量等。
历史特征和上下文特征:BDT 模型中用到的特征分类两类:上下文特征和历史统计特征。
上下文特征:曝光广告的当前上下文信息。如:用户设备、用户所在页面的信息等等。
历史统计特征:广告的历史统计行为,或者用户的历史统计行为。如:广告的上周平均点击率,用户的历史平均点击率。
这里我们研究这两种类型的特征如何影响系统性能。
首先我们检查这两类特征的相对重要性。我们通过按重要性对所有特征进行排序,然后计算 top k 个重要特征中历史特征的百分比。结果如下所示,其中 Y 轴表示在 top k 特征中历史特征的占比。
可以看到:历史特征比上下文特征提供了更多的解释。按照重要性排序的 top 10 特征都是历史特征。在所有 top 20 特征中,只有 2 个上下文特征,而历史特征占据了 75% 。

为了更好地比较这两类特征,我们训练了两个仅包含上下文特征和历史特征的 BDT 模型,然后将这两个模型与所有特征的完整模型进行比较,结果如下表所示。我们再次验证,总体而言,历史特征比上下文特征发挥更大的作用。在仅有上下文特征的情况下,我们的 NE 损失了 4.5% 。相反,在仅有历史特征的情况下,我们的 NE 损失小于 1% 。
应该注意的是:上下文特征对于处理冷启动问题非常重要。对于新用户和新广告,上下文特征对于合理的点击率预估是必不可少的。

最后,我们在连续几周内评估仅有历史特征或仅有上下文特征的训练模型,以测试这两种类型特征对数据新鲜度的依赖性。实验结果如下图所示。可以看到:具有上下文特征的模型比具有历史特征的模型更依赖于数据新鲜度。这符合我们的直觉,因为历史特征描述了长期累计的用户行为,这比上下文特征要稳定得多。

Facebook 每天的广告曝光量非常大。即使是每个小时,数据样本也可能上亿。用于控制训练成本的常用技术是减少训练数据量。本节中,我们评估两种降采样技术,均匀降采样和负降采样。在每种情况下,我们训练一组包含 600 棵树的 boosted tree model ,并是使用 calibration 和 归一化熵来评估这些模型。
均匀降采样:所有样本都以同一个概率
我们评估了 0.001,0.01,0.1,0.5,1 这几种采样率。结果表明:更多的数据带来更好的模型。但是采用 10% 的训练样本相对于全量样本仅仅损失了 1%的预测能力,而训练代价降低一个量级。在该采样率下的 calibration 甚至没有性能下降。注意:calibration 越接近 1.0 越好。

负降采样:保留所有的正样本,仅负样本以概率
我们评估了 0.0001, 0.001, 0.01, 0.1 这几种采样率。可以看到:负采样率对训练模型的性能有显著影响。将负采样率设置为 0.025 可以实现最佳性能。

Re-Calibration :负降采样可以加快训练速度,改善模型能力。但是负采样中的训练数据分布和线上数据分布不一致,因此必须对模型进行校准。
假设采样之前样本集的平均 CTR 为 0.1% 。当执行采样率为 0.01 的负降采样之后,由于正样本数量不变、负样本数量降低到之前的 0.01 ,因此采样后的样本集的平均 CTR 为 10% 。此时需要校准模型,使得模型的预估平均 CTR 尽可能与线上的平均 CTR 一致。假设模型预估的结果为
其中
我们从 Facebook 广告数据的实验中提出了一些实践经验教训,这激发了用于点击率预估的有前途的混合模型架构。
数据新鲜度很重要,至少每天都值得重新训练。在本文中,我们进一步讨论了各种在线学习方案。我们还展示了允许生成实时训练数据的基础设施。
使用 BDT 转换实值输入特征显著提高概率线性分类器的预测准确性。这激发了一种混合模型架构,该架构将 BDT 和稀疏线性分类器拼接起来。
具有 per-coordinate 学习率的 LR 模型比其它正在研究的 LR SGD 学习率方案表现更好。
同时我们还描述了在大规模机器学习中优化内存和延迟的技巧:
我们提出了 BDT 的子树数量和准确性之间的 trade-off。保持较少的子树数量从而减少内存和计算量是有利的。
BDT 提供了一种通过特征重要性进行特征选择的便捷方法。可以激进地减少使用特征的数量,同时预测准确性只会略微下降。
我们分析了上下文特征和历史特征的效果。对于有历史特征的广告和用户,这些特征提供了比上下文特征更出色的预测性能。
最后,我们讨论了对训练数据进行降采样的方法,如均匀采样和负采样。