俗话说,三个臭皮匠顶个诸葛亮。类似的,如果集成一系列分类器的预测结果,也将会得到由于单个预测期的预测结果。一组预测期称为一个集合(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