AdaBoost算法
1. 集成学习
目前存在各种各样的机器学习算法,例如SVM、决策树、神经网络等等。但是实际应用中,或者说在打比赛时,成绩较好的队伍几乎都用了集成学习(ensemble learning)的方法。集成学习的思想,简单来讲,就是“三个臭皮匠顶个诸葛亮”。集成学习通过结合多个学习器,一般会获得比任意单个学习器都要好的性能,尤其是在这些学习器都是”弱学习器”的时候提升效果会很明显。
弱学习器指的是性能不太好的学习器,比如一个准确率略微超过50%的二分类器。
Boosting指的是一类集成方法,其主要思想就是将弱的基学习器提升(boost)为强学习器。具体步骤如下:
- 先用每个样本权重相等的训练集训练一个初始的基学习器;
- 根据上轮得到的学习器对训练集的预测表现情况调整训练集中的样本权重, 然后据此训练一个新的基学习器;
- 重复步骤2直到得到\(M\)个基学习器,最终的集成结果是\(M\)个基学习器的组合。
由此看出,Boosting算法是一个串行的过程。
关于集成学习的其他内容在集成学习简介这篇笔记中已经学习过了。
Boosting算法簇中最著名的就是AdaBoost,也是本篇笔记将要学习的算法。
2. AdaBoost算法概述
AdaBoost算法的全称是自适应增强(Adaptive Boosting),是一个具有里程碑意义的算法,因为其是第一个具有适应性的算法,即能适应基学习器各自的训练误差率。
AdaBoost算法的流程可描述为:先对每个样本赋予相同的初始权重,每一轮学习器训练过后都会根据其表现对每个样本的权重进行调整,增加分错样本的权重,这样先前分错的样本在后续训练中就能得到更多关注,按这样的过程重复训练出\(M\)个学习器,最后进行加权组合,如图1所示。
图1 AdaBoost算法流程示意图
图2显示通过将基学习器加权组合就能生成具有复杂边界的强学习器。
图2 AdaBoost算法组合策略示意图
简要说明一下图2的过程:
\(G_1(x)\)弱分类器, 正负样本被分为蓝\((+)\)红\((-)\)两个区域,红色区域有3个误分类正样本,\(G_2(x)\)将更关注它们(增加权重);
\(G_2(x)\)弱分类器,正负样本被分为蓝蓝\((+)\)红\((-)\)两个区域,蓝色区域有3个误分类负样本,\(G_3(x)\)更关注它们;
通过不断调整样本权重最终将若干个弱分类器进行集成得到强的分类器\(G(x)\)。
显然,这里有两个关键的问题需要解决:
1)如何得到基学习器的权重系数\(\alpha_m\)?
2)如何更新训练样本权重\(W\)?
那么Adaboost是怎么解决的呢?,接下来,我们就先描述AdaBoost算法是怎么实现的,然后说明为什么是这样的实现方式。
3. AdaBoost算法实现
考虑二分类问题(标准AdaBoost算法只适用于二分类任务),给定数据集
其中,\(x_i\)是一个含有\(d\)个元素的列向量,即\(x_i\in \mathcal{X} \subseteq \mathbf{R}^d\),\(y_i\)是标量,\(y \in \{+1,-1\}\)。
AdaBoost算法实现步骤:
1)初始化样本的权重:
初始时所有样本的权重相等。
2)对\(m=1,2,\cdots,M\),重复以下操作得到\(M\)个基学习器:
- 按照样本的权重分布\(W_m\)训练数据得到第\(m\)个基学习器\(G_m(x)\):
- 计算\(G_m(x)\)在加权训练数据集上的分类误差率:
上式中\(I(\cdot)\)是指示函数,括号里的条件成立其取值为1,否则为0。\(P(G_m(x_i) \neq y_i)\)表示编号为\(m\)的基分类器\(G_m(x)\)对\(x_i\)的预测标记与\(x_i\)的真实标记\(y_i\)之间不一致的概率,记为\(\epsilon\)。
- 计算\(G_m(x)\)的权重系数(即最终集成时使用的基学习器的权重):
- 更新训练样本的权重:
其中,\(Z_m\)是归一化因子,目的是为了使\(W_{m+1}\)的所有元素和为1。即
3)构建最终的分类器线性组合
最终,得到的分类器为
由式\((3.3)\)可知,当基学习器\(G_m(x)\)的误差率\(\epsilon_m \le 0.5\)时,\(\alpha_m \ge 0\),并且\(\alpha_m\)随着\(\epsilon_m\)的减小而增大,即分类误差率越小的基学习器在最终集成时占比也越大。即AdaBoost能够适应各个弱分类器的训练误差率,这也是它的名称中”适应性(Adaptive)”的由来。
由式\((3.5)\)知, 被基学习器\(G_m(x)\)误分类的样本权值得以扩大,而被正确分类的样本的权值被缩小。
需要注意的是式\((3.7)\)中所有的\(\alpha_m\)的和并不等于1(因为没有做一个softmax操作),\(f(x)\)的符号决定了所预测的类,其绝对值代表了分类的确信度。
严格地讲,Boosting算法(包括AdaBoost)在训练的每一轮都要检查当前生成的基学习器是否满足基本条件(例如,检查当前基分类器是否是比随机猜测好) ,一旦条件不满足,则当前基学习器即被抛弃,且学习过程停止。在此种情形下,初始设置的学习轮数\(M\)也许遥远未达到,可能导致最终集成中只包含很少的基学习器而性能不佳。
4. AdaBoost算法推导
上节描述的AdaBoost算法乍看上去像一个脑洞大开想出来的算法,因为有一些让人不解的地方,比如:为什么基分类器的权重计算公式是这样的?为什么样本权重的更新公式是这样的?事实上,它们是可以推导出来的。AdaBoost 算法有多种推导方式,比较容易理解的是基于“加法模型和指数损失函数”进行推导。
由图2及算法实现结果可以看出,AdaBoost最后得到的强学习器是一系列的基学习器的线性组合,此即加法模型(Additive Model):
其中\(G_{m}(x)\)为基学习器,\(\alpha_m\)为基学习器的权重系数。
给定数据集\(D=\{(x_{1},y_{1}),(x_{2},y_{2}),\cdots(x_{N},y_{N})\}\)。在第\(m\)步,我们的目标是最小化一个指定的损失函数\(L(y,f(x))\),即
通常这是一个复杂的优化问题。可以根据前向分步算法求解这一优化问题: 因为最终模型是一个加法模型,如果能从前往后,每一步只学习一个基学习器\(G_m(x)\)及其权重\(\alpha_m\), 不断迭代得到最终的模型,那么就可以简化问题复杂度。具体的,当我们经过\(m−1\)轮迭代得到了最优模型\(f_{m−1}(x)\)时,因为
这样在第\(m\)步我们只需就当前的\(\alpha_m\)和\(G_m(x)\)最小化损失函数
求解上式即可得到第\(m\)个基学习器\(G_m(x)\)及其权重\(\alpha_m\)。
最终,通过不断迭代就求得了从\(m=1\)到\(m=M\)的所有基学习器及其权重,问题得到了解决。
AdaBoost采用的损失函数为指数损失函数(Exponential Loss),形式如下:
周志华《机器学习》p174有证明,指数损失函数是分类任务原本0/1损失函数的一致(consistent)替代损失函数,由于指数损失函数有更好的数学性质,例如处处可微,所以我们用它替代0/1损失作为优化目标。
结合式\((4.4)\)和\((4.5)\),我们现在的目标是在指数损失函数最小的情况下求得基学习器\(G_m(x)\)及其权重\(\alpha_m\),即
这里将指数函数拆成了两部分,已有的强学习器,以及当前基学习器对训练样本的损失函数,前者在之前的迭代中已经求出,可以看成常数。
设\(w_{i}^{(m)} = e^{-y_{i}f_{m-1}(x_{i})}\),由于\(w_i^{(m)}\)只和前面迭代得到的强学习器有关,不依赖于当前的基学习器\(G_m(x)\)及其权重\(\alpha_m\),所以可认为其是第\(m\)步训练之前赋予每个样本的权重。然而\(w_i^{(m)}\)依赖于\(f_{m-1}(x_{i})\),所以每一轮迭代会改变。于是,目标函数\((4.6)\)可以简化为:
这个优化问题可以分两步求解,首先将\(\alpha\)看成常数,由于\(y_i\)和\(G(x_i)\)的取值只能为\(+1\)或\(-1\),要让上面的目标函数最小化,必须让二者相等。因此损失函数对\(G_m(x)\)的最优解为:
上式将指数函数换成指示函数是因为前面说的指数损失函数和0/1损失函数是一致等价的。
其中,\(I(\cdot)\)是指示函数,根据括号里的条件是否成立其取值为0或1。
式\((4.8)\)所示的优化问题其实就是AdaBoost算法的基学习器的学习过程,得到的\(\hat{G}_m(x)\)是使第\(m\)轮加权训练数据分类误差最小的基分类器。
于是,得到基学习器\(\hat{G}_m(x)\)之后,优化目标可以表示成\(\alpha\)的函数,将式\((4.7)\)展开:
式\((4.9)\)对\(\alpha_m\)求导并令导数为0,即
解得
其中\(\epsilon_m\)是分类误差率:
如果式\((4.12)\)中的\(w_{i}^{(m)}\)归一化成和为1的话,那么式\((4.12)\)也就和式 \((3.2)\)一模一样了,进一步地也有上面的\(\hat{\alpha}_m\) 也就是式\((3.3)\)的 \(\alpha_m\)。
最后来看看每一轮样本权值的更新,由\((4.3)\) 和\((4.7)\)可得
如果将式\((4.13)\)进行归一化成和为1的话,就与式\((3.5)\)完全相同了。
由此可见,AdaBoost算法实现步骤是可以经过严密推导得来的。总结一下,本节推导有如下关键点:
- AdaBoost算法是一个加性模型,将其简化成前向分步算法求解;
- 将0/1损失函数用数学性质更好的指数损失函数替代。
5. AdaBoost算法采用指数损失的原因
上一节提到,指数损失函数是分类任务原本0/1损失函数的一致的(consistent)替代损失函数。下面简单的看一下原因。
若将指数损失表示为期望值的形式:
由于是最小化指数损失,则将上式求导并令其为0:
于是有
仔细看,这不就是logistic regression吗?二者只差系数\(\frac{1}{2}\),因此每一轮最小化指数损失其实就是在训练一个logistic regression模型,以逼近对数几率 (log odds)。
于是,
这意味着\(sign(f(x))\)达到了贝叶斯最优错误率,即对于每个样本\(x\)都选择后验概率最大的类别。若指数损失最小化,则分类错误率也将最小化。这说明指数损失函数是分类任务原本0-1损失函数的一致性替代函数。由于这个替代函数是单调连续可微函数,因此用它代替0-1损失函数作为优化目标。
6. AdaBoost算法正则化和Weight Trimming
对每个基学习器乘以一个系数\(ν(0 \lt ν \le 1)\),使其对最终模型的贡献减小,从而防止学的太快产生过拟合。\(ν\)又称学习率(learning rate),于是上文的加法模型就从:
变为
一般\(ν\)要和迭代次数\(M\)结合起来使用,较小的\(ν\)意味着需要较大的\(M\)。通常我们用步长和迭代最大次数一起来决定算法的拟合效果,现实中常用交叉验证进行选择。
Weight trimming不是正则化的方法,其主要目的是提高训练速度。在AdaBoost的每一轮基学习器训练过程中,只有小部分样本的权重较大,因而能产生较大的影响,而其他大部分权重小的样本则对训练影响甚微。Weight trimming的思想是每一轮迭代中删除那些低权重的样本,只用高权重样本进行训练。具体是设定一个阈值 (比如90%或99%),再将所有样本按权重排序,计算权重的累积和,累积和大于阈值的权重 (样本) 被舍弃,不会用于训练。注意每一轮训练完成后所有样本的权重依然会被重新计算,这意味着之前被舍弃的样本在之后的迭代中如果权重增加,可能会重新用于训练。
根据 [Friedman et al., 2000] 中的描述,weighting trimming可以提高计算效率,且不会牺牲准确率。
7. AdaBoost算法小结
到这里Adaboost就写完了,前面有一个没有提到,就是基学习器的类型。理论上任何学习器都可以用于Adaboost。但一般来说,使用最广泛的Adaboost基学习器是决策树和神经网络。
这里对Adaboost算法的优缺点做一个总结。
Adaboost的主要优点有:
1)Adaboost作为分类器时,分类精度很高
2)在Adaboost的框架下,可以使用各种回归分类模型来构建基学习器,非常灵活。
3)作为简单的二元分类器时,构造简单,结果可理解。
4)不容易发生过拟合
Adaboost的主要缺点有:
1)对异常样本敏感,异常样本在迭代中可能会获得较高的权重,影响最终的强学习器的预测准确性。
参考来源:
1)机器学习 - 周志华