本文会详细介绍 Adaboost (Adaptive Boosting) 这一 ensemble 模型(属于 boosting)。
这属于集成(ensemble)算法中的提升(boosting)方法,是迭代算法。我们每一轮迭代寻找一个合适的 weak learner 集成到模型中(本质上是梯度下降),通过 T 轮的迭代来集成出一个强分类器,这是一个 boosting 提升过程。
这涉及实现提升的细节。所有的样本都有自己的 weight,初始化时一致。training 时每一轮迭代,我们要更新所有样本的 weight,模型正确判别的样本 weight 减小,而错误判别的样本 weight 增加。这就是 Adaboost 的核心了,这非常像一个我们依据错误经验持续学习的过程。
本算法数学上可以解释为类似在函数空间上做最速梯度下降。每次迭代中,选择的 weak classifier 函数其实是当前负梯度方向,而对应的权值则是在此方向使 loss 减少最多的步长(greedy~)。这里使用的 loss function 是 exponential function,而 GBDT(gradient boost decision tree)推广到了其他 error function,也可以说 AdaBoost 是一种 GBDT。
实际上不同 Adaboost 版本的细节策略略有不同,这里讲解的是Viola-Jones 的 Real-Time Face Detection 论文(AdaBoost 的一个著名的成功应用)中使用的版本。
假设我们有 N 个样本 D=[(x1,y1),(x2,y2),...,(xn,yn)] ,其中 x 为特征向量, y 为 0/1 分类的 label。
我们要迭代训练 T 轮,样本集 weight 向量 ut=1,2...T 初始化为 ut=1=[1N,1N,...,1N] ,即 N 个样本的重要性一开始是一致的,且和为 1。
(这是正例负例等比例的情况,不等比例时,可以假设正例 M 个而负例 L 个则初始化为 ut=1=[12M,12M,...,12L,12L] ,即保证正负例各自总权重皆为 12 )
(对于第 t 轮迭代)
选取 weak classifier 并计算 error:
根据当前样本权重 ut 获取一个当前最好的 weak classifier ht(x) 函数(训练一个 decision tree 或者 decision stump),函数输出 0/1 结果,其相关 error 为 ϵt=1N∑Ni=1uti|ht(xi)−yi| 。这里应该有 0≤ϵt<0.5 ,因为我们要求 weak classifier 至少优于乱猜。
更新训练集样本权重:
针对 ϵt ,我们设置一个核心变量 scaling factor st=1−ϵtϵt ( 1<st<∞ ),并更新样本集 weight :
确认此 weak classifer 权重:
会根据本轮 ht(x) 的表现给予它一个权重 αt=ln st ( 0<αt<∞ );当 ϵt=0 时, αt=∞ 即对于完美的 classifier 我们可以给到无穷大的权重;而当 ϵt=0.5 时, αt=0 即对于乱猜的 classifier 直接不予集成。可见 error 越小的分类器权重越大。
历经 T 轮训练后,将 T 个 ht(x) 线性集成为 strong classifier。实际上集成的参数在迭代过程中已经决定了,这又称为 linearly on the fly with theoretical guarantee,涉及的理论验证之后会详述。
这里把训练流程中的 weak classifier 单独拿出来详细说明。
Random Forest 也是 ensemble 集成算法,属于 bagging 类别,通过 bootstrap 来 uniformly aggregate 了一组等权重的 decision tree,然后通过投票给出整体结果。这是使用 classification(输出 0/1 结果) 或者 regression decision tree 都可以。
这个也是 weak classifier 集成为 strong classifier 的过程,但是集成思想和 Adaboost 不一致(bagging vs. boosting)。Adaboost 也可以使用 classification decision tree 作为 weak classifier,但更常用的是更 weaker 的 decision stump。这里还可以想象一下,我们如果给 Adaboost 一个 fully grown 的 decision tree,那么可能会有 ϵ=0,s=∞ ,训练就崩坏了~ 所以即使用 decision tree 也要做约束出弱的树,而不是像 Random Forest 那样 fully grown。
这个是一个弱弱的 weak classifier,类似只有 1 层的树,只剩一个树桩了。具体公式如下:
Adaboost 常用 decision stump 作 weak classifier,即训练流程中寻找的 h(x) 就是 decision stump。在样本集 N-samples 和 特征空间 M-dimensions 中结合当时样本 weight 学习到最优 h(x) 其实是一个搜索过程,也可以看做是 feature selection;目标是最小化加权 error rate:(VJ 版本的 uti 保证和为 1,所以下式不需要再除以 ∑Ni=1uti )
(本节参考了 Hsuan-Tien Lin 机器学习技法课程)
Adaboost 凭什么能完成 weak classifiers to strong classifier?凭什么可以收敛?可以越来越好?我们可以从数学层面(steepest decent with approximate functional gradient)找到充分解释,本节详细阐述。
之前“2. 训练流程详解”使用的是 VJ 论文中原版公式。这里为了更清晰解释数学理论,会改动一些公式定义:
改变 scaling factor s 公式为 st=1−ϵtϵt‾‾‾‾‾‾‾√ ,比之前版本多了一个 square root,取值范围不变,这是为了方便后续数学推导
样本权重 u 公式更改为下述,这个改动也不大,也是为了方便后续数学推导(原公式只考虑 scale up,然后 normalize;现在加入 scale down 而去掉了麻烦的 normalize):
根据 αt=lnst 可以有 st=exp{α} ,
进而可以对样本权值公式进一步变换:
这实际上就是 Adaboost 的目标就是 exponential error 越来越小(最优化问题),也可以说是让所有样本的权值越来越小;最终 error/loss function 为所有样本的 exponential error 之和:
上述的 exponential error 实际上可以找到直观解释。先变化 strong classifier 判别公式如下:
signed and unnormalized margin=yi∑Tt=1αtht(xi)
AdaBoost 的目标是让这个 margin 尽量为正数且最大化,也就是让其负指数尽量小于1且最小化,也就是我们之前得到的 error/loss function。
另外,因为使用了 exponential,分类错误的 penalty 呈指数增长 (1,∞) ;而一旦分类正确,则 penalty 只在 (0,1) 范围。这里有个问题是 AdaBoost 对噪声或脏数据敏感。
Gradient Descent 标准套路是我要从当前位置(模型状态)走一小步,让 loss 最快的下降(减少):
目标其实是找到一个让 loss 函数下降最快的方向 v ,上式的约等于号是一阶泰勒展开,再加上其他数学工具可以证明最优的方向是负梯度方向 v=−∇E(wt) 。
AdaBoost 的套路很类似,核心是其通过新加入函数来完成梯度下降,这个函数对应最速下降的方向,而函数的权重对应了下降的步长。AdaBoost 在第 t 轮迭代时,优化目标如下:
这里特别重要的一点是, ht(x) 确定的是方向,它的 scale 理论上是没有意义,这种情况下我们一般会约束其 scale(例如标准 GBDT 中就会)。但是!在 AdaBoost 中,我们的 ht(x) 本身的输出只是 -1/1 状态,本身就没有 scale 的概念,所以不需要额外约束!
对上述目标进一步变化:
Recap 一下,我们想找到一个方向 ht(x) 使 ϵt 最小。这本身就是 AdaBoost 定义的 weak classifier ht(x) 的选取标准,一般是通过在特征空间上搜索选取 Decision Stump 实现,这一过程近似地获取到最速下降方向。
我们在上一小节中已经确认了让 AdaBoost loss function EADA 最速下降的方向是某一 ht(x) ,我们接下来需要考虑在这个方向要走多大的一步( η )?
对于 Gradient Descent 的标准套路, η 会作为一个训练的超参数(学习率),可以尝试定义不同的值,然后通过 validation 选择合适的学习率;有时还会加入 annealing 退火机制或其他机制来动态调节学习率。但是在 AdaBoost 中,我们每走一步的代价是巨大的:
所以,我们希望每走一步,都尽可能走最大的一步,尽量减少走的步数。上一小节,我们固定 η ,通过 minhEADA^ 确定了 ht(x) 方向(approximate functional gradient);现在,我们使用这个 ht(x) ,通过 minηEADA^ 来走出减少 loss 的最大的一步(greedily faster),这个套路被称为 Steepest Descent。以下进行最优 η 的推导(注意这里使用了泰勒展开之前的准确 loss 公式):
现在可以完整地说:AdaBoost 每一次迭代,会选取一个函数 ht(x) 近似 loss 最速下降方向,并计算 αt 作为当前最优下降步长,来集成这个新的 weak classifer;本质上是做梯度下降,这是 AdaBoost 的理论基础。