[Python嗯~机器学习]---集成学习基础

集成学习

原文作者:刘建平Pinard

集成学习(ensemble learning)本身不是一个单独的机器学习算法,而是通过构建并结合多个机器学习器来完成学习任务。也就是我们常说的“博采众长”。集成学习可以用于分类问题集成,回归问题集成,特征选取集成,异常点检测集成等等。

基本思路

对于训练集数据,我们通过训练若干个个体学习器,通过一定的结合策略,就可以最终形成一个强学习器,以达到博采众长的目的。

也就是说,集成学习有两个主要的问题需要解决,第一是如何得到若干个个体学习器,第二是如何选择一种结合策略,将这些个体学习器集合成一个强学习器。
1、构建个体学习器
        第一种就是所有的个体学习器都是一个种类的,或者说是同质的。比如都是决策树个体学习器,或者都是神经网络个体学习器。
        第二种是所有的个体学习器不全是一个种类的,或者说是异质的。比如我们有一个分类问题,对训练集采用支持向量机个体学习器,逻辑回归个体学习器和朴素贝叶斯个体学习器来学习,再通过某种结合策略来确定最终的分类强学习器。

  目前来说,同质个体学习器的应用是最广泛的,一般我们常说的集成学习的方法都是指的同质个体学习器。而同质个体学习器使用最多的模型是CART决策树和神经网络
        同质个体学习器按照个体学习器之间是否存在依赖关系可以分为两类:
        1、个体学习器之间存在强依赖关系,一系列个体学习器基本都需要串行生成,代表算法是boosting系列算法。
        2、个体学习器之间不存在强依赖关系,一系列个体学习器可以并行生成,代表算法是bagging和随机森林(Random Forest)系列算法。

集成学习之Boosting



        从图中可以看出,Boosting算法的工作机制是首先从训练集用初始权重训练出一个弱学习器1,根据弱学习的学习误差率表现来更新训练样本的权重,使得之前弱学习器1学习误差率高的训练样本点的权重变高,使得这些误差率高的点在后面的弱学习器2中得到更多的重视。然后基于调整权重后的训练集来训练弱学习器2.,如此重复进行,直到弱学习器数达到事先指定的数目T,最终将这T个弱学习器通过集合策略进行整合,得到最终的强学习器。
        Boosting系列算法里最著名算法主要有AdaBoost算法和提升树(boosting tree)系列算法。提升树系列算法里面应用最广泛的是梯度提升树(Gradient Boosting Tree)。

AdaBoost


1、Adaboost算法:
        首先,思考四个问题:
        1)如何计算学习误差率 e ?
        2) 如何得到弱学习器权重系数 α ?
        3)如何更新样本权重 D ?
        4) 使用何种结合策略?
基于上面的问题我们开始AdaBoost
假设,训练集:
        T=\{(x_,y_1),(x_2,y_2), ...(x_m,y_m)\}
训练集的在第k个弱学习器的输出权重为:
        D(k) = (w_{k1}, w_{k2}, ...w_{km}) ;\;\; w_{1i}=\frac{1}{m};\;\; i =1,2...m
        第二个问题,分类问题的误差率很好理解和计算。由于多元分类是二元分类的推广,这里假设我们是二元分类问题,输出为{-1,1},则第k个弱分类器 G_k(x) 在训练集上的加权误差率为:
        e_k = P(G_k(x_i) \neq y_i) = \sum\limits_{i=1}^{m}w_{ki}I(G_k(x_i) \neq y_i)
接着我们看弱学习器权重系数,对于二元分类问题,第k个弱分类器 G_k(x) 的权重系数为:
        \alpha_k = \frac{1}{2}log\frac{1-e_k}{e_k}
为什么这样计算弱学习器权重系数?从上式可以看出,如果分类误差率 e_k 越大,则对应的弱分类器权重系数 \alpha_k 越小。也就是说,误差率小的弱分类器权重系数越大。具体为什么采用这个权重系数公式,我们在讲Adaboost的损失函数优化时再讲。
        第三个问题,更新更新样本权重D。假设第k个弱分类器的样本集权重系数为D(k) = (w_{k1}, w_{k2}, ...w_{km}),则对应的第k+1个弱分类器的样本集权重系数为
        w_{k+1,i} = \frac{w_{ki}}{Z_K}exp(-\alpha_ky_iG_k(x_i))

这里 Z_k 是规范化因子
        Z_k = \sum\limits_{i=1}^{m}w_{ki}exp(-\alpha_ky_iG_k(x_i))
 从 w_{k+1,i} 计算公式可以看出,如果第 i 个样本分类错误,则 y_iG_k(x_i) < 0,导致样本的权重在第 k+1 个弱分类器中增大,如果分类正确,则权重在第 k+1 个弱分类器中减少.具体为什么采用样本权重更新公式,我们在讲Adaboost的损失函数优化时再讲。
        最后一个问题是集合策略。Adaboost分类采用的是加权表决法,最终的强分类器为
        f(x) = sign(\sum\limits_{k=1}^{K}\alpha_kG_k(x))
2、AdaBoost回归问题
        接着我们看看Adaboost的回归问题。由于Adaboost的回归问题有很多变种,这里我们以Adaboost R2算法为准。
        我们先看看回归问题的误差率的问题,对于第 k 个弱学习器,计算他在训练集上的最大误差
        E_k= max|y_i - G_k(x_i)|\;i=1,2...m
  然后计算每个样本的相对误差
        e_{ki}= \frac{|y_i - G_k(x_i)|}{E_k}
这里是误差损失为线性时的情况,如果我们用平方误差,则e_{ki}= \frac{(y_i - G_k(x_i))^2}{E_k^2},如果我们用的是指数误差,则

最终得到第k个弱学习器的 误差率

        e_k = \sum\limits_{i=1}^{m}w_{ki}e_{ki}
我们再来看看如何得到弱学习器权重系数 α。这里有:
        \alpha_k =\frac{e_k}{1-e_k}
对于更新更新样本权重 D,第 k+1 个弱学习器的样本集权重系数为
        w_{k+1,i} = \frac{w_{ki}}{Z_k}\alpha_k^{1-e_{ki}}
这里Z_k是规范化因子
        Z_k = \sum\limits_{i=1}^{m}w_{ki}\alpha_k^{1-e_{ki}}
最后是结合策略,和分类问题稍有不同,采用的是对加权的弱学习器取权重中位数对应的弱学习器作为强学习器的方法,最终的强回归器为
        f(x) =G_{k^*}(x)
其中,G_{k^*}(x)是所有ln\frac{1}{\alpha_k}, k=1,2,....K的中位数值对应序号 k^* 对应的弱学习器。 
 

3. AdaBoost分类问题的损失函数优化

        上面我们分析了分类Adaboost的弱学习器权重系数公式和样本权重更新公式。但是没有解释选择这个公式的原因,让人觉得是魔法公式一样。其实它可以从Adaboost的损失函数推导出来。
        从另一个角度讲,Adaboost是模型为加法模型,学习算法为前向分步学习算法,损失函数为指数函数的分类问题。
        模型为加法模型好理解,我们的最终的强分类器是若干个弱分类器加权平均而得到的。
        前向分步学习算法也好理解,我们的算法是通过一轮轮的弱学习器学习,利用前一个弱学习器的结果来更新后一个弱学习器的训练集权重。也就是说,第k-1轮的强学习器为
        f_{k-1}(x) = \sum\limits_{i=1}^{k-1}\alpha_iG_{i}(x)
而第k轮的强学习器为
        f_{k}(x) = \sum\limits_{i=1}^{k}\alpha_iG_{i}(x)

上两式一比较可以得到
        f_{k}(x) = f_{k-1}(x) + \alpha_kG_k(x)

可见强学习器的确是通过前向分步学习算法一步步而得到的。

Adaboost损失函数为指数函数,即定义损失函数为
        \underbrace{arg\;min\;}_{\alpha, G} \sum\limits_{i=1}^{m}exp(-y_if_{k}(x))
利用前向分步学习算法的关系可以得到损失函数为
        (\alpha_k, G_k(x)) = \underbrace{arg\;min\;}_{\alpha, G}\sum\limits_{i=1}^{m}exp[(-y_i) (f_{k-1}(x) + \alpha G(x))]
它的值不依赖于α,G,因此与最小化无关,仅仅依赖于f_{k-1}(x),随着每一轮迭代而改变。
将这个式子带入损失函数,损失函数转化为
        
首先,我们求G_k(x),可以得到
        
G_k(x)带入损失函数,并对 α 求导,使其等于0,则就得到了
        \alpha_k = \frac{1}{2}log\frac{1-e_k}{e_k}
其中,e_k即为我们前面的分类误差率。
        
最后看样本权重的更新。利用f_{k}(x) = f_{k-1}(x) + \alpha_kG_k(x),即可得:

        

这样就得到了我们上面的样本权重更新公式。

4. AdaBoost二元分类问题算法流程

    这里我们对AdaBoost二元分类问题算法流程做一个总结。

    输入为样本集T=\{(x_,y_1),(x_2,y_2), ...(x_m,y_m)\},输出为{-1, +1},弱分类器算法, 弱分类器迭代次数K。

    输出为最终的强分类器f(x)

    1) 初始化样本集权重为
                        D(1) = (w_{11}, w_{12}, ...w_{1m}) ;\;\; w_{1i}=\frac{1}{m};\;\; i =1,2...m
               2) 对于k=1,2,...K:

      a) 使用具有权重D_k的样本集来训练数据,得到弱分类器G_k(x)

      b)计算G_k(x)的分类误差率
                        e_k = P(G_k(x_i) \neq y_i) = \sum\limits_{i=1}^{m}w_{ki}I(G_k(x_i) \neq y_i)

      c) 计算弱分类器的系数
                        \alpha_k = \frac{1}{2}log\frac{1-e_k}{e_k}

      d) 更新样本集的权重分布
                        w_{k+1,i} = \frac{w_{ki}}{Z_K}exp(-\alpha_ky_iG_k(x_i)) \;\; i =1,2,...m

      这里Z_k是规范化因子
                        Z_k = \sum\limits_{i=1}^{m}w_{ki}exp(-\alpha_ky_iG_k(x_i))

    3) 构建最终分类器为:
                        f(x) = sign(\sum\limits_{k=1}^{K}\alpha_kG_k(x))

    对于Adaboost多元分类算法,其实原理和二元分类类似,最主要区别在弱分类器的系数上。比如Adaboost SAMME算法,它的弱分类器的系数
                         \alpha_k = \frac{1}{2}log\frac{1-e_k}{e_k} + log(R-1)

    其中R为类别数。从上式可以看出,如果是二元分类,R=2,则上式和我们的二元分类算法中的弱分类器的系数一致。

5. Adaboost回归问题的算法流程

    这里我们对AdaBoost回归问题算法流程做一个总结。AdaBoost回归算法变种很多,下面的算法为Adaboost R2回归算法过程。

    输入为样本集T=\{(x_,y_1),(x_2,y_2), ...(x_m,y_m)\},弱学习器算法, 弱学习器迭代次数K。

    输出为最终的强学习器f(x)

    1) 初始化样本集权重为
                   D(1) = (w_{11}, w_{12}, ...w_{1m}) ;\;\; w_{1i}=\frac{1}{m};\;\; i =1,2...m

    2) 对于k=1,2,...K:

      a) 使用具有权重D_k的样本集来训练数据,得到弱学习器G_k(x)

      b) 计算训练集上的最大误差
                         E_k= max|y_i - G_k(x_i)|\;i=1,2...m

      c) 计算每个样本的相对误差:

        如果是线性误差,则e_{ki}= \frac{|y_i - G_k(x_i)|}{E_k}

        如果是平方误差,则e_{ki}= \frac{(y_i - G_k(x_i))^2}{E_k^2}

        如果是指数误差,则        

      d) 计算回归误差率
                         e_k = \sum\limits_{i=1}^{m}w_{ki}e_{ki}

      c) 计算弱学习器的系数
                         \alpha_k =\frac{e_k}{1-e_k}

      d) 更新样本集的权重分布为
                         w_{k+1,i} = \frac{w_{ki}}{Z_k}\alpha_k^{1-e_{ki}}

                  这里Z_k是规范化因子
                          Z_k = \sum\limits_{i=1}^{m}w_{ki}\alpha_k^{1-e_{ki}}

    3) 构建最终强学习器为:
                          f(x) =G_{k^*}(x)

    其中,G_{k^*}(x)是所有ln\frac{1}{\alpha_k}, k=1,2,....K的中位数值对应序号 k^* 对应的弱学习器。  

6. Adaboost算法的正则化

  为了防止Adaboost过拟合,我们通常也会加入正则化项,这个正则化项我们通常称为步长(learning rate)。定义为 ν,对于前面的弱学习器的迭代
        f_{k}(x) = f_{k-1}(x) + \alpha_kG_k(x)

  如果我们加上了正则化项,则有
        f_{k}(x) = f_{k-1}(x) + \nu\alpha_kG_k(x)

  v 的取值范围为0<ν≤1。对于同样的训练集学习效果,较小的 ν 意味着我们需要更多的弱学习器的迭代次数。通常我们用步长和迭代最大次数一起来决定算法的拟合效果。

7. Adaboost小结

  到这里Adaboost就写完了,前面有一个没有提到,就是弱学习器的类型。理论上任何学习器都可以用于Adaboost.但一般来说,使用最广泛的Adaboost弱学习器是决策树和神经网络。对于决策树,Adaboost分类用了CART分类树,而Adaboost回归用了CART回归树。

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

    Adaboost的主要优点有:

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

    Adaboost的主要缺点有:

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

梯度提升树(GBDT)

1. GBDT概述

  GBDT也是集成学习Boosting家族的成员,但是却和传统的Adaboost有很大的不同。回顾下Adaboost,我们是利用前一轮迭代弱学习器的误差率来更新训练集的权重,这样一轮轮的迭代下去。GBDT也是迭代,使用了前向分布算法,但是弱学习器限定了只能使用CART回归树模型,同时迭代思路和Adaboost也有所不同。

  在GBDT的迭代中,假设我们前一轮迭代得到的强学习器是f_{t-1}(x), 损失函数是L(y, f_{t-1}(x)),我们本轮迭代的目标是找到一个CART回归树模型的弱学习器 h_t(x),让本轮的损失函数L(y, f_{t}(x) =L(y, f_{t-1}(x)+ h_t(x))最小。也就是说,本轮迭代找到决策树,要让样本的损失尽量变得更小。

  GBDT的思想可以用一个通俗的例子解释,假如有个人30岁,我们首先用20岁去拟合,发现损失有10岁,这时我们用6岁去拟合剩下的损失,发现差距还有4岁,第三轮我们用3岁拟合剩下的差距,差距就只有一岁了。如果我们的迭代轮数还没有完,可以继续迭代下面,每一轮迭代,拟合的岁数误差都会减小。

  从上面的例子看这个思想还是蛮简单的,但是有个问题是这个损失的拟合不好度量,损失函数各种各样,怎么找到一种通用的拟合方法呢?

2. GBDT的负梯度拟合

  在文中,我们介绍了GBDT的基本思路,但是没有解决损失函数拟合方法的问题。针对这个问题,大牛Freidman提出了用损失函数的负梯度来拟合本轮损失的近似值,进而拟合一个CART回归树。第t轮的第i个样本的损失函数的负梯度表示为
                 r_{ti} = -\bigg[\frac{\partial L(y_i, f(x_i)))}{\partial f(x_i)}\bigg]_{f(x) = f_{t-1}\;\; (x)}

  利用(x_i,r_{ti})\;\; (i=1,2,..m),我们可以拟合一颗CART回归树,得到了第t颗回归树,其对应的叶节点区域R_{tj}, j =1,2,..., J。其中J为叶子节点的个数。

  针对每一个叶子节点里的样本,我们求出使损失函数最小,也就是拟合叶子节点最好的的输出值 c_{tj} 如下:
                  c_{tj} = \underbrace{arg\; min}_{c}\sum\limits_{x_i \in R_{tj}} L(y_i,f_{t-1}(x_i) +c)

  这样我们就得到了本轮的决策树拟合函数如下:
                  h_t(x) = \sum\limits_{j=1}^{J}c_{tj}I(x \in R_{tj})
  从而本轮最终得到的强学习器的表达式如下:
                  f_{t}(x) = f_{t-1}(x) + \sum\limits_{j=1}^{J}c_{tj}I(x \in R_{tj})

  通过损失函数的负梯度来拟合,我们找到了一种通用的拟合损失误差的办法,这样无轮是分类问题还是回归问题,我们通过其损失函数的负梯度的拟合,就可以用GBDT来解决我们的分类回归问题。区别仅仅在于损失函数不同导致的负梯度不同而已。

 3. GBDT回归算法

  有了上面的思路,下面我们总结下GBDT的回归算法。为什么没有加上分类算法一起?那是因为分类算法的输出是不连续的类别值,需要一些处理才能使用负梯度。

    输入是训练集样本T=\{(x_,y_1),(x_2,y_2), ...(x_m,y_m)\}, 最大迭代次数T, 损失函数L。

    输出是强学习器f(x)

    1) 初始化弱学习器
                 f_0(x) = \underbrace{arg\; min}_{c}\sum\limits_{i=1}^{m}L(y_i, c)

    2) 对迭代轮数t=1,2,...T有:

      a)对样本i=1,2,...m,计算负梯度
                          r_{ti} = -\bigg[\frac{\partial L(y_i, f(x_i)))}{\partial f(x_i)}\bigg]_{f(x) = f_{t-1}\;\; (x)}

      b)利用(x_i,r_{ti})\;\; (i=1,2,..m), 拟合一颗CART回归树,得到第t颗回归树,其对应的叶子节点区域为R_{tj}, j =1,2,..., J。其中J为回归树t的叶子节点的个数。

      c) 对叶子区域j =1,2,..J,计算最佳拟合值
                            c_{tj} = \underbrace{arg\; min}_{c}\sum\limits_{x_i \in R_{tj}} L(y_i,f_{t-1}(x_i) +c)

      d) 更新强学习器
                           f_{t}(x) = f_{t-1}(x) + \sum\limits_{j=1}^{J}c_{tj}I(x \in R_{tj})

    3) 得到强学习器f(x)的表达式
                          f(x) = f_T(x) =f_0(x) + \sum\limits_{t=1}^{T}\sum\limits_{j=1}^{J}c_{tj}I(x \in R_{tj})

4. GBDT分类算法

  这里我们再看看GBDT分类算法,GBDT的分类算法从思想上和GBDT的回归算法没有区别,但是由于样本输出不是连续的值,而是离散的类别,导致我们无法直接从输出类别去拟合类别输出的误差。

  为了解决这个问题,主要有两个方法,一个是用指数损失函数,此时GBDT退化为Adaboost算法。另一种方法是用类似于逻辑回归的对数似然损失函数的方法。也就是说,我们用的是类别的预测概率值和真实概率值的差来拟合损失。本文仅讨论用对数似然损失函数的GBDT分类。而对于对数似然损失函数,我们又有二元分类和多元分类的区别。

4.1 二元GBDT分类算法

  对于二元GBDT,如果用类似于逻辑回归的对数似然损失函数,则损失函数为:
                             L(y, f(x)) = log(1+ exp(-yf(x)))

  其中y \in\{-1, +1\}。则此时的负梯度误差为
                             r_{ti} = -\bigg[\frac{\partial L(y, f(x_i)))}{\partial f(x_i)}\bigg]_{f(x) = f_{t-1}\;\; (x)} = y_i/(1+exp(y_if(x_i)))

  对于生成的决策树,我们各个叶子节点的最佳负梯度拟合值为
                        c_{tj} = \underbrace{arg\; min}_{c}\sum\limits_{x_i \in R_{tj}} log(1+exp(-y_i(f_{t-1}(x_i) +c)))

  由于上式比较难优化,我们一般使用近似值代替
                        c_{tj} = \sum\limits_{x_i \in R_{tj}}r_{ti}\bigg / \sum\limits_{x_i \in R_{tj}}|r_{ti}|(1-|r_{ti}|)

  除了负梯度计算和叶子节点的最佳负梯度拟合的线性搜索,二元GBDT分类和GBDT回归算法过程相同。

4.2 多元GBDT分类算法

  多元GBDT要比二元GBDT复杂一些,对应的是多元逻辑回归和二元逻辑回归的复杂度差别。假设类别数为K,则此时我们的对数似然损失函数为:
                           L(y, f(x)) = - \sum\limits_{k=1}^{K}y_klog\;p_k(x)

  其中如果样本输出类别为k,则y_k=1。第k类的概率p_k(x)的表达式为:
                           p_k(x) = exp(f_k(x)) \bigg / \sum\limits_{l=1}^{K} exp(f_l(x))

  集合上两式,我们可以计算出第tt轮的第 i 个样本对应类别ll的负梯度误差为
                            r_{til} = -\bigg[\frac{\partial L(y_i, f(x_i)))}{\partial f(x_i)}\bigg]_{f_k(x) = f_{l, t-1}\;\; (x)} = y_{il} - p_{l, t-1}(x_i)

  观察上式可以看出,其实这里的误差就是样本ii对应类别ll的真实概率和t-1轮预测概率的差值。

  对于生成的决策树,我们各个叶子节点的最佳负梯度拟合值为
                           c_{tjl} = \underbrace{arg\; min}_{c_{jl}}\sum\limits_{i=0}^{m}\sum\limits_{k=1}^{K} L(y_k, f_{t-1, l}(x) + \sum\limits_{j=0}^{J}c_{jl} I(x_i \in R_{tj}))

  由于上式比较难优化,我们一般使用近似值代替
                           c_{tjl} = \frac{K-1}{K} \; \frac{\sum\limits_{x_i \in R_{tjl}}r_{til}}{\sum\limits_{x_i \in R_{til}}|r_{til}|(1-|r_{til}|)}

  除了负梯度计算和叶子节点的最佳负梯度拟合的线性搜索,多元GBDT分类和二元GBDT分类以及GBDT回归算法过程相同。

5. GBDT常用损失函数

  这里我们再对常用的GBDT损失函数做一个总结。

  对于分类算法,其损失函数一般有对数损失函数和指数损失函数两种:

   a) 如果是指数损失函数,则损失函数表达式为
                 L(y, f(x)) = exp(-yf(x))

  其负梯度计算和叶子节点的最佳负梯度拟合参见Adaboost原理篇。

   b) 如果是对数损失函数,分为二元分类和多元分类两种。

  对于回归算法,常用损失函数有如下4种:

   a)均方差,这个是最常见的回归损失函数了
                   L(y, f(x)) =(y-f(x))^2

   b)绝对损失,这个损失函数也很常见
                   L(y, f(x)) =|y-f(x)|

  对应负梯度误差为:
                   sign(y_i-f(x_i))

   c)Huber损失,它是均方差和绝对损失的折衷产物,对于远离中心的异常点,采用绝对损失,而中心附近的点采用均方差。这个界限一般用分位数点度量。损失函数如下:
                   L(y, f(x))= \begin{cases} \frac{1}{2}(y-f(x))^2& {|y-f(x)| \leq \delta}\\ \delta(|y-f(x)| - \frac{\delta}{2})& {|y-f(x)| > \delta} \end{cases}

  对应的负梯度误差为:
                    r(y_i, f(x_i))= \begin{cases} y_i-f(x_i)& {|y_i-f(x_i)| \leq \delta}\\ \delta sign(y_i-f(x_i))& {|y_i-f(x_i)| > \delta} \end{cases}

   d) 分位数损失。它对应的是分位数回归的损失函数,表达式为
                     L(y, f(x)) =\sum\limits_{y \geq f(x)}\theta|y - f(x)| + \sum\limits_{y < f(x)}(1-\theta)|y - f(x)|

  其中 \theta 为分位数,需要我们在回归前指定。对应的负梯度误差为:
                      r(y_i, f(x_i))= \begin{cases} \theta& { y_i \geq f(x_i)}\\ \theta - 1 & {y_i < f(x_i) } \end{cases}

  对于Huber损失和分位数损失,主要用于健壮回归,也就是减少异常点对损失函数的影响。

6. GBDT的正则化

  和Adaboost一样,我们也需要对GBDT进行正则化,防止过拟合。GBDT的正则化主要有三种方式。
        第一种是和Adaboost类似的正则化项,即步长(learning rate)。定义为ν,对于前面的弱学习器的迭代
                  f_{k}(x) = f_{k-1}(x) + h_k(x)

  如果我们加上了正则化项,则有
                 f_{k}(x) = f_{k-1}(x) + \nu h_k(x)

  ν的取值范围为 0<ν≤1。对于同样的训练集学习效果,较小的ν意味着我们需要更多的弱学习器的迭代次数。通常我们用步长和迭代最大次数一起来决定算法的拟合效果。

  第二种正则化的方式是通过子采样比例(subsample)。取值为(0,1]。注意这里的子采样和随机森林不一样,随机森林使用的是放回抽样,而这里是不放回抽样。如果取值为1,则全部样本都使用,等于没有使用子采样。如果取值小于1,则只有一部分样本会去做GBDT的决策树拟合。选择小于1的比例可以减少方差,即防止过拟合,但是会增加样本拟合的偏差,因此取值不能太低。推荐在[0.5, 0.8]之间。

  使用了子采样的GBDT有时也称作随机梯度提升树(Stochastic Gradient Boosting Tree, SGBT)。由于使用了子采样,程序可以通过采样分发到不同的任务去做boosting的迭代过程,最后形成新树,从而减少弱学习器难以并行学习的弱点。

  第三种是对于弱学习器即CART回归树进行正则化剪枝。在决策树原理篇里我们已经讲过,这里就不重复了。

7. GBDT小结 

     由于GBDT的卓越性能,只要是研究机器学习都应该掌握这个算法,包括背后的原理和应用调参方法。目前GBDT的算法比较好的库是xgboost。当然scikit-learn也可以。

    最后总结下GBDT的优缺点。

    GBDT主要的优点有:

    1) 可以灵活处理各种类型的数据,包括连续值和离散值。
               2) 在相对少的调参时间情况下,预测的准确率也可以比较高。这个是相对SVM来说的。
               3) 使用一些健壮的损失函数,对异常值的鲁棒性非常强。比如 Huber损失函数和Quantile损失函数。

    GBDT的主要缺点有:

    1)由于弱学习器之间存在依赖关系,难以并行训练数据。不过可以通过自采样的SGBT来达到部分并行。

集成学习之Bagging

        Bagging的算法原理和 boosting不同,它的弱学习器之间没有依赖关系,可以并行生成,我们可以用一张图做一个概括如下:

        从上图可以看出,bagging的个体弱学习器的训练集是通过随机采样得到的。通过T次的随机采样,我们就可以得到T个采样集,对于这T个采样集,我们可以分别独立的训练出T个弱学习器,再对这T个弱学习器通过集合策略来得到最终的强学习器。

  对于这里的随机采样有必要做进一步的介绍,这里一般采用的是自助采样法(Bootstap sampling),即对于m个样本的原始训练集,我们每次先随机采集一个样本放入采样集,接着把该样本放回,也就是说下次采样时该样本仍有可能被采集到,这样采集m次,最终可以得到m个样本的采样集,由于是随机采样,这样每次的采样集是和原始训练集不同的,和其他采样集也是不同的,这样得到多个不同的弱学习器。

  随机森林是bagging的一个特化进阶版,所谓的特化是因为随机森林的弱学习器都是决策树。所谓的进阶是随机森林在bagging的样本随机采样基础上,又加上了特征的随机选择,其基本思想没有脱离bagging的范畴。

随机森林

boosting派系,它的特点是各个弱学习器之间有依赖关系。
bagging流派,它的特点是各个弱学习器之间没有依赖关系,可以并行拟合。

随机森林是集成学习中可以和梯度提升树GBDT分庭抗礼的算法,尤其是它可以很方便的并行训练,在如今大数据大样本的的时代很有诱惑力。

1.  bagging的原理

  给出Bagging原理图。

  从上图可以看出,Bagging的弱学习器之间的确没有boosting那样的联系。它的特点在“随机采样”。那么什么是随机采样?

  随机采样(bootsrap)就是从我们的训练集里面采集固定个数的样本,但是每采集一个样本后,都将样本放回。也就是说,之前采集到的样本在放回后有可能继续被采集到。对于我们的Bagging算法,一般会随机采集和训练集样本数m一样个数的样本。这样得到的采样集和训练集样本的个数相同,但是样本内容不同。如果我们对有m个样本训练集做T次的随机采样,,则由于随机性,T个采样集各不相同。

  注意到这和GBDT的子采样是不同的。GBDT的子采样是无放回采样,而Bagging的子采样是放回采样。

  对于一个样本,它在某一次含m个样本的训练集的随机采样中,每次被采集到的概率是\frac{1}{m}。不被采集到的概率为1-\frac{1}{m}。如果m次采样都没有被采集中的概率是(1-\frac{1}{m})^m。当m \to \infty时,(1-\frac{1}{m})^m \to \frac{1}{e} \simeq 0.368。也就是说,在bagging的每轮随机采样中,训练集中大约有36.8%的数据没有被采样集采集中。

    对于这部分大约36.8%的没有被采样到的数据,我们常常称之为袋外数据(Out Of Bag, 简称OOB)。这些数据没有参与训练集模型的拟合,因此可以用来检测模型的泛化能力。

  bagging对于弱学习器没有限制,这和Adaboost一样。但是最常用的一般也是决策树和神经网络。

  bagging的集合策略也比较简单,对于分类问题,通常使用简单投票法,得到最多票数的类别或者类别之一为最终的模型输出。对于回归问题,通常使用简单平均法,对T个弱学习器得到的回归结果进行算术平均得到最终的模型输出。

  由于Bagging算法每次都进行采样来训练模型,因此泛化能力很强,对于降低模型的方差很有作用。当然对于训练集的拟合程度就会差一些,也就是模型的偏倚会大一些。

2.  bagging算法流程

  上面我们对bagging算法的原理做了总结,这里就对bagging算法的流程做一个总结。相对于Boosting系列的Adaboost和GBDT,bagging算法要简单的多。

  输入为样本集D=\{(x_,y_1),(x_2,y_2), ...(x_m,y_m)\},弱学习器算法, 弱分类器迭代次数T。

  输出为最终的强分类器f(x)

   1)对于t=1,2...,T:
                   a)对训练集进行第t次随机采样,共采集m次,得到包含m个样本的采样集D_t
                   b)用采样集DtDt训练第t个弱学习器G_t(x)
           2) 如果是分类算法预测,则T个弱学习器投出最多票数的类别或者类别之一为最终类别。如果是回归算法,T个弱学习器得到的回归结果进行算术平均得到的值为最终的模型输出。

3. 随机森林算法

  理解了bagging算法,随机森林(Random Forest,以下简称RF)就好理解了。它是Bagging算法的进化版,也就是说,它的思想仍然是bagging,但是进行了独有的改进。我们现在就来看看RF算法改进了什么。   

  首先,RF使用了CART决策树作为弱学习器,这让我们想到了梯度提示树GBDT。第二,在使用决策树的基础上,RF对决策树的建立做了改进,对于普通的决策树,我们会在节点上所有的n个样本特征中选择一个最优的特征来做决策树的左右子树划分,但是RF通过随机选择节点上的一部分样本特征,这个数字小于n,假设为n_{sub},然后在这些随机选择的n_{sub}个样本特征中,选择一个最优的特征来做决策树的左右子树划分。这样进一步增强了模型的泛化能力。    

  如果n_{sub} =n,则此时RF的CART决策树和普通的CART决策树没有区别。n_{sub} 越小,则模型约健壮,当然此时对于训练集的拟合程度会变差。也就是说 n_{sub} 越小,模型的方差会减小,但是偏倚会增大。在实际案例中,一般会通过交叉验证调参获取一个合适的 n_{sub} 的值。

  除了上面两点,RF和普通的bagging算法没有什么不同, 下面简单总结下RF的算法。

  输入为样本集D=\{(x_,y_1),(x_2,y_2), ...(x_m,y_m)\},弱分类器迭代次数T。

  输出为最终的强分类器f(x)

   1)对于t=1,2...,T:
                  a)对训练集进行第t次随机采样,共采集m次,得到包含m个样本的采样集D_t
                  b)用采样集DtDt训练第t个决策树模型G_t(x),在训练决策树模型的节点的时候, 在节点上所有的样本特征中选择一部分样本特征, 在这些随机选择的部分样本特征中选择一个最优的特征来做决策树的左右子树划分
           2) 如果是分类算法预测,则T个弱学习器投出最多票数的类别或者类别之一为最终类别。如果是回归算法,T个弱学习器得到的回归结果进行算术平均得到的值为最终的模型输出。

4. 随机森林的推广

  由于RF在实际应用中的良好特性,基于RF,有很多变种算法,应用也很广泛,不光可以用于分类回归,还可以用于特征转换,异常点检测等。下面对于这些RF家族的算法中有代表性的做一个总结。

 4.1 extra trees

  extra trees是RF的一个变种, 原理几乎和RF一模一样,仅有区别有:
           1) 对于每个决策树的训练集,RF采用的是随机采样bootstrap来选择采样集作为每个决策树的训练集,而extra trees一般不采用随机采样,即每个决策树采用原始训练集。
           2) 在选定了划分特征后,RF的决策树会基于基尼系数,均方差之类的原则,选择一个最优的特征值划分点,这和传统的决策树相同。但是extra trees比较的激进,他会随机的选择一个特征值来划分决策树。
        从第二点可以看出,由于随机选择了特征值的划分点位,而不是最优点位,这样会导致生成的决策树的规模一般会大于RF所生成的决策树。也就是说,模型的方差相对于RF进一步减少,但是偏倚相对于RF进一步增大。在某些时候,extra trees的泛化能力比RF更好。

4.2 Totally Random Trees Embedding

  Totally Random Trees Embedding(以下简称 TRTE)是一种非监督学习的数据转化方法。它将低维的数据集映射到高维,从而让映射到高维的数据更好的运用于分类回归模型。我们知道,在支持向量机中运用了核方法来将低维的数据集映射到高维,此处TRTE提供了另外一种方法。

  TRTE在数据转化的过程也使用了类似于RF的方法,建立T个决策树来拟合数据。当决策树建立完毕以后,数据集里的每个数据在T个决策树中叶子节点的位置也定下来了。比如我们有3颗决策树,每个决策树有5个叶子节点,某个数据特征 x 划分到第一个决策树的第2个叶子节点,第二个决策树的第3个叶子节点,第三个决策树的第5个叶子节点。则 x 映射后的特征编码为(0,1,0,0,0,     0,0,1,0,0,     0,0,0,0,1), 有15维的高维特征。这里特征维度之间加上空格是为了强调三颗决策树各自的子编码。

  映射到高维特征后,可以继续使用监督学习的各种分类回归算法了。

4.3 Isolation Forest

  Isolation Forest(以下简称IForest)是一种异常点检测的方法。它也使用了类似于RF的方法来检测异常点。

  对于在T个决策树的样本集,IForest也会对训练集进行随机采样,但是采样个数不需要和RF一样,对于RF,需要采样到采样集样本个数等于训练集个数。但是IForest不需要采样这么多,一般来说,采样个数要远远小于训练集个数?为什么呢?因为我们的目的是异常点检测,只需要部分的样本我们一般就可以将异常点区别出来了。

  对于每一个决策树的建立, IForest采用随机选择一个划分特征,对划分特征随机选择一个划分阈值。这点也和RF不同。

  另外,IForest一般会选择一个比较小的最大决策树深度max_depth,原因同样本采集,用少量的异常点检测一般不需要这么大规模的决策树。

  对于异常点的判断,则是将测试样本点xx拟合到T颗决策树。计算在每颗决策树上该样本的叶子节点的深度h_t(x)。从而可以计算出平均高度h(x)。此时我们用下面的公式计算样本点 x 的异常概率:
                    s(x,m) = 2^{-\frac{h(x)}{c(m)}}

  其中,m为样本个数。c(m)的表达式为:
                    

  s(x,m)的取值范围是[0,1],取值越接近于1,则是异常点的概率也越大。

5. 随机森林小结

  RF的算法原理也终于讲完了,作为一个可以高度并行化的算法,RF在大数据时候大有可为。 这里也对常规的随机森林算法的优缺点做一个总结。

  RF的主要优点有:
            1) 训练可以高度并行化,对于大数据时代的大样本训练速度有优势。个人觉得这是的最主要的优点。
            2) 由于可以随机选择决策树节点划分特征,这样在样本特征维度很高的时候,仍然能高效的训练模型。
            3) 在训练后,可以给出各个特征对于输出的重要性
          4) 由于采用了随机采样,训练出的模型的方差小,泛化能力强。
             5) 相对于Boosting系列的Adaboost和GBDT, RF实现比较简单。
             6) 对部分特征缺失不敏感。
        RF的主要缺点有:
             1)在某些噪音比较大的样本集上,RF模型容易陷入过拟合。
             2) 取值划分比较多的特征容易对RF的决策产生更大的影响,从而影响拟合的模型的效果。

集成学习之结合策略

  在上面我们主要关注于学习器,提到了学习器的结合策略但没有细讲,本节就对集成学习之结合策略做一个总结。我们假定我得到的T个弱学习器是\{h_1,h_2,...h_T\}

1 平均法

  对于数值类的回归预测问题,通常使用的结合策略是平均法,也就是说,对于若干个弱学习器的输出进行平均得到最终的预测输出。

  最简单的平均是算术平均,也就是说最终预测是
              H(x) = \frac{1}{T}\sum\limits_{1}^{T}h_i(x)

  如果每个个体学习器有一个权重 w,则最终预测是
                H(x) = \sum\limits_{i=1}^{T}w_ih_i(x)

  其中 w_i 是个体学习器hihi的权重,通常有
                 w_i \geq 0 ,\;\;\; \sum\limits_{i=1}^{T}w_i = 1

2. 投票法

  对于分类问题的预测,我们通常使用的是投票法。假设我们的预测类别是\{c_1,c_2,...c_K\},对于任意一个预测样本x,我们的T个弱学习器的预测结果分别是(h_1(x), h_2(x)...h_T(x))

  最简单的投票法是相对多数投票法,也就是我们常说的少数服从多数,也就是 T 个弱学习器的对样本 x 的预测结果中,数量最多的类别 c_i 为最终的分类类别。如果不止一个类别获得最高票,则随机选择一个做最终类别。

  稍微复杂的投票法是绝对多数投票法,也就是我们常说的要票过半数。在相对多数投票法的基础上,不光要求获得最高票,还要求票过半数。否则会拒绝预测。

  更加复杂的是加权投票法,和加权平均法一样,每个弱学习器的分类票数要乘以一个权重,最终将各个类别的加权票数求和,最大的值对应的类别为最终类别。

3. 学习法

  上面的方法都是对弱学习器的结果做平均或者投票,相对比较简单,但是可能学习误差较大,于是就有了学习法这种方法,对于学习法,代表方法是stacking,当使用stacking的结合策略时, 我们不是对弱学习器的结果做简单的逻辑处理,而是再加上一层学习器,也就是说,我们将训练集弱学习器的学习结果作为输入,将训练集的输出作为输出,重新训练一个学习器来得到最终结果。

  在这种情况下,我们将弱学习器称为初级学习器,将用于结合的学习器称为次级学习器。对于测试集,我们首先用初级学习器预测一次,得到次级学习器的输入样本,再用次级学习器预测一次,得到最终的预测结果。

你可能感兴趣的:(鹏鹏哥哥的机器学习,集成学习,GBDT,随机森林,bagging,boosting)