XGBoost 与 Spark 在广告排序中的应用

127 篇文章 14 订阅

文章来源: mp.weixin.qq.com/s/4i5O0QlKpWz......

背景

广告排序的核心问题是CTR预估,CTR预估的准确度,很大程度上决定了最终排序的质量。工业界目前用的比较多的是基于LR的线性策略,该方法的主要问题之一是需要人工大量的时间去挑选和组合特征,而使用树模型(tree model)则可以大大减轻这个工作量。

XGBoost是GBRT的一个工程实现,GBRT算法由多棵决策树构成,每一颗树都是从之前所有树的残差中来学习的,具有很好的性能,并且泛化性能较强。自从dmlc/XGBoost面世以来,已经越来越多的应用在各种机器学习问题的场合,当然也不乏广告排序中的CTR预估问题,并且从2015年的kaggle竞赛获奖情况来看,一半以上的获奖团队使用了XGBoost方法。

鉴于XGBoost优异的性能,蘑菇街广告排序很早就引入了XGBoost作为CTR预估策略,并且尝试了其分布式(spark)的实现,本文即从XGBoost的原理应用等方面来展开介绍。

XGBoost与ctr预估模型

目前广告排序的主要公式是 c ∗ b i d ,因此本文主要讨论广告算法排序的ctr预估问题。

我们采用机器学习上gradient boosted tree[1]的模型去解决广告算法排序的ctr预估问题。boosted tree的目标函数为:

上图是对于一个用户是否点击某广告的决策树森林(ensembled trees)的例子。给定样本 X1:”不常访问蘑菇街app的女性用户“看到一个“喜欢数为20000,售价为35元的裙子”。该样本时在上述ensemble trees中的权重为

在我们ctr预估模型中采用的损失函数类型采用了二分类的logistic函数,因此上述样本的预测ctr为:

为了精准的预测ctr,我们需要构建GBDT模型(gradient boosting decision tree)。首先定义损失函数为

X 1 :”不常访问蘑菇街app的女性用户“看到一个“喜欢数为20000,售价为35元的裙子”。该样本时在上述ensemble trees中的权重为 y 1 ¯ = ( 1) + ( 2) =1.0 +0.4 =1.4 y 1 ¯ = f ( t r e e 1 )+ f ( t r e e 2 ) = 1.0 + 0.4 = 1.4 。在我们ctr预估模型中采用的损失函数类型采用了二分类的logistic函数,因此上

其中

其中 Ω ( f ) 为模型复杂度,取决于决策树的深度和对于叶子节点的正则。将上述  公式根据泰勒公式展开,可以获得

其中 g i 和 h i 分别为损失函数 l ( y i , y ¯ ( t − 1 ) ) 的一阶和二阶偏导。

在迭代第 t 轮时,我们可以获得目标函数为

以上详细公式推导可以参见论文[2].

XGBoost较于其它机器学习包优势在于基本原理之外的实践细节的优化。其中对于决策树分裂点的选择就是是在训练损失值(信息熵)和正则化约束(剪枝)中寻找平衡点。其参考论文[3]中通过将数据分到有序桶中从而寻找队列中rank_n数值的方法,XGBoost在线性实践内对于某维度的特征进行排序,从而降低了分裂点的实践复杂度。此外,XGBoost还借鉴了随机森林的思路,除了基本的样本采样,构造每棵决策树的时候对于选用的样本特征进行了采样; 而且在boosting的过程中引入了学习率 λ ,在增加第t棵树时,通过当前学习率 λ ,降低已经构建好的前t-1棵树的权重w,  w = w ∗ λ。这种通过控制学习率和列采样的方法能有效的避免了过拟合和模型效果的优化。此外针对稀疏样本,不同于之前的相关工作,XGBoost还通过将常见的二叉树转化为三叉树,增加了对于缺失值的处理。此外在系统层面基于IO和CPU效率等方面XGBoost也有相当优秀的工作。

广告排序的应用

在蘑菇街的cpc广告的ctr预估模型中,我们使用的特征按照特征来源区分,主要分为三类:query, ad和context。分类见下表:

特征来源特征举例
query前台类目,搜索词等
ad商品特征,包括价格,标题,图片质量,销量,喜欢数等
context广告位置,时间因素等

在query类别中,除了图墙场景中使用的前台类目,我们使用的特征还包括搜索场景中的搜索词,以及对该短文本搜索词进行后处理的结果;在ad类别中,除了使用后台类目,原价,折扣价,图片,评论,描述等商品单一维度特征,还增加了若干统计特征,如各种维度的历史点击曝光数,喜欢数,销量,gmv等;在context类别,选用特征包括了广告位置和时间这两个bias因素。

考虑到GBDT模型能够很好的解决交叉特征,我们没有额外增加人为交叉特征;模型使用的特征中我们依然选用了离散特征,虽然考虑到gbdt通常只适用于连续特征,但是在树的规模足够大的情况下,对离散特征也会具有一定学习能力。我们选用的离散特征包括分类特征前台类目,商品各级类目等; 以及其它id类特征,如商品id, 文本id等。

训练样本预处理: 考虑到训练数据中负样本偏多,我们会对训练数据按照采样率 α 进行负样本采样,将正负样本比例控制在一定范围内。在GBDT中,单决策树的构造和树的融合会对预测结果产生较高bias,因此采用保序回归方法进行校验。此后将获得pred_ctr按照公式

进行采样校准。

XGBoost还提供了参数 early stopping rounds ,其作用是当训练损失在指定迭代数中趋于稳定时,训练会提前终止迭代。需要注意的是此终止参数参数不能设置太小,如果太小可能会由于采样不均匀等干扰因素导致训练不充分缺提前结束。

模型效果评估: 在GBDT模型中,除了计算特征和目标值之间的皮尔森相关性,我们还可以参考 特征重要性 指标来帮助我们进行筛选。该重要性通俗讲可以通过该特征在我们的决策树森林的结点中出现的次数进行衡量。

目前我们在图墙场景中遇到较多的挑战。图墙场景上用户的搜索意图不强烈,以“逛”为主,我们很难抽取出有用特征,特别是文本特征更难以被有效利用。在后续工作中我们会引入个性化特征以及点击反馈等来解决上述困难。

XGBoost分布式

分布式实现的两个主要问题:

分割点的确定

在XGBoost设计之初,就考虑了分布式的实现。树模型最重要的一个问题即是分割点的确定,XGBoost在单机的环境中,数据全部load进内存,feature已经按照值的大小排好序,采用一个叫做“exact greedy algorithm”算法,经过线性扫描,就可以快速的找到最佳的分割点;但是在分布式环境中,数据分布在各个节点,这种情况下,要找到最佳的分割点是很不容易的,XGBoost提供了一个近似算法来解决这个问题,近似算法的核心在于根据特征的分布来提供一组候选的分割点,至于如何保证候选分割集的有效性和理论上的完备性,不在本文的讨论范围,有兴趣的读者可以参考文献[4]。

容错

分布式环境中,多个节点共同工作,结果采用Allreduce的机制来同步,xgboost依赖dmlc/rabit来完成这个工作

rabit:可容错的Allreduce库

Allreduce是MPI提供的一个主要功能,但是MPI一般不是特别受到广泛欢迎,原因之一就是它本身不容错,但如果砍掉MPI的多余接口,只保留Allreduce和Broadcast,支持容错则简单很多。原因是Allreduce有一个很好的性质,每一个节点最后拿到的是一样的结果,这意味着我们可以让一些节点记住结果。当有节点挂掉重启的时候,可以直接向还活着的节点索要结果就可以了。

容错过程:

1、Node1在第二个checkpoint之后的第一次和第二次allreduce中间挂了

2、当Node1重启,它会调用LoadCheckPoint,这样可以从其他节点得到最近的一次CheckPoint

3、Node1从当前的CheckPoint开始跑,并进行第一次Allreduce,这时其他节点已经知道了结果并把结果告诉Node1

4、当Node1执行到第二个Allreduce,这时大家就已经完全同步上了

有了Allreduce容错机制和近似算法确定分割点,XGBoost算法可以运行在很多已知的集群上,如MPI,Yarn...

XGBoost on spark

由于spark等基于JVM平台的大数据处理系统应用越来越广泛,于2016.4月XGBoost推出了基于spark/Flink的XGBoost4J(XGBoost for JVM Platform)。

XGBoost4J的核心与XGBoost一样,分布式实现仍然采用rabit Allreduce,但是抽象了一套Java/Scala接口,供spark平台使用。

XGBoost-spark应用

XGBoost-spark在蘑菇街广告排序中的特征处理和参数选择与单机版本基本一致,在分布式环境中需要注意的几个问题:

1、numWorker参数应该与executor数量设置一致,executor-cores设置为1(笔者认为的最优化的配置)

2、在train的过程中,每个partition占用的内存最好限制在executor-memory的1/3以内,因为除了本来训练样本需要驻留的内存外,xgboost为了速度的提升,为每个线程申请了额外的内存,并且这些内存是JVM所管理不到的

3、对于需要在集群机器上共享的资源,比如字典/库文件等,spark提供了一套类似于hadoop distribute cached的机制来满足需求

XGBoost与LR的结合

看到这里,其实本文的主题已经结束了,这里是bonus。

XGBoost+LR结合的思想源于facebook的研究论文[5],使用树模型来做特征选择,最后用LR来输出CTR分数,充分利用了两种模型的优点,实践证明,XGBoost+LR离线评估和线上AB都优于单独XGBoost。除了论文中提供的方案带来的收益外,我们还将这种stacking的想法做了发挥,工程上单独抽取出LR层,这样做有如下优点:

1、对于一些类似于ID类的非连续特征,可以单独使用LR层来承载

2、事实上很多feature extraction 强大的模型稍作处理都可以作为LR层的输入,处理得当的话,LR还是很强大的

3、通过在LR层组合不同的特征来源,方便的做到“刻画”和“泛化”的结合,类似于deep and wide这样的思想

4、LR本身的优势,适合大规模并行,online learning算法成熟等等。。。

总结

本文首先简要介绍了XGBoost的原理和相比其他机器学习方法的优势,并以蘑菇街CPC广告中的CTR预估为例,介绍了XGBoost的应用,最后阐述了分布式实现的问题和在spark上应用的注意事项。

广告排序是计算广告的核心问题,未来我们会尝试更多的方案,更大的数据集,以取得更加好的效果。

  • 参考文献

    [1]: Greedy function approximation: a gradient boosting machine

    [2]: XGBoost: A Scalable Tree Boosting System(KDD16)

    [3]: A fast algorithm for approximate quantiles in high speed data streams [4]: XGBoost: A Scalable Tree Boosting System Supplementary Material [5]: Practical Lessons from Predicting Clicks on Ads at Facebook

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值