传统的搜索引擎排序(Ranking)问题,通常会涉及到很多的排序策略。这些策略根据不同的特征,在不同的适用范围中起作用。因此,一个传统的排序算法,至少涉及到两方面的内容:策略的制定,以及不同策略的组合。策略的组合需要考虑策略分析适用的特征,以及相应策略的适用情况。根据这些内容,通过人工或者半机器半人工的方式组合起来,才能组成一个可堪使用的排序算法。

  和自然语言处理中遇到的情况一样,随着数据量的增加,使用人工的方式做策略的组合,会变得越来越困难。因此,将机器学习引入搜索引擎排序问题,也就是相当自然的事情了。在排序问题中使用的机器学习算法,被称为 Learning to Rank (LTR) 算法,或者 Machine-Learning Rank (MLR) 算法。

  LTR 算法通常有三种手段,分别是:Pointwise、Pairwise 和 Listwise。Pointwise 和 Pairwise 类型的 LTR 算法,将排序问题转化为回归分类或者有序分类问题。Listwise 类型的 LTR 算法则另辟蹊径,将用户查询(Query)所得的结果作为整体,作为训练用的实例(Instance)。

  LambdaMART 是一种 Listwise 类型的 LTR 算法,它基于 LambdaRank 算法和 MART (Multiple Additive Regression Tree) 算法,将搜索引擎结果排序问题转化为回归决策树问题。MART 实际就是梯度提升决策树(GBDT, Gradient Boosting Decision Tree)算法。GBDT 的核心思想是在不断的迭代中,新一轮迭代产生的回归决策树模型拟合损失函数的梯度,最终将所有的回归决策树叠加得到最终的模型。LambdaMART 使用一个特殊的 Lambda 值来代替上述梯度,也就是将 LambdaRank 算法与 MART 算法加和起来。考虑到 LambdaRank 是基于 RankNet 算法的,所以在搞清楚 LambdaMART 算法之前,我们首先需要了解 MART、RankNet 和 LambdaRank 是怎么回事。

MART 算法

MART,即多重增量回归树(Multiple Additive Regression Tree)有许多名字:

  • MART - 多重增量回归树(Multiple Additive Regression Tree)
  • GBDT - 梯度渐进决策树(Gradient Boosting Decision Tree)
  • GBRT - 梯度渐进回归树(Gradient Boosting Regression Tree)
  • TreeNet - 决策树网络(Tree Net)

这些名字的含义都一样,都是一个意思。

从这些名字,我们可以看出 MART 的一些特征:

  1. 使用决策树来预测结果;
  2. 用到的决策树有很多个;
  3. 每个树都比之前的树改进一点点,逐渐回归、拟合到真实结果。

实际上,这三点就是 Boosting 思想的精髓了。Boosting 思想源自 Kearns 和 Valiant 的提问,并最终从 Robert Schapire 在 1990 年的论文 The Strength of Weak Learnablity 中对上述问题明确的回答发展起来。

Boosting(渐进)思想

Boosting 思想,尝试通过不断迭代弱模型(Weak Learner),通过叠加弱模型的方式,渐进地逼近真实情况,起到足以预测真实值的强模型的作用。显而易见,Boosting 思想至少需要解决两个问题:

  1. 如何保证每一次迭代都对解决问题有所帮助,或者说如何确定迭代步骤中拟合的方向?
  2. 如何将每一次迭代产生的弱模型有效地叠加起来?

下面,我们通过 AdaBoost(Adaptive Boosting,自适应渐进法)来回答这两个问题。

AdaBoost

AdaBoost 是 Yoav Freund 和 Robert Schapire 提出的机器学习算法。两人因为该算法获得了 2003 年的哥德尔奖。

AdaBoost 是一种用于分类的算法,它的运行过程大致可以理解如下:

  1. 制作一个弱分类器(实际是一个决策树),去拟合实际情况,我们将它记录为 WL1
  2. 运行 WL1,记录分类错误的那些样本。接下来,赋予这些被错误分类的样本比较高的权重,进行第二次拟合,得到新的弱分类器 WL2
  3. 依次运行 WL1 - WL2,记录分类错误的那些样本。接下来,赋予这些被错误分类的样本比较高的权重,进行第三次拟合,得到新的弱分类器 WL3
  4. 依次运行 WL1 - WL2 - WL3,如此迭代……

上图来自 Pattern Recognition and Machine Learning 一书的 660 页,讲述的是运用 Boosting 思想进行分类的过程。

蓝色和红色的圆圈,代表两类样本,圆圈的大小代表当前该点的权重;绿色的线条代表训练既得分类器模型;虚线表示当前训练新增的分类器模型。

可以看到,在不断的迭代过程中,每一次迭代,分类器都会关注之前区分错误的那些样本点,进行有针对性的处理。因此,在进行到 150 次迭代之后(m=150m=150),最终叠加起来的模型已经非常细致,足够将红蓝两种类别细致地区分开来了。

整个过程,用数学符号表达如下(PRML Page 658):

在这里:

  • w(k)nwn(k) 表示一个 nn 元向量,向量中的每一个元素都对应训练集中的一个样本点;向量中元素的值,就是所对应样本点在第 kk 次迭代中的权重。
  • yk(x)yk(x) 是根据上述权重计算出来的第 kk 次迭代的模型。
  • αkαk 是第 kk 次迭代的模型的权重。
  • YM(x)YM(x) 是根据上述 MM 个弱分类器加权求和得到的最终分类器。

最开始的时候,每个样本点的权重都一致。随着算法不断迭代,被错误分类的样本,权重不断加强,与此同时被正确分类的样本,权重不断减弱。可以想象,越往后,算法越关注那些容易被分错的样本点,从而最终解决整个问题。

现在,我们至少可以从 AdaBoost 的角度回答上一小节的两个问题了:

  1. AdaBoost 通过调整样本的权值,来确定下一轮迭代中弱模型的拟合方向:提升分类错误的样本的权值,降低分类正确的样本的权值。
  2. AdaBoost 用一个「加法模型」,将每一轮迭代得到的弱模型组合叠加起来,得到一个有效的强模型。

MART 的数学原理

MART 是一种 Boosting 思想下的算法框架,它的目标是寻找强模型 f(x)f(x) 满足:

 

f^(x)=arg maxf(x)E[L(y,f(x))∣∣x]f^(x)=arg maxf(x)E[L(y,f(x))|x]

 

和 AdaBoost 一样,训练之后的 MART 模型也是一个加法模型,形式如下:

f^(x)=f^M(x)=m=1Mfm(x)f^(x)=f^M(x)=∑m=1Mfm(x)


这里:

 

  • f^=f^M:RdRf^=f^M:Rd↦R 是模型的目标函数;
  • xRdx∈Rd 是样本点,它包含 dd 个特征的值;
  • f^(x)Rf^(x)∈R 是预测值;
  • MM 是训练过程中迭代的次数,也就是模型中回归决策树的数量;
  • fm:RdRfm:Rd↦R 是模型训练过程中得到的弱模型(也就是回归决策树)。

那么,关于 MART 的 Boosting,我们还剩下一个回答,即:如何保证每一次迭代都对解决问题有所帮助,或者说如何确定迭代步骤中拟合的方向。接下来的分析,我们就来解决这个问题。

假设我们已经迭代了 mm 次,得到了 mm 颗决策树。我们将这 mm 颗决策树的和记作 f^m(x)=mi=1fi(x)f^m(x)=∑i=1mfi(x),于是,第 m+1m+1 轮拟合的目标

 

δf^m+1=f^m+1f^m=fm+1(1)(1)δf^m+1=f^m+1−f^m=fm+1

 

现在我们要求这个 δf^m+1δf^m+1。我们引入损失函数

 

L=L((x,y),f)=L(y,f(x)∣∣x)L=L((x,y),f)=L(y,f(x)|x)

 

来描述预测函数 ff 的预测结果 y=f(x)y∗=f(x) 与真实值 yy 的差距。那么,我们的目的是要在进行第 m+1m+1 轮拟合之后,预测值与真实情况的差距会减小,即

 

δLm+1=L((x,y),f^m+1)L((x,y),f^m)<0δLm+1=L((x,y),f^m+1)−L((x,y),f^m)<0

 

考虑到

 

δLm+1L((x,y),f^m)f^mδf^m+1,δLm+1≈∂L((x,y),f^m)∂f^m⋅δf^m+1,

 

若取

 

δf^m+1=gim=L((x,y),f^m)f^m,(2)(2)δf^m+1=−gim=−∂L((x,y),f^m)∂f^m,

 

则必有 δLm+1<0δLm+1<0。因此,这个 δf^m+1δf^m+1 就是 fm+1fm+1 拟合的目标;也就是说,fm+1fm+1 要拟合这样一个训练集:

 

{i=1,2,,N∣∣∣(xi,L((xi,yi),f^m(xi))f^m(xi))}{i=1,2,…,N|(xi,−∂L((xi,yi),f^m(xi))∂f^m(xi))}

 

式 22 描述的正是损失函数(泛函) LL 的梯度。亦即,循环迭代中,模型每次拟合的目标都是损失函数的梯度。这就是算法被称为「梯度渐进」的原因。

决策树实际上将样本空间划分成了若干区域,并对每个划分区域赋上预测值。假设 fmfm 划分而成的区域是 RmRm,预测值则是 γmγm。那么,我们有

fm(x)=hm(x;Rm,γm),fm(x)=hm(x;Rm,γm),


也就是

f^(x)=m=1Mfm(x)=m=1Mhm(x;Rm,γm).f^(x)=∑m=1Mfm(x)=∑m=1Mhm(x;Rm,γm).

 

那么,MART 的每一步也就是要解优化问题:

hm(x;Rm,γm)=arg minR,γi=1N(gimF(xi;R,γ))2,()(⋆)hm(x;Rm,γm)=arg minR,γ∑i=1N(−gim−F(xi;R,γ))2,


其中 FF 是一棵回归决策树。

 

现在我们引入一个非常小的正数 ηη,称为「学习度」或者「收缩系数」。如果,我们在每轮迭代中的预测结果前,乘上这么一个学习度;亦即我们将第 m+1m+1 轮拟合的目标,从 gim−gim 调整为 ηgim−η⋅gim。这样一来,我们每次拟合的目标,就变成了损失函数梯度的一部分。由于 δL<0δL<0 仍然成立,经过多次迭代之后,模型依然可以得到一个很好的结果。但是,与引入学习度之前的情况相比较,每次拟合像是「朝着正确的方向只迈出了一小步」。这种 Shrinkage(缩减),主要是为了防止「过拟合」现象。

小结

MART 是一种 Boosting 思想下的算法框架。它通过加法模型,将每次迭代得到的子模型叠加起来;而每次迭代拟合的对象都是学习率与损失函数梯度的乘积。这两点保证了 MART 是一个正确而有效的算法。

MART 中最重要的思想,就是每次拟合的对象是损失函数的梯度。值得注意的是,在这里,MART 并不对损失函数的形式做具体规定。实际上,损失函数几乎只需要满足可导这一条件就可以了。这一点非常重要,意味着我们可以把任何合理的可导函数安插在 MART 模型中。LambdaMART 就是用一个 λλ 值代替了损失函数的梯度,将 λλ 和 MART 结合起来罢了。

Lambda

Lambda 的设计,最早是由 LambdaRank 从 RankNet 继承而来。因此,我们先要从 RankNet 讲起。

RankNet 的创新

Ranking 常见的评价指标都无法求梯度,因此没法直接对评价指标做梯度下降。

RankNet 的创新之处在于,它将不适宜用梯度下降求解的 Ranking 问题,转化为对概率的交叉熵损失函数的优化问题,从而适用梯度下降方法。

RankNet 的终极目标是得到一个带参的算分函数:

 

s=f(x;w).s=f(x;w).

 

于是,根据这个算分函数,我们可以计算文档 xixi 和 xjxj 的得分 sisi 和 sjsj

 

si=f(xi;w)sj=f(xj;w),si=f(xi;w)sj=f(xj;w),

 

然后根据得分计算二者的偏序概率

 

Pij=P(xixj)=exp(σ(sisj))1+exp(σ(sisj))=11+exp(σ(sisj)),Pij=P(xi⊳xj)=exp⁡(σ(si−sj))1+exp⁡(σ(si−sj))=11+exp⁡(−σ(si−sj)),

 

再定义交叉熵为损失函数

 

Lij=P¯ijlogPij(1P¯ij)log(1Pij)=12(1Sij)σ(sisj)+log{1+exp(σ(sisj))},Lij=−P¯ijlog⁡Pij−(1−P¯ij)log⁡(1−Pij)=12(1−Sij)σ(si−sj)+log⁡{1+exp⁡(−σ(si−sj))},

 

进行梯度下降

wkwkηLwk.wk→wk−η∂L∂wk.

 

再探梯度

这里每条横线代表一条文档,其中蓝色的表示相关的文档,灰色的则表示不相关的文档。在某次迭代中,RankNet 将文档的顺序从左边调整到了右边。于是我们可以看到:

  • RankNet 的梯度下降表现在结果的整体变化中是逆序对的下降:13 → 11
  • RankNet 的梯度下降表现在单条结果的变化中,是结果在列表中的移动趋势(图中黑色箭头)
  • 我们通常更关注前几条文档的排序情况,因此我们会期待真正的移动趋势如图中红色箭头所示

那么问题就来了:我们能不能直接定义梯度呢?

LambdaRank

现在的情况是这样:

  • RankNet 告诉我们如何绕开 NDCG 等无法求导的评价指标得到一个可用的梯度;
  • 上一节我们明确了我们需要怎样的梯度;
  • 梯度(红色箭头)反应的是某条结果排序变化的趋势和强度;
  • 结果排序最终由模型得分 ss 确定。

于是,我要扼住 Lijsi∂Lij∂si 的咽喉!

先看看 RankNet 的梯度

Lwk=(i,j)PLijwk=(i,j)PLijsisiwk+Lijsjsjwk,∂L∂wk=∑(i,j)∈P∂Lij∂wk=∑(i,j)∈P∂Lij∂si∂si∂wk+∂Lij∂sj∂sj∂wk,


注意有下面对称性

Lijsi={12(1Sij)σ(sisj)+log{1+exp(σ(sisj))}}si=12(1Sij)σ(sisj)σ1+exp(σ(sisj))=Lijsj.∂Lij∂si=∂{12(1−Sij)σ(si−sj)+log⁡{1+exp⁡(−σ(si−sj))}}∂si=12(1−Sij)σ(si−sj)−σ1+exp⁡(σ(si−sj))=−∂Lij∂sj.

 

于是我们定义

λij=defLijsi=Lijsj,λij=def∂Lij∂si=−∂Lij∂sj,


考虑有序对 (i,j)(i,j),有 Sij=1Sij=1,于是有简化

λij=defσ1+exp(σ(sisj)),λij=def−σ1+exp⁡(σ(si−sj)),


在此基础上,考虑评价指标 ZZ(比如 NDCG)的变化

λij=defσ1+exp(σ(sisj))ΔZij.λij=def−σ1+exp⁡(σ(si−sj))⋅∣ΔZij∣.

 

对于具体的文档 xixi,有

λi=(i,j)Pλij(j,i)Pλij.λi=∑(i,j)∈Pλij−∑(j,i)∈Pλij.

 

也就是说:每条文档移动的方向和趋势取决于其他所有与之 label 不同的文档。

现在回过头来,看看我们做了什么?

  • 分析了梯度的物理意义;
  • 绕开损失函数,直接定义梯度。

当然,我们可以反推一下 LambdaRank 的损失函数:

 

Lij=log{1+exp(σ(sisj))}ΔZij.Lij=log⁡{1+exp⁡(−σ(si−sj))}⋅∣ΔZij∣.

 

LambdaMART

现在的情况变成了这样:

  • MART 是一个框架,缺一个「梯度」;
  • LambdaRank 定义了一个「梯度」。

让他们在一起吧!于是,就有了 LambdaMART。

LambdaMART 的优点

LambdaMART 有很多优点,取一些列举如下:

    • 直接求解排序问题,而不是用分类或者回归的方法;
    • 可以将 NDCG 之类的不可求导的 IR 指标转换为可导的损失函数,具有明确的物理意义;
    • 可以在已有模型的基础上进行 Continue Training;
    • 每次迭代选取 gain 最大的特征进行梯度下降,因此可以学到不同特征的组合情况,并体现出特征的重要程度(特征选择);
    • 对正例和负例的数量比例不敏感。
posted on 2017-05-01 10:12  sxron  阅读(1510)  评论(0)    收藏  举报