这里主要介绍集成学习的基本思想,然后讨论常用的集成学习方法,如:bagging、boosting、stacking
集成学习是对其他算法(模型)进行组合的一种方式,其思想与人们在面临重要决定时会听取多个人的意见而不是单个人的意见是类似的。构建的一系列模型是基学习器(弱学习器:准确率大于0.5即可),通过使用不同的策略将基学习器聚合起来,这种聚合起来的模型犯错率会降低。集成方法的多种形式:
l 不同的算法的集成
l 同一算法在不同设置下的集成
l 数据集的不同部分分配给不同分类器后的集成
按照学习器生成策略的不同,集成学习方法分为:
l 并行方法: 如bagging
l 顺序方法: 如boosting
在并行方法中,同时构建多个基学习器,并利用这些基学习器的独立性以提高最后模型的性能。在集成学习中,我们要尽量构建独立的学习器,以使得它们犯错也相互独立。当然,在实际中我们很难得到完全相互独立的基学习器。此外,我们一般只有一个训练集。如果都从同一训练集得到多个不同的模型的话,它们之间很难做到相互独立。因此,在实践中,我们通常通过引入随机性来尽量构造相互独立的模型。并行方法的一大优点是利于并行计算,可以显著地降低训练模型所需要的时间。
在顺序方法中,顺次构建多个学习器。当构建后面的学习器时,后面的学习器能够避免前面学习器的错误,从而提高聚合后的性能。因此,在顺序方法中,我们要利用基学习器的相关性。与并行方法不同,在顺序方法中,我们需要逐个建立新的学习器,较难利用并行性以缩短训练时间。
1.1bagging:基于数据随机重抽样的分类器构建方法
自举汇聚法(bootstrapaggregating),也称为bagging方法,是通过bootstrap取样(可重复取样)的方法,从原始数据集得到新数据集的一种技术。在数据集建好之后,将某个学习算法分别作用于每个数据集就得到了S个基学习器,然后将这些基学习器聚合(aggregation)起来得到最终的模型。boostrap取样和模型聚合(aggregation)是bagging的两个重要组成部分。
boostrap取样:
在前面的讨论中,我们强调了基学习器相互独立的重要性:虽然每个基学习器的性能较弱,但是如果它们都是从不同的角度犯错,那么将它们聚合起来的性能也许会有较大提升。在实际中,在给定一个训练集的情况下,如何尽可能地建立相对独立的基学习器呢?基本上我们只有两种选择:
(1)在训练每个基学习器的时候使用不同的训练集;
如果我们选择使用不同的训练集,一种可能性是将整个训练集划分为多个不同的子集,然后在每个子集上训练不同的基学习器。这个方法虽然保证了这些基学习器是从不同的训练集上得到的,但是由于每个子集都显著小于原来的训练集,使得构建的基学习器可能遗漏了原始训练集中的一些关键信息。同时,每个子集和整个训练集的分布可能存在差异。因此,这样得到的基学习器的性能会受到影响。
(2)在训练集相同或者相近的情况下,使用不同的学习算法来训练不同的基学习器。
既要利用训练集中更多的样本,又要同时尽量保证不同的训练集的独立性。为了解决这个问题,人们提出了bootstrap取样(bootstrap sampling)。简而言之,bootstrap取样就是使用可重复取样(sampling with replacement)的方法,从样本数为n的数据集中取出n个样本。除了一种极端情况(就是bootstrap取样得到了整个原来的数据集),使用bootstrap取样得到的n个样本中都有重复样本,同时也有原来数据集中的样本没有被取到。注意,在可重复取样中,我们假设每个样本被选中的概率是一样的。在bagging中,对于原始的训练集,我们使用bootstrap取样m次,选取出m个样本集。在每个样本集上,我们构建相应的基学习器。这样就得到了m个不同的学习器。
模型聚合:
在bagging中,我们通常采用比较简单的方法来聚合多个模型。对于分类问题,我们采用投票(voting)的方法将m个基学习器的分类结果中出现最多的一个作为最终的分类结果;对于回归问题,我们直接取m个基学习器的输出的平均值。注意,使用bagging还可以处理多类分类问题,只需要基学习器能够处理多类问题即可。
算法1-1给出了bagging在分类和回归问题中的基本流程。其中mode函数计算统计中的众数(mode),表示从中选取出现频率最高的类标作为最终的分类结果。
bagging的基本流程
for j=1:m
产生一个boostrap取样的样本集
在Sj上训练一个基学习器
聚合m个模型
对于分类问题:
)
对于回归问题:
bagging的另一个优点:对于每个基学习器,我们可以利用不在训练集中的样本(out-of-bag sample,OOB样本)来估计基学习器的性能。在训练模型的过程中,由于我们从未接触过OOB样本,因此它们是天然的检验算法性能的数据。
1.2boosting
boosting是一种与bagging很类似的技术。不论在boosting还是bagging方法中,所使用的多个分类器的类型都是一致的。但是在boosting中,不同的分类器是通过串行训练获得的,每个新分类器都根据已训练出的基学习器性能来进行训练(通过分析前一个建立的基学习器,寻求改进方向,重新构建新的基学习器)。boosting通过集中关注被已有分类器错分的那些数据来获得新的分类器。
由于boosting分类器是基于所有分类器的加权求和的结果,因此boosting与bagging不太一样。bagging中的分类器权重是相等的,而boosting中的分类器权重并不相等,每个权重代表的是其对应分类器在上一轮迭代中的成功度。(boosting在bagging的思路上更进了一步,它在数据集上顺序应用了多个不同的分类器。)随机森林也是一个很成功的集成方法,但不如boosting流行。
boosting方法拥有多个版本,这里只关注其中一个最流行的版本AdaBoost。AdaBoost的一般流程:
l 收集数据:可以使用任意方法。
l 准备数据:依赖于所使用的弱分类器类型,这里使用的单层决策树,这种分类器可以处理任何数据类型。当然也可以使用任意分类器作为弱分类器。作为弱分类器,简单分类器的效果更好。
l 分析数据:可以使用任意方法。
l 训练算法:AdaBoost的大部分时间都用在训练上,分类器将多次在同一数据集上训练弱分类器。
l 测试算法:计算分类的错误率。
l 使用算法:同SVM一样,AdaBoost预测二分类。如想应用到多个类别,就需要想SVM一样的做法对AdaBoost进行修改。
2、训练算法基于错误提升分类器的性能
能否用若分类器和多个实例来构建一个强分类器?这是一个非常有趣的问题,这里的“弱”意味着分类器的性能比随机猜测要略好,但是也不会好太多。这就是说,在二分类情况下,弱分类器的错误率会高于50%,而“强”分类器的错误率将会降低很多。AdaBoost算法在上述问题的基础上形成的。
AdaBoost是Adaptiveboosting的缩写,其运行过程如下:训练数据中的每个样本,并赋予其一个权重,这些权重构成了向量D。一开始,这些权重都初始化成相等值。首先在训练数据上训练出一个弱分类器并计算该分类器的错误率,然后在同一数据集上再次训练弱分类器。在分类器的第二次训练当中,将会重新调整每个样本的权重,其中,第一次分类正确的样本权重降低,而第一次分类错误的样本权重提高。为了从所有弱分类器中得到最终的分类结果,AdaBoost为每个分类器都分配了一个权重值alpha,这些alpha值是基于每个弱分类器的错误率计算的。其中,错误率ε的定义为:
而alpha的计算公式如下:
AdaBoost算法的流程图,如下图1所示。
分类器 |
分类器 |
分类器 |
|
图1 AdaBoost 算法示意图。左边是数据集,其中直方图的不同长度表示每个样例上的不同权重。在经过一个分类器后,加权的预测结果后通过三角形中的alpha值进行加权。每个三角形中输出的加权结果在圆形中求和,从而得到最终的输出结果。
计算出alpha值后,可以对权重向量D进行更新,以使那些正确分类的样本的权重降低而错分类样本权重升高。D的计算方法如下。
如果某个样本被正确分类,那么样本的权重更改为:
而如果某个样本被错分,那么该样本的权重更改为:
计算出D后,AdaBoost又开始进入下一轮迭代。AdaBoost算法会不断地重复训练和调整权重的过程,直到训练错误率为0或者弱分类器的数目达到用户的指定值为止。
接下来,建立完整的AdaBoost算法。在此之前,先通过代码建立弱分类器及保存数据集的权重。
3、基于单层决策树构建弱分类器
单层决策树(decisionstump,也称决策树桩)是一种简单的决策树。前面已经介绍了决策树的原理,接下来将构建一个单层决策树,而它仅基于单个特征来做决策。由于这棵树只有一次分裂过程,因此实际上就是一个树桩。
第一个函数用于测试是否有某个值小于或者大于我们正在测试的阈值。第二个函数则更加复杂一些,它会在一个加权数据集中循环,并找到具有最低错误率的单层决策树。
这个程序的伪代码看起来大致是:
将最小错误率minError设为+∞
对数据集中的每一个特征(第一层循环):
对每个步长(第二层循环):
对每个不等号(第三层循环):
建立一棵单层决策树并利用加权数据集对它进行测试
如果错误率低于minError,则将当前单层决策树设为最佳单层决策树
返回最佳单层决策树
4、完整AdaBoost算法的实现
上面构建了一个基于加权输入值进行决策的分类器。实现一个完整AdaBoost算法的伪代码如下:
对每次迭代:
利用bulidStump()函数找到最佳的单层决策树
将最佳单层决策树加入到单层决策树数组
计算alpha
计算新的权重向量D
更新累计类别估计值
如果错误率等于0.0,则退出循环
5、测试算法:基于AdaBoost的分类
一旦拥有了多个弱分类器以及其对应的alpha值,进行测试就容易了。现在要做的只是将弱分类器的训练过程从程序中抽取出来,然后应用到某个具体的实例上去。每个弱分类器的结果以其对应的alpha值作为权重。所有这些弱分类器的结果加权求和得到最后结果。