CTR 预测理论(五):集成学习之Boosting家族(AdaBoost+GBDT)

1. Boosting 方法的基本思想

提升方法基于这样一种思想:对于一个复杂任务来说,将多个专家的判断进行 适当(按照一定权重) 的综合(例如线性组合加法模型)所得出的判断,要比其中任何一个专家单独的判断好

历史上,Kearns 和 Valiant 首先提出了“强可学习(strongly learnable)”和“弱可学习(weekly learnable)”的概念,指出在 概率近似正确(probably approximately correct,PAC) 学习的框架中:

  1. 一个概念(概率规律)如果存在一个多项式的学习算法能够学习它(通过建模抽象拟合),并且正确率很高,那么就称这个概念是强可学习的;
  2. 一个概念如果存在一个多项式的学习算法能够学习它,但是学习的正确率仅比随机猜测略好,那么就称这个概念是弱可学习的

同时,后来 Schapire 证明强在PAC学习的框架下,一个概念是强可学习的充分必要条件是这个概念是弱可学习的。这样一来,问题就转化为了,在算法训练建模中,如果已经发现了 “弱可学习算法”(即当前分类效果并不优秀,甚至仅仅比随机预测效果要好),就有可能将其boosting(提升)为强可学习算法,这其中最具代表性的方法就是 AdaBoosting(AdaBoosting algorithm)

提升方法就是从弱学习算法出发,反复学习,得到一系列弱分类器(基本分类器),然后组合这些弱分类器,构成一个强分类器。大多数的提升方法都是改变训练数据的概率分布(训练数据的权重分布)

2. 提升方法的两个关键要素

对于提升方法来说,有两个非常重要的问题

  1. 在每一轮如何改变训练数据的权值或概率分布,修改的策略是什么?
  2. 如何将弱分类器组合成一个强分类器?

这2个问题是所有 Boosting 方法都要考虑和解决的问题,这里以 AdaBoost 为例,讨论 AdaBoost 的策略

  1. 提高那些被前一轮弱分类器错误分类的样本的权值,而降低那些被正确分类样本的权值。 这样一来,那些被分错的数据,在下一轮就会得到更大的关注。所以,分类问题被一系列的弱分类器 “分而治之”;
  2. 对弱分类器的组合,AdaBoost采取加权多数表决的方法。即加大分类误差率小的弱分类器的权值,使其在表决中起较大作用,减小分类误差率大的弱分类器的权值,使其在表决中起较小的作用。

3. 前向分步算法

在开始学习AdaBoost算法之前,我们需要先了解前向分步算法思想。实际上,AdaBoost算法是模型为加法模型、损失函数为指数函数、学习算法为前向分步算法时的二类分类学习算法

3.1 加法模型(aditive model)

加法模型是一种线型模型, f ( x ) = ∑ m = 1 M β m b ( x ; γ m ) f(x)=\sum_{m=1}^M\beta_mb(x;\gamma_m) f(x)=m=1Mβmb(x;γm),其中, b ( x ; γ m ) b(x;\gamma_m) b(x;γm)为基函数, γ m \gamma_m γm为基函数的参数, β m \beta_m βm为基函数的系数(权重)。
在给定训练数据及损失函数 L ( y , f ( x ) ) L(y,f(x)) L(y,f(x))的条件下,学习加法模型 f ( x ) f(x) f(x)成为经验风险极小化(即损失函数极小化)问题:
m i n β m , γ m ∑ i = 1 N L ( y i , ∑ m = 1 M β m b ( x i ; γ m ) ) min_{\beta_m,\gamma_m}\sum_{i=1}^{N}L(y_i,\sum_{m=1}^{M}\beta_m b(x_i;\gamma_m)) minβm,γmi=1NL(yi,m=1Mβmb(xi;γm))

即同时考虑N个样本在整个线性模型组中的损失函数的极小值,通常这是一个十分复杂的优化问题(求极值问题),想要一步到位求出最优解特别困难。前向分步算法(forward stagewise algorithm)求解这一优化问题的思想是:

因为学习的是加法模型(线性模型),如果能够从前向后,每一步只学习一个基函数 b ( x ; γ m ) b(x;\gamma_m) b(x;γm)及其系数 β m \beta_m βm,逐步逼近优化目标函数式
m i n β m , γ m ∑ i = 1 N L ( y i , ∑ m = 1 M β m b ( x i ; γ m ) ) min_{\beta_m,\gamma_m}\sum_{i=1}^{N}L(y_i,\sum_{m=1}^{M}\beta_m b(x_i;\gamma_m)) minβm,γmi=1NL(yi,m=1Mβmb(xi;γm))
那么就可以极大简化优化的复杂度。具体地,每步之选哦优化如下损失函数:
m i n β m , γ m ∑ i = 1 N L ( y i , β m b ( x i ; γ m ) ) min_{\beta_m,\gamma_m}\sum_{i=1}^{N}L(y_i,\beta_m b(x_i;\gamma_m)) minβm,γmi=1NL(yi,βmb(xi;γm))
每次只要考虑一个基函数及其系数即可。

有一点要注意,前向分步的思想和贝叶斯估计有类似的地方:

  • 它们都假设每一步之间的基函数和系数是独立不相关的(在贝叶斯估计中这叫独立同分布),也因为这一假设才可以把原始的全局最优解求解等价为分步的子项求解过程。
  • 但是这种假设会丢失一部分精确度,即每一步之间的依赖关联会被丢弃。

而前向分步算法的思想就是不求一步到位,而是逐步逼近最优解,通过分步求得每一步的最优解来逼近全局最优解。我个人觉得这和SGD梯度下降的求最优思想是一样的

3.2 算法策略

和其他统计机器学习模型一样,前向分布算法的策略也同样是:经验风险最小化。如果在模型中加入了penalty惩罚项,则可以演进为结构风险最小化

3.3 前向分步算法

给定训练数据集 T = ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x N , y N ) T={(x_1,y_1), (x_2,y_2), \dots, (x_N,y_N)} T=(x1,y1),(x2,y2),,(xN,yN), x i ∈ χ ⊆ R n x_i \in \chi \subseteq R^n xiχRn, y i ∈ Y = { − 1 , + 1 } y_i \in Y = \{-1, +1\} yiY={1,+1},损失函数 L ( y , f ( x ) ) L(y, f(x)) L(y,f(x)) 和基函数的集合 b ( x ; γ ) b(x; \gamma) b(x;γ),学习加法模型 f ( x ) f(x) f(x) 的前向分步算法如下:

  1. 初始化 f 0 ( x ) = 0 f_0(x)=0 f0(x)=0
  2. m = 1 , 2 , 3 , … , M m = 1, 2, 3, \dots, M m=1,2,3,,M (M代表基函数个数)
    (a) 在上一步得到的最有基函数的基础上,极小化本次单个基函数的损失函数: ( β m , γ m ) = a r g   m i n β , γ ∑ i = 1 N L ( y i , f m − 1 ( x i ) + β m b ( x ; γ m ) ) (\beta_m, \gamma_m) = arg\ min_{\beta, \gamma}\sum_{i=1}^{N}L(y_i, f_{m-1}(x_i) + \beta_m b(x;\gamma_m)) (βm,γm)=arg minβ,γi=1NL(yi,fm1(xi)+βmb(x;γm)),得到本轮最优基函数参数 β m , γ m \beta_m, \gamma_m βm,γm
    (b) 更新(线性累加基函数) f m ( x ) = f m − 1 ( x ) + β m b ( x ; γ m ) f_m(x) = f_{m-1}(x) + \beta_mb(x; \gamma_m) fm(x)=fm1(x)+βmb(x;γm)
  3. 得到最终加法模型 f ( x ) = f M ( x ) = ∑ m = 1 M β m b ( x ; γ m ) f(x) = f_M(x) = \sum_{m=1}^{M}\beta_mb(x; \gamma_m) f(x)=fM(x)=m=1Mβmb(x;γm)。这样,前向分步算法将同时求解从m=1到M所有的参数 β m , γ m \beta_m, \gamma_m βm,γm的全局最优解问题简化为逐次求解各个 β m , γ m \beta_m, \gamma_m βm,γm的局部最优化问题。

4. AdaBoost算法

4.1 算法过程

假设给定一个二类分类的训练数据集(adaboost不限于二类分类)

T = ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯   , ( x N , y N ) T = {(x_1, y_1),(x_2, y_2),\cdots,(x_N, y_N)} T=(x1,y1),(x2,y2),,(xN,yN)

其中,每个样本点由实例与标记组成。实例 x i ∈ χ ⊆ R n x_i \in \chi \subseteq R^n xiχRn,标记 y i ∈ Y = { − 1 , + 1 } y_i \in Y = \{-1, +1\} yiY={1,+1} χ \chi χ是实例空间, Y Y Y是标记集合。AdaBoost利用以下算法,从训练数据集中学习一系列弱分类器或基本分类器,并将这些弱分类器线性组合成一个强分类器。

  1. 初始化训练数据的权值分布(N代表样本数量):
    D 1 = ( w 11 , ⋯   , w 1 i , ⋯   , w 1 N ) ,   i = 1 , 2 , ⋯   , N D_1 = (w_{11}, \cdots, w_{1i}, \cdots,w_{1N}),\ i =1,2,\cdots,N D1=(w11,,w1i,,w1N), i=1,2,,N

    注:(初始等概率分布体现了最大熵原理,在没有任何先验知识的前提下作等概率假设是最合理的)。这一步假设数据集具有均匀的权值分布,即每个训练样本在基本分类器的学习中作用相同,这一假设保证第一步能够在原始数据上学习基本分类器 G 1 ( x ) G_1(x) G1(x)

  2. 假设训练轮次为M(直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数),则对 m = 1 , 2 , ⋯   , M m = 1, 2, \cdots, M m=1,2,,M
    a. 使用具有权值分布 D m D_m Dm的训练数据集(对应本轮权值分布的数据集)学习,得到本轮次的基本分类器: G m ( x ) : χ → { − 1 , + 1 } G_m(x): \chi \rightarrow \{-1, +1\} Gm(x):χ{1,+1}
    b. 计算 G m ( x ) G_m(x) Gm(x)在本轮训练数据集上的分类误差率(权重误差函数):
    e m = ∑ i = 1 N P ( G m ( x i ) ≠ y i ) = ∑ i = 1 N w m i I ( G m ( x i ) ≠ y i ) e_m = \sum_{i=1}^{N}P(G_m(x_i) \ne y_i) = \sum_{i=1}^{N}w_{mi}I(G_m(x_i) \ne y_i) em=i=1NP(Gm(xi)̸=yi)=i=1NwmiI(Gm(xi)̸=yi)
    c. 根据本轮的弱分类器对数据集的分类误差计算 G m ( x ) G_m(x) Gm(x)的模型系数:
    α m = 1 2 l o g 1 − e m e m , \alpha_m = \frac{1}{2}log\frac{1-e_m}{e_m}, αm=21logem1em
    代表了本轮得到的弱分类器的重要程度。
    由左式可知,当 e m ≤ 1 2 e_m\leq\frac{1}{2} em21时, α m ≥ 0 \alpha_m \geq 0 αm0,并且 α m \alpha_m αm随着 e m e_m em的减小而增大,所以在本轮分类误差率越小的基本分类器在最终分类器中的作用越大。
    d. 更新下一轮训练数据集的权值分布
    D m + 1 = ( w m + 1 , 1 , ⋯   , w m + 1 , i , ⋯   , w m + 1 , N ) D_{m+1} = (w_{m+1,1},\cdots,w_{m+1,i}, \cdots, w_{m+1,N}) Dm+1=(wm+1,1,,wm+1,i,,wm+1,N)
    w m + 1 , i = w m i Z m e x p ( − α m y i G m ( x i ) ) ,   i = 1 , 2 , ⋯   , N w_{m+1,i} = \frac{w_{mi}}{Z_m}exp(-\alpha_m y_i G_m(x_i)),\ i = 1,2,\cdots,N wm+1,i=Zmwmiexp(αmyiGm(xi)), i=1,2,,N
    这里, Z m Z_m Zm是规范化因子:
    Z m = ∑ i = 1 N w m i e x p ( − α m y i G m ( x i ) ) Z_m = \sum_{i=1}^{N}w_{mi}exp(-\alpha_m y_i G_m(x_i)) Zm=i=1Nwmiexp(αmyiGm(xi))
    它使得 D m + 1 D_{m+1} Dm+1成为一个概率分布(每一轮的权值总和都为1, ∑ i = 1 N w m i = 1 \sum_{i=1}^{N}w_{mi}=1 i=1Nwmi=1)。

    注:更新训练数据的权值分布为下一轮作准备。 w m + 1 , i w_{m+1,i} wm+1,i式子可以写成:
    w m + 1 , i = { w m i Z m e − α m , G m ( x i ) = y i w m i Z m e α m , G m ( x i ) ≠ y i w_{m+1,i}=\begin{cases} \frac{w_{mi}}{Z_m}e^{-\alpha_m},& G_m(x_i)=y_i \\ \frac{w_{mi}}{Z_m}e^{\alpha_m},& G_m(x_i) \neq y_i \end{cases} wm+1,i={Zmwmieαm,Zmwmieαm,Gm(xi)=yiGm(xi)̸=yi
    由此可知,被基本分类器 G m ( x ) G_m(x) Gm(x)误分类样本的权值得以扩大,而被正确分类样本的权值却在下一轮得以缩小。 两相比较,误分类样本的权值被放大了 e 2 α m e^{2\alpha_m} e2αm倍,因此误分类样本在下一轮学习中起更大作用。不改变所给的训练数据本身,而不断改变训练数据权值的分布,使得训练数据在基本分类器的学习中起不同的作用,一次优化一个弱分类模型,或者理解为一次优化全局复杂问题中的一次子问题(分而治之)。

    注: G m ( x ) G_m(x) Gm(x) 在加权的训练数据集上的分类误差率是被 G m ( x ) G_m(x) Gm(x) 误分类样本的权值之和,注意,权重误差函数关注的是本轮数据集的权重(概率)分布,而不关注弱分类器内部的参数。即我们对本轮高概率分布(重点关注的数据)的错误会给与更大的惩罚,这样就体现了模型 Adding 组合过程中根据权重误差进行模型组合选择的策略了.

  3. 构建基本分类器的线性组合:
    f ( x ) = ∑ m = 1 M α m G m ( x ) f(x)=\sum_{m=1}^{M}\alpha_m G_m(x) f(x)=m=1MαmGm(x)
    得到最终分类器:
    G ( x ) = s i g n ( f ( x ) ) = s i g n ( ∑ m = 1 M α m G m ( x ) ) G(x)=sign(f(x))=sign(\sum_{m=1}^{M} \alpha_m G_m(x)) G(x)=sign(f(x))=sign(m=1MαmGm(x))
    线性组合 f ( x ) f(x) f(x)实现M个基本分类器的加权表决。系数 α m \alpha_m αm表示了基本分类器 G m ( x ) G_m(x) Gm(x)的重要性。

    注:可以看到,在每轮的训练中,训练样本的权值分布不断在变动,同时

    1. 权值分布对本轮的弱分类器在最终线性分类器组合中重要程度起正比例作用;
    2. 对下一轮的样本权值调整起反比例作用

注:传统的 AdaBoost 只能用于二分类,现在已经出现了可以用于回归于多分类的变体。
AdaBoost 可以看作是 boosting + 指数损失函数的采用加和函数策略的一种组合,其损失函数指定为指数损失函数 l o s s = e x p ( − y i f ( x i ) ) loss = exp(-y^i f(x^i)) loss=exp(yif(xi)),boosting 也可以组合其他损失函数如平方损失等,但这将不再是 AdaBoost 而是其他 boosting 变体,而到了梯度特征更是支持任意可导损失函数,如GBDT的损失函数只需函数具备一阶导,以为采用的是梯度下降,而 XGBoost 做 GBDT 的一种高效实现,则进一步衍化为支持任意可求一阶、二阶导的损失函数,包括logistic loss function. hinge loss function等,也同样支持自定义损失函数。

CTR 预测理论(五):集成学习之Boosting家族(AdaBoost+GBDT)_第1张图片

4.2 AdaBoost 推导

Adaboost可以看出是加法模型、损失函数为指数损失函数、学习算法为前向分布算法时的二分类学习方法。此外,之后要介绍的GBDT也可以看出是加法模型。

下面进行证明:

前向分布分布算法学习的是加法模型,当基函数为基本分类器时,该加法模型等价于Adaboost的最终分类器。 H ( x ) = ∑ t = 1 T α t h t ( x ) H({\bf x}) = \sum_{t=1}^T \alpha_t h_t({\bf x}) H(x)=t=1Tαtht(x)

4.2.1 指数损失函数

首先证明前向分布算法的损失函数是指数损失函数 L ( y , F ( x ) ) = exp ⁡ ( − y F ( x ) ) L(y, F({\bf x})) = \exp(-yF({\bf x})) L(y,F(x))=exp(yF(x)) 时,其学习的具体操作等价于Adaboost算法学习的具体操作。

假设经过t – 1轮迭代前向分步算法已经得到:
f t − 1 ( x ) = f t − 2 ( x ) + α t − 1 h t − 1 ( x ) = α 1 h 1 ( x ) + ⋯ + α t − 1 h t − 1 ( x ) f_{t-1}({\bf x}) = f_{t-2}({\bf x}) + \alpha_{t-1}h_{t-1}({\bf x}) = \alpha_{1}h_1({\bf x}) + \cdots + \alpha_{t-1}h_{t-1}({\bf x}) ft1(x)=ft2(x)+αt1ht1(x)=α1h1(x)++αt1ht1(x)

则在第t轮迭代应该寻找最优的 α t , h t \alpha_t, h_t αt,ht 使得指数损失最小即 ( α t , h t ) = arg ⁡ min ⁡ α t , h t ∑ i = 1 N L ( y i , f t − 1 ( x i ) + α t h t ( x ) ) (\alpha_t, h_t) = \arg\min_{\alpha_t,h_t} \sum_{i=1}^N L\left(y_i, f_{t-1}({\bf x_i}) + \alpha_t h_t({\bf x})\right) (αt,ht)=argminαt,hti=1NL(yi,ft1(xi)+αtht(x))

从而得到 f t ( x ) = f t − 1 ( x ) + α t h t ( x ) f_{t}({\bf x}) = f_{t-1}({\bf x}) + \alpha_{t}h_t({\bf x}) ft(x)=ft1(x)+αtht(x)。而指数损失最小可以写为:

(3-3) ( α t , h t ) = arg ⁡ min ⁡ α t , h t ∑ i = 1 N exp ⁡ ( − y i ( f t − 1 ( x i ) + α t h t ( x ) ) ) = arg ⁡ min ⁡ α t , h t ∑ i = 1 N D t , i exp ⁡ ( − y i α t h t ( x ) ) (\alpha_t, h_t) =\mathop{\arg\min}_{\alpha_t,h_t} \sum_{i=1}^N \exp\left(-y_i(f_{t-1}({\bf x_i}) + \alpha_th_t({\bf x}))\right) \\ =\mathop{\arg\min}_{\alpha_t,h_t} \sum_{i=1}^N D_{t,i}\exp\left( -y_i\alpha_th_t({\bf x})\right)\tag{3-3} (αt,ht)=argminαt,hti=1Nexp(yi(ft1(xi)+αtht(x)))=argminαt,hti=1NDt,iexp(yiαtht(x))(3-3)

其中 D t i = E r r o r ( t − 1 , i ) = exp ⁡ ( − y i f t − 1 ( x i ) ) D_{ti} = Error_{(t-1,i)} = \exp(-y_if_{t-1}({\bf x_i})) Dti=Error(t1,i)=exp(yift1(xi)) 与当前的优化目标无关,只与之前的有关,因此为指数损失函数。

4.2.2 基分类器求解和权重推导

接着证明使得式子3-3达到最小的 α t ∗ \alpha_t^* αt h t ∗ ( x ) h_t^*({\bf x}) ht(x) 就是Adaboost算法得到的 α t \alpha_t αt h t ( x ) h_t({\bf x}) ht(x)

求解3-3可以分为两步,首先求 h t ( x ) h_t({\bf x}) ht(x),对于任意的 α t > 0 \alpha_t \gt 0 αt>0,使 3-3 最小的 h t ( x ) h_t(x) ht(x) 由下式得到:

h t ∗ ( x ) = arg ⁡ min ⁡ h ∑ i = 1 N D t , i I ( y i ≠ h ( x ) ) h_t^*({\bf x}) = \mathop{\arg\min}_h \sum_{i=1}^ND_{t,i}I(y_i\ne h({\bf x})) ht(x)=argminhi=1NDt,iI(yi̸=h(x))

其中 D t , i = exp ⁡ ( − y i f t − 1 ( x i ) ) D_{t,i}= \exp(-y_if_{t-1}(\bf x_i)) Dt,i=exp(yift1(xi))

这样就得到了基分类器 h t ∗ ( x ) h_t^*({\bf x}) ht(x),而该分类器就是Adaboost算法的基本分类器 h t ( x ) h_t({\bf x}) ht(x),因为它是第 t 轮加权训练数据分类误差率最小的基本分类器。

接下来求 α t \alpha_t αt, 式在3-3中:
(3-4) ∑ i = 1 N D t , i exp ⁡ ( − y i α t h t ( x ) ) = ∑ y i = h t ( x ) D t , i e − α + ∑ y i ≠ h t ( x ) D t , i e α = e − α ∑ i = 1 N D t , i + ( e α – e − α ) ∑ i = 1 N D t , i I ( y i ≠ h t ( x i ) ) \sum_{i=1}^N D_{t,i}\exp\left( -y_i\alpha_th_t({\bf x})\right) = \sum_{y_i=h_t(\bf x)}D_{t,i} e^{-\alpha} + \sum_{y_i\ne h_t(\bf x)}D_{t,i}e^{\alpha} \\ =e^{-\alpha}\sum_{i=1}^ND_{t,i} + (e^{\alpha} – e^{-\alpha})\sum_{i=1}^N D_{t,i}I(y_i\ne h_t({\bf x_i})) \tag{3-4} i=1NDt,iexp(yiαtht(x))=yi=ht(x)Dt,ieα+yi̸=ht(x)Dt,ieα=eαi=1NDt,i+(eαeα)i=1NDt,iI(yi̸=ht(xi))(3-4)

最后一个变换可以认为是第一项多加了不相等时候的 e − α e^{-\alpha} eα, 因此在第二项的时候减去。1-8 对 α \alpha α 求导,并使导数为 0,得到使得 3-3 最小的 α t \alpha_t αt

α t = 1 2 ln ⁡ ( 1 – ϵ t ϵ t ) \alpha_t = \frac{1}{2} \ln(\frac{1 – \epsilon_t }{\epsilon_t}) αt=21ln(ϵt1ϵt)

其中 ϵ t \epsilon_t ϵt 为分类误差率

ϵ t = ∑ i = 1 N D t , i I ( y i ≠ h t ( x ) ) ∑ i = 1 N D t , i = ∑ i = 1 N D ~ t , i I ( h t ( x i ) ≠ y i ) \epsilon_t = \frac{\sum_{i=1}^N D_{t,i}I(y_i\ne h_t({\bf x}))}{\sum_{i=1}^N D_{t,i}} = \sum_{i=1}^N \tilde D_{t,i}I(h_t(x_i) \ne y_i) ϵt=i=1NDt,ii=1NDt,iI(yi̸=ht(x))=i=1ND~t,iI(ht(xi)̸=yi)

可以看出和之前更新 α t \alpha_t αt 一致。

最后来看每一轮样本的权值更新,由 f t ( x ) = f t − 1 ( x ) + α t h t ( x ) f_{t}({\bf x}) = f_{t-1}({\bf x}) + \alpha_{t}h_t({\bf x}) ft(x)=ft1(x)+αtht(x) D t , i = exp ⁡ ( − y i f t − 1 ( x i ) ) D_{t,i}= \exp(-y_if_{t-1}(\bf x_i)) Dt,i=exp(yift1(xi)) 可得:

D t + 1 , i = exp ⁡ ( − y i f t ( x i ) ) = exp ⁡ ( − y i ( f t − 1 ( x i ) + α t h t ( x i ) ) = D ( t , i ) exp ⁡ ( − α t y i h t ( x i ) ) D_{t + 1,i} = \exp(-y_if_{t}(\bf x_i))\\ = \exp(-y_i( f_{t-1}({\bf x_i}) + \alpha_{t}h_t({\bf x_i}))\\ = D_{(t,i)}\exp(- \alpha_{t}y_{i}h_t({\bf x_i}))\\ Dt+1,i=exp(yift(xi))=exp(yi(ft1(xi)+αtht(xi))=D(t,i)exp(αtyiht(xi))

这与之前的Adaboost的样本权值更新公式相比,只差规范化因子,因而等价。

5. AdaBoost 总结

到这里 Adaboost 就写完了,前面有一个没有提到,就是弱学习器的类型。理论上任何学习器都可以用于Adaboost.但一般来说,使用最广泛的Adaboost弱学习器是决策树和神经网络。对于决策树,Adaboost 分类用了 CART 分类树,而 Adaboost 回归用了 CART 回归树,也因此,Adaboost tree 也是一种针对数据进行数据空间划分的策略(对比 LR 是建模拟合数据模型)。

这里对Adaboost算法的优缺点做一个总结。

Adaboost的主要优点有:

  1. Adaboost作为分类器时,分类精度很高;
  2. 在Adaboost的框架下,可以使用各种回归分类模型来构建弱学习器,非常灵活;
  3. 作为简单的二元分类器时,构造简单,结果可理解;
  4. 不容易发生过拟合;

Adaboost的主要缺点有:

  1. 对异常样本敏感,异常样本在迭代中可能会获得较高的权重,影响最终的强学习器的预测准确性。

示例:可参考陈航《统计机器学习》 p 140 p_{140} p140示例。

6. GBDT

GBDT全称为:Gradient Boosting Decision Tree,即梯度提升决策树。可以理解为梯度 + 提升 + 决策树

在介绍GBDT之前,先介绍比较简单的提升树(Boosting Decision Tree)

6.1 提升树

提升树实际上就是加法模型和前向分布算法,然后以CART决策树为基学习器。

可以表示为决策树的前向分布算法
F 0 ( x ) = 0 F t ( x ) = F t − 1 ( x ) + h t ( x ) , t = 1 , 2 , ⋯   , T F T ( x ) = ∑ t = 1 T h t ( x ) F_0({\bf x}) = 0\\ F_t({\bf x}) = F_{t-1}({\bf x}) + h_t({\bf x}), t=1,2,\cdots ,T\\ F_T({\bf x}) = \sum_{t=1}^Th_t({\bf x}) F0(x)=0Ft(x)=Ft1(x)+ht(x),t=1,2,,TFT(x)=t=1Tht(x)

在前向分布算法的第t步,给定当前模型 F t − 1 ( x ) F_{t−1}(x) Ft1(x),需要求解
h t ∗ ( x ) = arg ⁡ min ⁡ h t ∑ i = 1 N L ( y i , F t − 1 ( x ) + h t ( x ) ) h_t^*({\bf x}) = \mathop{\arg\min}_{h_t} \sum_{i=1}^NL(y_i, F_{t-1}({\bf x}) + h_t({\bf x})) ht(x)=argminhti=1NL(yi,Ft1(x)+ht(x))

得到第 t 棵树 F t ( x ) F_t(x) Ft(x)。针对不同问题的提升树学习方法,主要区别在于使用的损失函数不同。比如平方误差损失函数的回归问题,用指数损失函数的分类问题,以及用一般损失函数的问题。

采用平方损失函数时,有:
L ( y , F t − 1 ( x ) + h t ( x ) ) = ( y – F t − 1 ( x ) – h t ( x ) ) 2 = ( r – h t ( x ) ) 2 L\left(y, F_{t-1}({\bf x}\right) + h_t({\bf x})) =\left(y – F_{t-1}({\bf x} ) – h_t({\bf x})\right)^2\\ =(r – h_t({\bf x}))^2 L(y,Ft1(x)+ht(x))=(yFt1(x)ht(x))2=(rht(x))2

其中 r = y – F t − 1 ( x ) r = y – F_{t-1}({\bf x}) r=yFt1(x) 称为 残差(Residual)。因此,对回归树的提升树算法来说,只需要简单的拟合当前模型的残差即可。注意这里的是回归树。

因此回归问题的提升树算法可以描述如下:

输入: 训练集 D a t a = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯   , ( x N , y N ) } , y i ∈ { + 1 , − 1 } Data =\{({\bf x_1},y_1),({\bf x_2},y_2),\cdots,({\bf x_N},y_N)\}, y_i \in\{+1, -1\} Data={(x1,y1),(x2,y2),,(xN,yN)},yi{+1,1};

过程:

初始化 F 0 ( x ) = 0 F_0({\bf x}) = 0 F0(x)=0

for t = 1 to T do

\quad 计算残差 r t i = y i – F t − 1 ( x ) ,   i = 1 , 2 , ⋯   , N r_{ti} = y_i – F_{t-1}({\bf x}) , \ i=1,2,\cdots,N rti=yiFt1(x), i=1,2,,N

\quad 拟合残差得到一个回归树: h t ( x ) h_t({\bf x}) ht(x)

\quad 更新 F t ( x ) = F t − 1 ( x i ) + h t ( x ) F_t({\bf x}) = F_{t-1}({\bf x_i}) + h_t({\bf x}) Ft(x)=Ft1(xi)+ht(x)

得到加法模型 F ( x ) = ∑ t = 1 T h t ( x ) F({\bf x}) = \sum_{t=1}^T h_t({\bf x}) F(x)=t=1Tht(x)

该算法可以用下面的图表示:

CTR 预测理论(五):集成学习之Boosting家族(AdaBoost+GBDT)_第2张图片

对比 GBDT 来说,该算法可以说是修改样本的”label”,而AdaBoost则是修改样本的权重。

例子

继续搬出之前的决策树中的例子

x 1 2 3 4 5 6 7 8 9 10
y 5.56 5.70 5.91 6.40 6.80 7.05 8.90 8.70 9.00 9.05

第一轮计算后,我们算出(计算过程看决策树那章)
h 1 ( x ) = { 6.24 , x ≤ 6.5 8.91 , x > 6.5 h_1(x) = \begin{cases} 6.24, & x\le 6.5 \\ 8.91, & x \gt 6.5 \\ \end{cases} h1(x)={6.24,8.91,x6.5x>6.5

可以算出残差(比如x=1就是5.56 – 6.24 = -0.68)

x 1 2 3 4 5 6 7 8 9 10
y -0.68 -0.54 -0.33 0.16 0.56 0.81 -0.01 -0.21 0.09 0.14

接着,继续拟合数据,只是拟合的是上面的残差。得到:
h 2 ( x ) = { − 0.52 , x ≤ 3.5 0.22 , x > 3.5 h_2(x) = \begin{cases} -0.52, & x\le 3.5 \\ 0.22, & x \gt 3.5 \\ \end{cases} h2(x)={0.52,0.22,x3.5x>3.5

f 2 ( x ) f_2(x) f2(x) 为:
F 2 ( x ) = f 1 ( x ) + f 2 ( x ) = { 5.72 , x ≤ 3.5 6.46 , 3.5 < x ≤ 6.5 9.13 , 6.5 < x F_2({\bf x}) = f_1({\bf x}) + f_2({\bf x}) = \begin{cases} 5.72, & x\le 3.5 \\ 6.46, & 3.5\lt x \le 6.5 \\ 9.13, & 6.5\lt x \end{cases} F2(x)=f1(x)+f2(x)=5.72,6.46,9.13,x3.53.5<x6.56.5<x

以此类推进行计算即可,直到损失 L ( y , F t ( x ) ) L(y, F_t(\bf x)) L(y,Ft(x)) 满足要求,比如达到迭代次数 T。

和决策树CART不同的地方在于,BDT每次拟合的是残差,而CART是经典的分治算法(divide and conquer),不断的划分子空间并在子空间中进一步精确的拟合。

6.2 梯度提升

前面提到过,GBDT 全称为 Gradient Boosting Decision Tree,梯度提升决策树。

现在我们来介绍通用的“梯度提升”算法。

当采用平方损失和指数损失的时候,每一步优化是很简单的,但是一般的损失函数来说,每一步的优化不容易,因此提出了梯度提升的方法,这是利用梯度下降的近似方法,其关键是利用损失函数的负梯度在当前模型的值
(4-1) − [ ∂ L ( y i , F ( x i ) ) ∂ F ( x i ) ] F ( x ) = F t − 1 ( x ) -\left[\frac{\partial L(y_i, F({\bf x_i}))}{\partial F({\bf x_i})} \right]_{F({\bf x}) = F_{t-1}({\bf x})}\tag{4-1} [F(xi)L(yi,F(xi))]F(x)=Ft1(x)(4-1)

怎么理解这个近似呢?

以前面的均方损失函数为例,也是可以用这个方法来解释的。为了求导方便,我们在均方损失函数前乘以 1/2。
L ( y i , F ( x i ) ) = 1 2 ( y i – F ( x i ) ) 2 L(y_i, F({\bf x_i})) = \frac{1}{2}(y_i – F({\bf x_i}))^2 L(yi,F(xi))=21(yiF(xi))2

注意到 F ( x i ) F({\bf x_i}) F(xi) 其实只是一些数字而已,我们可以将其像变量一样进行求导:
∂ L ( y i , F ( x i ) ) ∂ F ( x i ) = F ( x i ) – y i \frac{\partial L(y_i, F({\bf x_i}))}{\partial F({\bf x_i})} = F({\bf x_i}) – y_i F(xi)L(yi,F(xi))=F(xi)yi

而前面所说的残差就是上式相反数,即 负梯度

必须知道的是,Boosting Tree 旨在拟合负梯度,只有当损失函数选定为 均方损失函数时候,其负梯度才表现为拟合残差,当选择其他损失函数时候,不一定就是拟合残差,比如 log 损失函数,指数损失函数等等;其次,有的损失函数会引入正则项(如 XGBoost 的损失函数引入了叶节点个数及叶子节点分数的正则项用于控制单棵树的生长),其更不可能仅仅是一个残差就能代替负梯度信息了,上述选择均方差损失函数只是为了便于理解!

r t i = y i – F t − 1 ( x ) = − [ ∂ L ( y i , F ( x i ) ) ∂ F ( x i ) ] F ( x ) = F t − 1 ( x ) r_{ti} = y_i – F_{t-1}({\bf x}) =-\left[\frac{\partial L(y_i, F({\bf x_i}))}{\partial F({\bf x_i})} \right]_{F({\bf x}) = F_{t-1}({\bf x})} rti=yiFt1(x)=[F(xi)L(yi,F(xi))]F(x)=Ft1(x)

在梯度提升中,就是将式2-1作为残差来进行拟合。由此,我们给出一般的梯度提升算法:

输入: 训练集 D a t a = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯   , ( x N , y N ) } , y i ∈ { + 1 , − 1 } Data =\{({\bf x_1},y_1),({\bf x_2},y_2),\cdots,({\bf x_N},y_N)\}, y_i \in\{+1, -1\} Data={(x1,y1),(x2,y2),,(xN,yN)},yi{+1,1};

过程:

初始化 F 0 ( x ) = arg ⁡ min ⁡ h 0 ∑ i = 1 N L ( y i , h 0 ( x ) ) F_0({\bf x}) =\mathop{\arg\min}_{h_0} \sum_{i=1}^NL(y_i, h_0({\bf x})) F0(x)=argminh0i=1NL(yi,h0(x))

for t = 1 to T do

\quad 计算负梯度 y ~ i = − [ ∂ L ( y i , F ( x i ) ) ∂ F ( x i ) ] F ( x ) = F t − 1 ( x ) ,   i = 1 , 2 , ⋯   , N {\tilde y}_{i} = -\left[\frac{\partial L(y_i, F({\bf x_i}))}{\partial F({\bf x_i})} \right]_{F({\bf x}) = F_{t-1}({\bf x})} , \ i=1,2,\cdots,N y~i=[F(xi)L(yi,F(xi))]F(x)=Ft1(x), i=1,2,,N

\quad w t = arg ⁡ min ⁡ w t ∑ i = 1 N ( y ~ i – h t ( x ; w t ) ) 2 w_t = \arg\min_{w_t} \sum_{i=1}^N \left({\tilde y}_{i} – h_t({\bf x}; {\bf w_t})\right)^2 wt=argminwti=1N(y~iht(x;wt))2 # 拟合“负梯度“得到基学习器权重,也就得到了基学习器

\quad α t = arg ⁡ min ⁡ α t ∑ i = 1 N L ( y i , f t − 1 ( x i ) + α t h t ( x ; w t ) ) \alpha_t= \arg\min_{\alpha_t} \sum_{i=1}^N L\left(y_i, f_{t-1}({\bf x_i}) + \alpha_t h_t({\bf x}; {\bf w_t})\right) αt=argminαti=1NL(yi,ft1(xi)+αtht(x;wt)) # 得到基学习器权重αt

\quad 更新 F t ( x ) = F t − 1 ( x i ) + α t h t ( x ; w t ) ​ F_t({\bf x}) = F_{t-1}({\bf x_i}) + \alpha_th_t({\bf x}; {\bf w_t})​ Ft(x)=Ft1(xi)+αtht(x;wt)

对比提升树来说,提升树没有基学习器参权重 α t \alpha_t αt

6.3 GBDT

至此,我们可以给出 GBDT 的算法了。就是采用梯度提升的决策树(CART)而已嘛。

有一点需要明确的是:GBDT 本质是回归模型,其可以处理分类问题,但同样是通过转换为回归问题进行求解!
虽然基学习器是 CART 树,但其解决分类问题时,早已放弃 Gini 系数准则,而是通过有几个类别,就每轮建几棵树,进行softmax求解各类别概率,这种思路不难理解,如果还是按照原始分类问题,GBDT 本质是梯度提升,当前轮拟合前一轮的负梯度,类别信息如何求解负梯度呢?!故而还是需转换为回归思路就行求解,将类别信息通过 softmax 转换为类别概率,这样,每轮拟合上一轮概率的负梯度进行求解!具体思路可参考下文。

前面提到过,CART 回归将空间划分为 K 个不相交的区域。可以用数学公式描述为:
f ( X ) = ∑ k = 1 K c k I ( X ∈ R k ) f(\mathbf{X}) = \sum_{k=1}^K c_k I(\mathbf{X} \in R_k) f(X)=k=1KckI(XRk)

GBDT算法(回归)描述如下:

输入: 训练集 D a t a = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯   , ( x N , y N ) } , y i ∈ { + 1 , − 1 } ​ Data =\{({\bf x_1},y_1),({\bf x_2},y_2),\cdots,({\bf x_N},y_N)\}, y_i \in\{+1, -1\}​ Data={(x1,y1),(x2,y2),,(xN,yN)},yi{+1,1};

过程

初始化 F 0 ( x ) = arg ⁡ min ⁡ h 0 ∑ i = 1 N L ( y i , h 0 ( x ) ) = arg ⁡ min ⁡ c ∑ i = 1 N L ( y i , c ) ) F_0({\bf x}) =\mathop{\arg\min}_{h_0} \sum_{i=1}^NL(y_i, h_0({\bf x})) =\mathop{\arg\min}_{c} \sum_{i=1}^NL(y_i, c)) F0(x)=argminh0i=1NL(yi,h0(x))=argminci=1NL(yi,c))

for t = 1 to T do

\quad 计算负梯度 y ~ i = − [ ∂ L ( y i , F ( x i ) ) ∂ F ( x i ) ] F ( x ) = F t − 1 ( x ) ,   i = 1 , 2 , ⋯   , N {\tilde y}_{i} = -\left[\frac{\partial L(y_i, F({\bf x_i}))}{\partial F({\bf x_i})} \right]_{F({\bf x}) = F_{t-1}({\bf x})} , \ i=1,2,\cdots,N y~i=[F(xi)L(yi,F(xi))]F(x)=Ft1(x), i=1,2,,N

\quad 拟合负梯度 y ~ i {\tilde y}_{i} y~i 得到一个回归树,得到第 t 棵树的叶结点区域 R t k R_{tk} Rtk h t ( x ) = ∑ k = 1 K c k I ( X ∈ R t k ) h_t({\bf x})= \sum_{k=1}^K c_k I(\mathbf{X} \in R_{tk}) ht(x)=k=1KckI(XRtk)

\quad 更新 F t ( x ) = F t − 1 ( x i ) + h t ( x ) = F t − 1 ( x i ) + ∑ k = 1 K c k I ( X ∈ R t k ) ​ F_t({\bf x}) = F_{t-1}({\bf x_i}) + h_t({\bf x}) = F_{t-1}({\bf x_i}) + \sum_{k=1}^K c_k I(\mathbf{X} \in R_{tk})​ Ft(x)=Ft1(xi)+ht(x)=Ft1(xi)+k=1KckI(XRtk)

​ 得到加法模型 F ( x ) = ∑ t = 1 T h t ( x ) F({\bf x}) = \sum_{t=1}^T h_t({\bf x}) F(x)=t=1Tht(x)

可以说,如果我们的任务是回归的话,并且使用RMSE作为损失函数,就和上面的boosting tree一样。因为负梯度算出来就是残差: ( y – F t − 1 ( x ) – h t ( x ) ) 2 = ( r – h t ( x ) ) 2 \left(y – F_{t-1}({\bf x} ) – h_t({\bf x})\right)^2=(r – h_t({\bf x}))^2 (yFt1(x)ht(x))2=(rht(x))2

关于 GBDT 容易迷糊的损失函数需要明白的是,GBDT 损失函数是指进行每轮增树的目标损失函数,其树内部节点生长的特征选择;对于 GBDT,其选定 CART 树作为基模型,其内部树生长策略已固定:均方差作为树节点分裂准则(无论是分类任务还是回归任务,GBDT 都是按照回归思路进行拟合负梯度,故而不会出现 Gini 系数分裂准则);而对于树生长策略的损失函数则可由用户自己指定,只有在指定外部损失函数为均方差的时候才能表现出拟合残差特性!

值得注意的是,基分类器采用 CART 分类器时,其分类是一种空间划分策略(这与 AdaBoost 更新样本权重或者采用 回归树 进行GBDT进行改变标签的策略有所不同,尤其是针对后者,都是不更新样本权重,直接判定样本标签的流程,但 CART 的分类策略与基于ID3, C4.5 策略的决策树不同,CART 重在对训练样本空间的正交划分)

6.3 GBDT 分类

如果要将GBDT用于分类问题,怎么做呢? 首先要明确的是,GBDT用于回归使用的仍然是CART回归树。回想我们做回归问题的时候,每次对残差(负梯度)进行拟合。而分类问题要怎么每次对残差拟合?要知道类别相减是没有意义的。因此,可以用Softmax进行概率的映射,然后拟合概率的残差

​如果选用的弱分类器是分类树,类别相减是没有意义的。上一轮输出的是样本 x 属于 A类,本一轮训练输出的是样本 x 属于 B类。 A 和 B 很多时候甚至都没有比较的意义,A 类- B类是没有意义的。

我们具体到分类这个任务上面来,我们假设样本 X 总共有 K类。来了一个样本 x,我们需要使用gbdt来判断 x 属于样本的哪一类。

具体的做法如下:

第一步:我们在训练的时候,是针对样本 X 每个可能的类都训练一个分类回归树。举例说明,目前样本有三类,也就是 K = 3。样本 x 属于 第二类。那么针对该样本 x 的分类结果,其实我们可以用一个 三维向量 [0,1,0] 来表示。0 表示样本不属于该类,1表示样本属于该类。由于样本已经属于第二类了,所以第二类对应的向量维度为 1,其他位置为 0。

​针对样本有 三类的情况,我们实质上是在每轮的训练的时候是同时训练三颗树。第一颗树针对样本x的第一类,输入为 (x, 0)。第二颗树输入针对 样本x 的第二类,输入为 (x,1)。第三颗树针对样本 x x x 的第三类,输入为 (x, 0)。

​在这里每颗树的训练过程其实就是就是我们之前已经提到过的 CATR TREE 的生成过程。在此处我们参照之前的生成树的程序 即可以就解出三颗树,以及三颗树对 x ​ x​ x 类别的预测值 f 1 ( x ) , f 2 ( x ) , f 3 ( x ) ​ f_{1}(x),f_{2}(x),f_{3}(x)​ f1(x),f2(x),f3(x)。那么在此类训练中,我们仿照多分类的逻辑回归 ,使用 softmax 来产生概率,则属于类别 1 的概率
p 1 = e x p ( f 1 ( x ) ) / ∑ k = 1 3 e x p ( f k ( x ) ) p_{1}=exp(f_{1}{(x)})/\sum_{k= 1}^{3}exp(f_{k}{(x)}) p1=exp(f1(x))/k=13exp(fk(x))
并且我们我们可以针对类别1 求出 残差 y 11 ( x ) = 0 − p 1 ( x ) ​ y_{11}(x) = 0-p_{1}(x)​ y11(x)=0p1(x);类别2 求出残差 y 22 ( x ) = 1 − p 2 ( x ) ​ y_{22}(x)= 1-p_2(x)​ y22(x)=1p2(x);类别 3 求出残差 y 33 ( x ) = 0 − p 3 ( x ) ​ y_{33}(x)= 0-p_{3}(x)​ y33(x)=0p3(x).

然后开始第二轮训练 针对第一类 输入为 ( x , y 11 ( x ) ) (x,y_{11}(x)) (x,y11(x)), 针对第二类输入为 ( x , y 22 ( x ) ) (x,y_{22}(x)) (x,y22(x)), 针对第三类输入为 ( x , y 33 ( x ) ) (x,y_{33}(x)) (x,y33(x)). 继续训练出三颗树。一直迭代 M 轮。每轮构建 3 颗树。

所以当 K = 3。我们其实应该有三个式子:

F 1 M ( x ) = ∑ m = 1 M C 1 m ^ I ( x ϵ R 1 m ) F_{1M}{(x)}=\sum_{m=1}^{M}{\hat{C_{1m}}I(x\epsilon R_{1m})} F1M(x)=m=1MC1m^I(xϵR1m)

F 2 M ( x ) = ∑ m = 1 M C 2 m ^ I ( x ϵ R 2 m ) F_{2M}{(x)}=\sum_{m=1}^{M}{\hat{C_{2m}}I(x\epsilon R_{2m})} F2M(x)=m=1MC2m^I(xϵR2m)

F 3 M ( x ) = ∑ m = 1 M C 3 m ^ I ( x ϵ R 3 m ) F_{3M}{(x)}=\sum_{m=1}^{M}{\hat{C_{3m}}I(x\epsilon R_{3m})} F3M(x)=m=1MC3m^I(xϵR3m)

当训练完毕以后,新来一个样本 x1 ,我们需要预测该样本的类别的时候,便可以有这三个式子产生三个值, f 1 ( x ) , f 2 ( x ) , f 3 ( x ) f_{1}(x),f_{2}(x),f_{3}(x) f1(x),f2(x),f3(x)。样本属于 某个类别 c 的概率为
p c = e x p ( f c ( x ) ) / ∑ k = 1 3 e x p ( f k ( x ) ) p_{c}=exp(f_{c}{(x)})/\sum_{k= 1}^{3}exp(f_{k}{(x)}) pc=exp(fc(x))/k=13exp(fk(x))

此时该样本的 loss 即可以用 logitloss 来表示,并对 f1 ~ fk 都可以算出一个梯度,f1 ~ fk 便可以计算出当前轮的残差,供下一轮迭代学习。最终做预测时,输入的 x 会得到 k 个输出值,然后通过 softmax 获得其属于各类别的概率即可。查看了 xgboost 的源码,实现即是这个思路。

6.4 被忽略的第三步

在原始的论文中,多分类的GBDT描述如下图(注意这里的m代表的是树的个数,N为样本数, K为类别数)

CTR 预测理论(五):集成学习之Boosting家族(AdaBoost+GBDT)_第3张图片

可以看出,和上面的一样,首先计算各个类的概率。然后对于每个类,计算出残差,然后用 CART 回归树拟合。这里和上面描述的是一样的。但是之后的倒数第五行那是什么鬼?在原论文中,描述为:拟合完后,每棵树有J个叶结点,对应区域 { R j k m } j = 1 J \{R_{jkm}\}_{j=1}^J {Rjkm}j=1J,模型通过下式的解更新这些 γ j k m {\gamma}_{jkm} γjkm
γ j k m = arg ⁡ min ⁡ γ j k ∑ i = 1 N ∑ k = 1 K ϕ ( y i k , F k , m − 1 ( x ) + ∑ j = 1 J γ j k I ( x i ∈ R j m ) ) ϕ ( y k , F k ) = − y k log ⁡ p k = p 1 ( x i ) = − y k e x p ( F k ( x i ) ) ∑ l = 1 K e x p ( F l ( x i ) ) {\gamma}_{jkm} = \mathop{\arg\min}_{\gamma_{jk}} \sum_{i=1}^N\sum_{k=1}^{K} \phi \left(y_{ik}, F_{k,m-1}({\bf x}) + \sum_{j=1}^J\gamma_{jk}I({\bf x_i} \in R_{jm})\right) \\ \phi(y_{k}, F_k)= -y_k\log p_k = p_{1}({\bf x_i})= -y_k\frac{exp(F_{k}{({\bf x_i})})}{\sum_{l= 1}^{K}exp(F_{l}{({\bf x_i})})} γjkm=argminγjki=1Nk=1Kϕ(yik,Fk,m1(x)+j=1JγjkI(xiRjm))ϕ(yk,Fk)=yklogpk=p1(xi)=ykl=1Kexp(Fl(xi))exp(Fk(xi))

但是这个式子没有闭式解。因此用牛顿法(Newton-Raphson step)进行近似。就是上面倒数第五行的结果。
虽然说没有推出来,但是大多数情况下,可以通过设置步长(Step-size,也有的叫收缩率Shrinkage)的方式来省略这一步。因此很多资料很往往不介绍这一步。关于步长,本文最后有介绍。

6.5 Sklearn GBDT二分类实现 – BinomialDeviance

在 GBDT 二分类中,可以用 Logistic 函数进行概率映射,而可以不用多分类的 SoftMax。

为了挽回一点面子,讲讲 sklearn 二分类的 BinomialDeviance 的实现。代码如下:

class BinomialDeviance(ClassificationLossFunction):
    ...
    def __call__(self, y, pred, sample_weight=None):
        """Compute the deviance (= 2 * negative log-likelihood). """
        # logaddexp(0, v) == log(1.0 + exp(v))
        pred = pred.ravel()
        if sample_weight is None:
            return -2.0 * np.mean((y * pred) - np.logaddexp(0.0, pred))
        else:
            return (-2.0 / sample_weight.sum() *
                    np.sum(sample_weight * ((y * pred) - np.logaddexp(0.0, pred))))

    def negative_gradient(self, y, pred, **kargs):
        """Compute the residual (= negative gradient). """
        return y - expit(pred.ravel())

首先是损失函数,忽略 sample_weight 权重设置,看看代码第八行。翻译过来就是
− 2.0 1 N ( y P – log ⁡ ( 1 + e x p ( P ) ) ) -2.0 \frac{1}{N}(yP – \log(1 + exp(P))) 2.0N1(yPlog(1+exp(P)))
怎么感觉和对率损失不太一样?

L = − ( y log ⁡ ( h ) + ( 1 − y ) log ⁡ ( 1 – h ) = − ( log ⁡ ( 1 – h ) + y log ⁡ ( h 1 − h ) ) = − log ⁡ ( h ( − P ) ) − y P 其 中 h ( P ) = 1 1 + e − P = log ⁡ ( 1 + exp ⁡ ( P ) ) – y P L = -(y \log(h) + (1-y) \log(1 – h) = -\left( \log(1 – h) + y \log \left( \frac{h}{1-h}\right) \right) \\ =-\log(h(-P))- y P\hspace{4ex} 其中h(P) = \frac{1}{1+e^{-P}} \\ =\log(1+ \exp(P)) – yP L=(ylog(h)+(1y)log(1h)=(log(1h)+ylog(1hh))=log(h(P))yPh(P)=1+eP1=log(1+exp(P))yP
这正是Sklearn使用的损失函数。

而负的梯度呢?
− ∂ L ∂ P = y – exp ⁡ ( P ) 1 + exp ⁡ ( P ) = y − h ( P ) -\frac{\partial L}{\partial P} = y – \frac{\exp(P)}{1+ \exp(P)} = y- h(P) PL=y1+exp(P)exp(P)=yh(P)
就是上面的 y – expit(pred.ravel())

再来看看牛顿法更新:

def _update_terminal_region(self, tree, terminal_regions, leaf, X, y,
                            residual, pred, sample_weight):
    terminal_region = np.where(terminal_regions == leaf)[0]
    residual = residual.take(terminal_region, axis=0)
    y = y.take(terminal_region, axis=0)
    sample_weight = sample_weight.take(terminal_region, axis=0)

    numerator = np.sum(sample_weight * residual)
    denominator = np.sum(sample_weight * (y - residual) * (1 - y + residual))

    # prevents overflow and division by zero
    if abs(denominator) < 1e-150:
        tree.value[leaf, 0, 0] = 0.0
        else:
            tree.value[leaf, 0, 0] = numerator / denominator

主要查看numerator和denominator的计算,这里 r e s i d u a l = y – h ( P ) residual = y – h(P) residual=yh(P)

分子就是上面的负梯度,即 r e s i d u a l = y – h ( P ) residual = y – h(P) residual=yh(P)

分母为二阶导,即 h ( P ) ( 1 − h ( P ) ) = ( y − r e s i d u a l ) ∗ ( 1 − y + r e s i d u a l ) ) h(P)(1-h(P))= (y-residual)*(1-y+residual)) h(P)(1h(P))=(yresidual)(1y+residual))

6.6 GBDT 正则化

为了避免过拟合,可以从两方面入手:

  • 弱算法的个数T, 上面描述的算法中,记得么?就是迭代T轮。T的大小就影响着算法的复杂度
  • 步长(Shrinkage)在每一轮迭代中,原来采用 F t ( x ) = F t − 1 ( x ) + α t h t ( x ; w t ) F_t({\bf x}) = F_{t-1}({\bf x}) + \alpha_th_t({\bf x}; {\bf w_t}) Ft(x)=Ft1(x)+αtht(x;wt)进行更新,可以加入步长v,使得一次不更新那么多: F t ( x ) = F t − 1 ( x ) + v   α t h t ( x ; w t ) ; v ∈ ( 0 , 1 ] F_t({\bf x}) = F_{t-1}({\bf x}) + v \ \alpha_th_t({\bf x}; {\bf w_t}); v\in(0,1] Ft(x)=Ft1(x)+v αtht(x;wt);v(0,1]

7. 参考资料

  • 机器学习技法 – 林轩田
  • 《机器学习》 – 周志华
  • 《统计学习方法》 – 李航

关于Adaboost还可以查阅:

  • Boosting Can we make dumb learners smart
  • Adaboost – 新的角度理解权值更新策略

关于GBDT可以查阅

  • Greedy Function Approximation: A Gradient Boosting Machine
  • A Gentle Introduction to Gradient Boosting
  • https://www.cnblogs.com/ModifyRong/p/7744987.html

你可能感兴趣的:(推荐系统理论进阶)