zoukankan      html  css  js  c++  java
  • 第七章——集成学习和随机森林(Ensemble Learning and Random Forests)

    俗话说,三个臭皮匠顶个诸葛亮。类似的,如果集成一系列分类器的预测结果,也将会得到由于单个预测期的预测结果。一组预测期称为一个集合(ensemble),因此这一技术被称为集成学习(Ensemble Learning)。集成学习算法称作集成方法(Ensemble method)。

    例如,可以基于训练集的不同随机子集,训练一组决策树分类器。做预测是,首先拿到每一个决策树的预测结果,得票数最多的一个类别作为最终结果,这就是随机森林。

    此外,通常还可以在项目的最后使用集成方法。比如已经创建了几个不错的分类器,可以将其集成为一个更优秀的分类器。

    本章介绍了最手欢迎的分类器,包括bagging,boosting,stacking。

    7.1 投票分类器(Voting Classifiers)

    假如训练了一些分类器,如图7-1所示,

    7-1. 训练不同的分离器

    根据每一分类器的预测结果,我们选择得票最多的分类器作为最终预测结果,如图7-2所示。这种多数票决分类器被称作硬投票(hard voting)分类器。

    7-2. 硬投票分类器

    一般情况下,投票分类器会优于它所集成的每一个分类器。即使每一个单独的分类器都很弱(预测结果仅仅略高于随机猜测),集成分类器也可以很强,只要弱分类器是多种多样不同的分类器。

     为什么会这么神奇呢?假设一枚硬币有缺陷,会导致51%的概率正面朝上,49%的概率反面朝上。如果投掷1000次,大约会有510次正面朝上,490次反面朝上,大多是是朝上的。通过数学计算可知,投掷1000次,大部分正面朝上的概率是75%(可以根据林德贝格-勒维中心极限定理求得)。投掷的次数越多,这一概率越高(投掷10000次,这一概率是97%)。这是由于大数定律:在重复试验中,随着试验次数的增加,事件发生的频率趋于其期望。

    类似的,假设有1000个分类器,其单独的正确率仅有51%,通过多数票决预测分类,其正确率可达75%。不过,这需要分类器完全独立,错误不相关。但由于是在同样的数据集训练的,错误的类型可能相同,从而降低了正确率。

    如果分类器可以给出类别的概率(也就是具有predict_proba()方法),那么可以使Scikit-Learn的最终预测结果为平均概率最高的那一类别。这被称作软投票(soft voting)。软投票的性能一般优于硬投票。

    7.2 Bagging and Pasting

    另一种获得不同分类器的方法是,训练算法虽然是相同的,但训练数据确是从训练集中随机选取的不同子集。如果子集的选取是有放回采样(sampling with replacement。replace在这里是复位、归还的意思,不是代替的意思。),这一方法称为bagging(bootstrap aggregating的简称。在统计学上,有放回采样称为bootstrapping)。如果是无放回采样(sampling without replacement),则称之为pasting

    7.2.1 Bagging and Pasting in Scikit-Learn

    介绍了如何使用BaggingRegressor

    如图7-5所示,集成树和单个子树有大致相当的bias,但是前者的variance更小。(二者在训练集上的误差大致相当,但是集成树边界更规则,更容易一般化。)

    图7-5. 一棵决策树 Vs 500棵决策树bagging集成

    有放回抽样(Bootstrapping)生成的子集之间更具多样性,因此bagging比pasting具有稍高的bias,但是预测期之间的相关性也较小从而集成后的variance会减小。总体来说,bagging更优一些。

    7.2.2 Out-of-Bag评估

    使用bagging时,对于某一个预测器,某些样本可能被抽样多次,也有些样本可能从没被抽样到。事实上,对于每一个预测期,平均有63%的样本会被抽样到,剩下的从没有被抽到的37%样本称为out-of-bag (oob)样本。注意,对每个预测器,这是不同的37%样本。

    可以证明为什么平均37%的样本不会被抽到。假设样本总数是$m$,在$m$次有放回抽样中,一个样本始终没有被抽中的概率为$P(oob)= (1 - frac{1}{m})^m$,当$m$足够大时,

    egin{align*}
    lim_{m ightarrow +infty}(1 - frac{1}{m})^m &= lim_{m ightarrow +infty}(frac{m - 1}{m})^m \
    &= lim_{m ightarrow +infty}(frac{1}{frac{m}{m-1}})^m \
    &= lim_{m ightarrow +infty}(frac{1}{1 + frac{1}{m-1}})^m \
    &= lim_{m ightarrow +infty}frac{1}{(1 + frac{1}{m-1})(1 + frac{1}{m-1})^{m-1}} \
    &= lim_{m ightarrow +infty}frac{1}{(1 + frac{1}{m-1})e} \
    &= frac{1}{e} \
    &approx 0.37
    end{align*}

    对于某一个预测器来说,它并没有使用oob样本,因此该预测器可以使用oob样本进行评估,而不用专门划分出校验集。

    7.3 Random Patches and Random Subspaces

    BaggingClassifier也支持特征抽样,这通过超参数max_features和bootstrap_features控制。工作原理与max_samples和bootstrap类似,只不过把样本抽样替换成了特征抽样。

    这一方法在高维度输入(比如图像)是很有用。样本和特征均抽样称为Random Patches method,只对特征抽样称为Random Subspaces method

    7.4 随机森林(Random Forests) 

    随机森林是一系列决策树的集成,一般使用bagging方法。 

    7.4.1 Extra-Trees 

    在随机森林中生成一棵决策树时,会使用随机选择的特征子集,来切分数据集。还可以通过使用随机的阈值来增加随机性。这种更为随机的森林被称作Extremely Randomized Tree sensemble(简称Extra-Trees)。

    7.4.2 特征重要性(Feature Importance)

    如果观察一棵决策树,会发现越靠近根节点的特征越重要。可以通过计算一个特征在森林中的平均深度来评估其重要性。

    7.5 Boosting

    Boosting (最初被称作hypothesis boosting)是指所有可以联合一系类弱学习器使其成为强学习器的方法。其基本思想是循环地训练预测器,每一次都尝试更新其预测。现在有很多Boosting方法,最有名的是AdaBoost(Adaptive Boosting的简称)和Gradient Boosting

    7.5.1 AdaBoost

    这一技术技术在训练的时候,多关照一下预测错的实例 。例如,创建一个AdaBoost分类器。第一个分类器在训练集上训练并作出预测。然后误分类实例的权重就会增加。第二个分类器会在权重更新后的训练集上训练,然后预测、更新权重。重复这一过程,如图7-7所示。

    图7-7. AdaBoost更新实例权重并连续训练

    等所有预测器训练完成后,预测过程类似于bagging或者pasting,只不过每一个预测期根据其总体精度,会有不同的权重。

    AdaBoost算法存在一个劣势,那就是不能并行运算,因为后面预测器的训练,需要用到之前预测器的预测结果。

    AdaBoost详解:

    训练样本大小$m$,每一个实例权重$w^{(i)}$初始化设置为$frac{1}{m}$。第一个预测器进行训练,并计算训练集的加权误差率(weighted error rate)$r_1$。

    第$j$个预测器的加权误差率:

    egin{align*}
    r_j = frac{sum_{i=1,hat{y}_j^{(i)} eq y^{(i)}}^{m}w^{(i)}}{sum_{i=1}^{m}w^{(i)}}
    end{align*}

    其中,$hat{y}_j^{(i)}$ 是第$j$个预测器对第$i$个实例的预测值。

    预测器权重:

    egin{align*}
    alpha_j = eta \, log \, frac{1-r_j}{r_i}
    end{align*}

    其中,$eta$是学习率超参数(默认是1)。错误率越低,权重越大。错误率接近50%(也就是随机猜测),权重接近0。错误率低于50%,则权重是负的。可参考下图。

    实例的权重将按照如下方式更新:

    egin{align*}
    &for i = 1, 2, cdots ,m \
    &w_{(i)} leftarrow left{egin{matrix}
    w^{(i)} &if hat{y}_j^{(i)} = y_{(i)} \
    w^{(i)} exp(a_j) &if hat{y}_j^{(i)} eq y_{(i)}
    end{matrix} ight.
    end{align*}

    然后权重还要进行标准化。(也就是除以$sum_{i=1}^{m}w^{(i)}$)

    紧接着,一个新的预测试会使用更新后的权重,重复这一训练过程。如果预测器个数超过预定值,或者预测结果已经足够好,算法将会停止。

    AdaBoost算法的预测:

    egin{align*}
    mathop{argmax}limits_{k}mathop{sum_{j=1}^{N}}limits_{hat{y}_j(X)=k} a_j
    end{align*}

    其中,N是预测器个数。

    事实上,Scikit-Learn使用的是一用被称作SAMME(Stagewise Additive Modeling using a Multiclass Exponential loss function)的多分类版本 AdaBoost。如果仅仅是二分类,SAMME和AdaBoost是等价的。

    如果发现AdaBoost在训练集上过拟合,可以减少评估器的数量,或者增加更强的正则约束。

    7.5.2 Gradient Boosting

    与AdaBoost类似,Gradient Boosting也是不停地增加预测器。不同的是,Gradient Boosting新增加的预测器,回去拟合其前任的残差(residual errors)。该算法处理回归任务表现很好,被称作Gradient Tree Boosting或者Gradient Boosted Regression Trees (GBRT,梯度提升决策树)。

    与之类似的GBDT (Gradient Boosting Decision Tree)好像更出名一些。有空学习一下GBDT。

    7.6 Stacking

    stacking(stacked generalization的简称)是本章最后一个集成方法。该方法思想很简单:与其使用简陋的集成方法(比如硬投票),何不专门训练一个集成方法?图7-12展示了这一预测过程。底部的三个预测器给出了3个不同的结果(3.1、2.7、2.9),上面一个预测器(被称作混合器,blendor)根据这3个结果,给出了最终的预测(3.0)。

    图7-12. 通过混合预测器进行集成预测

    为了训练blender,常用的方法是使用一个hold-out数据集(hold-out set)。其工作方式如下:

    首先将训练集划分为两个子集,第一个子集用于训练第一层的预测器,如图7-13所示:

    图7-13. 训练第一层

    然后,使用第一层训练出的预测器对第二个子集(也成为hold-out集)进行预测。现在hold-out集有三个预测值。这三个预测值和hold-out集的目标值组成新的训练集,用于训练blender,如图7-14所示。

    图7-14. 训练blender

    此外,也可以再复杂一点,训练多个blender。把训练集分为3份。第一份训练第一层,第二份用于产生第二层的训练集,第三份用于产生第三次的训练集。其预测过程如图7-15所示。

    7-15. 多层stacking ensemble预测流程

     

     Scikit-Learn并不直接支持stacking,不过github有开源实现:https://github.com/viisar/brew

    参考文献:Spark随机深林扩展—OOB错误评估和变量权重

  • 相关阅读:
    网上流行的学生选课相关的50个常用sql语句
    the interview questions of sql server
    ASP.NET 之 Chart Control for .Net Framework
    SQL Server之纵表与横表互转
    ASP.NET控件之RadioButtonList
    SQL Server通过钉钉机器人直接发送消息
    使用AMO对象,更改款属性名称
    常用MDX函数
    Excel 插入图片
    Sql Server 2008查询数据库中各表记录行数
  • 原文地址:https://www.cnblogs.com/royhoo/p/Ensemble-Learning-and-Random-Forests.html
Copyright © 2011-2022 走看看