机器学习:Adaboost 算法

Adaboost 算法

提升 (boosting) 方法是一种常用的集成学习方法, 其中常见的集成学习框架包括 Bagging, Boosting 和 Stacking. 它通过改变训练样本的权重, 学习多个分类器, 并将这些分类器进行线性组合, 提高分类的性能.

历史上, Kearns 和 Valiant 首先提出了强可学习 (strongly learnable) 和弱可学习 (weekly learnable) 的概念, 指出在概率近似正确 (probably approximately correct, PAC) 学习的框架中, 一个概念 (概率规律) 如果存在一个多项式的学习算法能够学习它 (通过建模抽象拟合), 并且正确率很高, 那么就称这个概念是强可学习的; 一个概念如果存在一个多项式的学习算法能够学习它, 但是学习的正确率仅比随机猜测略好, 那么就称这个概念是弱可学习的. 后来 Schapire 证明在 PAC 学习的框架下, 一个概念是强可学习的充分必要条件是这个概念是弱可学习的.

一般来说, 找到弱学习算法要相对容易一些, 提升方法就是从弱学习算法出发, 迭代地学习一系列弱学习算法 (基学习器), 当前弱学习算法依赖于上一轮学习器的学习过程, 然后组合这些弱学习器, 构成一个强学习器. 大多数的提升方法都是改变训练数据的概率分布 (训练数据的权重分布), 针对不同的训练数据分布调用弱学习算法学习一系列弱分类器.

提升方法中最具代表性的方法就是 AdaBoosting. 其中, Adaboost 通过提高那些被前一轮弱分类器错误分类的样本的权值, 而降低那些被正确分类样本的权值来改变每一轮训练数据的权值或概率分布; 其次 AdaBoost 采用加权多数表决的方法将弱分类器组合成一个强分类器, 并加大分类误差率小的弱分类器的权重, 减小分类误差率大的弱分类器的权重.

AdaBoost 算法 (分类问题)

AdaBoost 二元分类

假设给定一个二类分类 (Adaboost 不仅限于二类分类) 的训练数据集 \(T = \{ (\mathbf{x}_1, y_1), (\mathbf{x}_2, y_2), \cdots, (\mathbf{x}_N, y_N) \}\), 实例 \(\mathbf{x}_i \in \mathcal{X} \subset \mathbb{R}^n\), 标记 \(y_i \in \mathcal{Y} = \{ -1,+1\}\). Adaboost 从训练数据集学习一系列弱分类器或基本分类器, 并将这些弱分类器线性组合成为一个强分类器.

  • 初始化训练数据的权值分布

\[D_1 = (\omega_{11},\cdots,\omega_{1i}, \cdots,\omega_{1N}), \ \omega_{1i} = \frac{1}{N}, \ i = 1,2,\cdots,N \]

假设初始训练数据集为均匀分布 (最大熵原理, 在没有任何先验知识前提下作等概率假设是最合理的), 即每个训练样本在基本分类器的学习中作用相同. 这一假设保证第 1 步能够在原始数据上学习基本分类器 \(G_1(\mathbf{x})\).

  • Adaboost 反复学习基本分类器, 在每一轮 \(m=1,2,\cdots,M\) 顺次执行以下操作:
  1. 使用当前分布 \(D_m\) 加权的训练数据集, 学习基本分类器 \(G_m(\mathbf{x}): \mathcal{X} \rightarrow \{ -1,+1\}\).

  2. 计算基本分类器 \(G_m(\mathbf{x})\) 在加权训练数据集上的分类误差率:

\[e_m = \sum^N_{i=1} P(G_m(\mathbf{x}_i) \neq y_i) = \sum^N_{i=1} \omega_{mi}I(G_m(\mathbf{x}_i) \neq y_i) \]

上式表明 \(G_m(\mathbf{x})\) 在加权训练数据集上的分类误差率是被 \(G_m(\mathbf{x})\) 误分类样本的权值之和, 即对本轮高概率分布的错误会给予更大的惩罚.

  1. 计算 \(G_m(\mathbf{x})\) 的系数:

\[\alpha_m = \frac{1}{2} \log\frac{1-e_m}{e_m} \]

这里的对数为自然对数, \(\alpha_m\) 表示 \(G_m(\mathbf{x})\) 在最终分类器中的重要性. 当 \(e_m \leq \frac{1}{2}\) 时 (这里由选取的弱分类器总是比二类分类问题中随机猜测略好得到的结果), \(\alpha_m \geq 0\), 并且 \(\alpha_m\) 随着 \(e_m\) 的减小而增大, 所以分类误差率越小的基本分类器在最终分类器中的作用越大.

  1. 更新训练数据的权值分布:

\[D_{m+1} = (\omega_{m+1,1},\cdots, \omega_{m+1,i}, \cdots,\omega_{m+1,N}) \]

\[\omega_{m+1,i} = \frac{\omega_{mi}}{Z_m} \exp(-\alpha_m y_i G_m(\mathbf{x}_i)), \ i=1,2,\cdots, N \]

其中 \(Z_m\) 是规范化因子

\[Z_m = \sum^N_{i=1} \omega_{mi} \exp(-\alpha_m y_i G_m(\mathbf{x}_i)) \]

它使 \(D_{m+1}\) 成为一个概率分布. 这里的权值更新也可以写为:

\[\omega_{m+1,i} = \left\{ \begin{aligned} \frac{\omega_{mi}}{Z_m} e^{-\alpha_m}, & G_m(\mathbf{x}_i) = y_i \\ \frac{\omega_{mi}}{Z_m} e^{\alpha_m}, & G_m(\mathbf{x}_i) \neq y_i \end{aligned} \right. \]

由此可知被基本分类器 \(G_m(\mathbf{x})\) 误分类的样本权值扩大 (这里只要 \(e_m \leq \frac{1}{2}\) 就有 \(\alpha_m \geq 0\)), 被正确分类的则缩小.

  • 构建基本分类器的线性组合

\[f(\mathbf{x}) = \sum^M_{m=1} \alpha_m G_m(\mathbf{x}) \]

得到最终分类器

\[G(\mathbf{x}) = \text{sign}(f(\mathbf{x})) \]

注意这里的 \(\alpha_m\) 表示基本分类器 \(G_m(\mathbf{x})\) 的重要性, 所有 \(\alpha_m\) 之和不一定为 \(1\).

AdaBoost 多元分类

对于 Adaboost 多元分类算法, 其原理和二元分类类似, 最主要区别在弱分类器的系数上. 比如 Adaboost SAMME 算法的弱分类器的系数为:

\[\alpha_m = \frac{1}{2} \log\frac{1-e_m}{e_m} + \log(R-1) \]

其中 \(R\) 为类别数, 从上式可以看出, 如果是二元分类, \(R=2\), 则上式和二元分类算法中的弱分类器的系数一致.

对于 multi-class 分类, scikit-learn 库中的 AdaBoostClassifier 实现了 AdaBoost-SAMME 和 AdaBoost-SAMME.R 两种分类算法. SAMME 指离散形式的 Adaboost, 使用预测错误的标签进行调整, 返回离散的类别值, 它使用预测错误的类别标签进行调整. SAMME.R 指 Real AdaBoost, 返回值不再是离散的类型, 而是一个表示概率的实数值, 它使用预测类别的概率进行调整. SAMME.R 收敛速度快, 实现较低的测试错误需要的迭代次数更少, 但必须需要基学习器实现了返回类别的预测概率 (SAMME则不需要), SAMME.R 在较大学习率时对原始数据的拟合能力会出现降低, 而 SAMME 不会.

AdaBoost 算法 (回归问题)

下面总结 AdaBoost 回归问题算法, 以 scikit-learn 库中 AdaBoostRegressor 实现的 AdaBoost.R2 为例, 这是最早 Yoav Freund 和 Robert E. Schapire 论文中 AdaBoost.R 的改进.

给定训练数据集 \(T = \{ (\mathbf{x}_1, y_1), (\mathbf{x}_2, y_2), \cdots, (\mathbf{x}_N, y_N) \}\), 实例特征 \(\mathbf{x}_i \in \mathcal{X} \subset \mathbb{R}^n\), \(y_i \in \mathcal{Y}=\mathbb{R}\), AdaBoost 从训练数据集学习一系列弱回归算法, 并将这些弱回归算法线性组合成为一个强回归算法.

  • 初始化训练数据的权值分布

\[D_1 = (\omega_{11},\cdots,\omega_{1i}, \cdots,\omega_{1N}), \ \omega_{1i} = \frac{1}{N}, \ i = 1,2,\cdots,N \]

  • AdaBoost 反复学习基本分类器, 在每一轮 \(m=1,2,\cdots,M\) 顺次执行以下操作:
  1. 使用当前分布 \(D_m\) 加权的训练数据集, 学习基本回归学习机 \(G_m(\mathbf{x}): \mathcal{X} \rightarrow \mathbb{R}\).

  2. 计算回归学习机 \(G_m(\mathbf{x})\) 在加权训练数据集上的分类误差率:

\[e_m = \sum^N_{i=1} \omega_{mi} e_{mi} \]

这里的 \(e_{mi}\) 是每个训练样本的相对误差, 有不同的取法, 例如线性误差:

\[e_{mi} = \frac{|y_i - G_m(\mathbf{x}_i)|}{E_m} \]

平方误差:

\[e_{mi} = \frac{(y_i - G_m(\mathbf{x}_i))^2}{E_m} \]

指数误差:

\[e_{mi} = 1 - \exp\frac{-|y_i - G_m(\mathbf{x}_i)|}{E_m} \]

其中 \(E_m\) 为训练集上的最大误差, 用以归一化:

\[E_m = \max |y_i - G_m(\mathbf{x}_i)|, \ i=1,2,\cdots,N \]

  1. 计算 \(G_m(\mathbf{x})\) 的系数:

\[\alpha_m = \frac{e_m}{1-e_m} \]

注意这里的系数 \(\alpha_m\) 与分类问题中系数不同, 误差 \(e_m\) 越小, 系数 \(\alpha_m\) 也越小, 越低的 \(\alpha_m\) 会有更高的预测准确度.

  1. 更新训练数据的权值分布:

\[D_{m+1} = (\omega_{m+1,1},\cdots, \omega_{m+1,i}, \cdots,\omega_{m+1,N}) \]

\[\omega_{m+1,i} = \frac{\omega_{mi}}{Z_m} \alpha_m^{1 - e_{mi}}, \ i=1,2,\cdots, N \]

其中 \(Z_m\) 是规范化因子

\[Z_m = \sum^N_{i=1} \omega_{mi} \alpha_m^{1 - e_{mi}} \]

  • 构建最终的回归学习器:

\[f(\mathbf{x}) = G_{m^*}(\mathbf{x}) \]

其中,

\[m^* = \arg \min_k \left\{\sum_{G_m(\mathbf{x}) \leq G_{k}(\mathbf{x})} \log \frac{1}{\alpha_m} \geq \frac{1}{2}\sum_{m=1}^M \log \frac{1}{\alpha_m} \right\} \]

\(m^*\) 可以看作是所有 \(\log \frac{1}{\alpha_m}\) 中的中位数所对应的序号.

AdaBoost 算法的正则化

为了防止 AdaBoost 过拟合, 通常也会加入正则化项 \(\upsilon\), 通常称为步长 (learning rate), 对于前面的弱学习器的迭代:

\[f_{m}(\mathbf{x}) = f_{m-1}(\mathbf{x}) + \alpha_m G_m(\mathbf{x}) \]

加上正则化项后变为

\[f_{m}(\mathbf{x}) = f_{m-1}(\mathbf{x}) + \upsilon \alpha_m G_m(\mathbf{x}) \]

上面相当于在每轮的系数 \(\alpha\) 前加上步长 \(\upsilon\), 其中 \(0 < \upsilon \leq 1\), 对于同样的训练集学习, 较小的 \(\upsilon\) 意味着需要更多的弱学习器的迭代次数, 通常用步长和迭代最大次数一起来决定算法的拟合效果.

Adaboost 算法解释 (以二元分类为例)

可以认为 Adaboost 算法的二元分类问题是一个模型为加法模型, 损失函数为指数函数, 学习算法为前向分步算法时的二类分类学习方法.

前向分步算法

考虑加法模型 (additive model)

\[f_M(\mathbf{x}) = \sum^M_{m=1} \beta_m b(\mathbf{x},\gamma_m) \]

其中 \(b(\mathbf{x},\gamma_m)\) 为基函数, \(\beta_m\)\(\gamma_m\) 分别为基函数的参数和系数, 在给定训练数据及损失函数 \(L(y,f(\mathbf{x}))\) 的条件下, 学习加法模型 \(f(\mathbf{x})\) 成为经验风险极小化即损失函数极小化问题:

\[\min_{\beta_m,\gamma_m} \sum^N_{i=1} L \left( y_i, \sum^M_{m=1} \beta_m b(\mathbf{x}_i,\gamma_m) \right) \]

这是针对所有 \(\beta_m\)\(\gamma_m\) 的最优化问题, 通常这是一个复杂的优化问题, 前向分步算法 (forward stagewise algorithm) 求解这一优化问题的想法是: 从前往后, 每一步只学习一个基函数及其系数, 逐步逼近目标函数式, 那么就可以简化优化的复杂度, 具体地每步只需优化如下损失函数:

\[\min_{\beta,\gamma} \sum^N_{i=1} L \left( y_i, f_{m-1}(\mathbf{x}_i) + \beta b(\mathbf{x}_i,\gamma) \right) \]

给定训练数据集 \(T = \{ (\mathbf{x}_1, y_1), (\mathbf{x}_2, y_2), \cdots, (\mathbf{x}_N, y_N) \}\), 损失函数 \(L(y,f(\mathbf{x}))\), 基函数集 \(b(\mathbf{x},\gamma_m)\), 输出加法模型 \(f(\mathbf{x})\), 前向分步算法如下:

  • 初始化 \(f_0(\mathbf{x}) = 0\), 在每一轮 \(m=1,2,\cdots,M\) 顺次执行以下操作:
  1. 极小化损失函数

\[(\beta_m, \gamma_m) = \arg \min_{\beta,\gamma} \sum^N_{i=1} L \left( y_i, f_{m-1}(\mathbf{x}_i) + \beta b(\mathbf{x}_i,\gamma) \right) \]

得到参数 \(\beta_m\)\(\gamma_m\).

  1. 更新

\[f_{m}(\mathbf{x}) = f_{m-1}(\mathbf{x}) + \beta b(\mathbf{x},\gamma) \]

  • 得到加法模型

\[f(\mathbf{x}) = f_{M}(\mathbf{x}) = \sum^M_{m=1} \beta_m b(\mathbf{x},\gamma_m) \]

这样前向分步算法将同时求解从 \(m=1\)\(M\) 所有参数 \(\beta_m\)\(\gamma_m\) 的优化问题简化为逐次求解各个 \(\beta_m\)\(\gamma_m\) 的优化问题. 需要注意的是这样求解的假设是每一步之间的基函数和系数是独立不相关的, 如果它们之间存在关联则会丢失一部分精确度.

前向分步算法与 Adaboost

Adaboost 算法是前向分步加法算法的一个具体实现, 这时模型是由基本分类器组成的加法模型, 损失函数是指数函数. 具体地来说, 当基函数为基本分类器时, 该加法模型等价于 Adaboost 的最终分类器 \(f(\mathbf{x}) = \sum^M_{m=1} \alpha_m G_m(\mathbf{x})\). 前向分步算法的损失函数是指数损失函数 (exponential loss function)

\[L(y,f(\mathbf{x})) = \exp [-y f(\mathbf{x})] \]

前向分步算法逐一学习基函数的过程与 Adaboost 算法逐一学习基本分类器的过程一致. 假设经过 \(m-1\) 轮迭代前向分步算法已经得到 \(f_{m-1}(\mathbf{x})\):

\[\begin{aligned} f_{m-1}(\mathbf{x}) &= f_{m-2}(\mathbf{x}) + \alpha_{m-1}G_{m-1}(\mathbf{x})\\ &= \alpha_{1}G_{1}(\mathbf{x}) + \cdots + \alpha_{m-1}G_{m-1}(\mathbf{x}) \end{aligned} \]

在第 \(m\) 轮迭代要得到 \(\alpha_m\), \(G_m(\mathbf{x})\)\(f_{m}(\mathbf{x}) = f_{m-1}(\mathbf{x}) + \alpha_{m}G_{m}(\mathbf{x})\), 目标是使得 \(f_{m}(\mathbf{x})\) 在训练数据集上的指数损失最小, 即:

\[\begin{aligned} (\alpha_m, G_m(\mathbf{x})) &= \arg \min_{\alpha, G} \sum^N_{i=1} \exp [-y_i (f_{m-1}(\mathbf{x}_i) + \alpha G(\mathbf{x}_i))]\\ &= \arg \min_{\alpha, G} \sum^N_{i=1} \overline{\omega}_{mi} \exp [-y_i \alpha G(\mathbf{x}_i)] \end{aligned} \]

其中 \(\overline{\omega}_{mi} = \exp[-y_i f_{m-1}(\mathbf{x}_i)]\), 由于 \(\overline{\omega}_{mi}\) 既不依赖于 \(\alpha\) 也不依赖于 \(G\), 因此与最小化无关, 但 \(\overline{\omega}_{mi}\) 依赖于 \(f_{m-1}(\mathbf{x}_i)\), 随着每轮迭代而发生改变. 上面的最小化就相当于第 \(m\) 步的最小化问题. 先求 \(G_m(\mathbf{x})\), 要使得上式取值最小, 即包含 \(y_i \neq G(\mathbf{x}_i)\) 的项要尽可能的少, 此时 \(G_m(\mathbf{x})\) 可以如下得到:

\[G_m(\mathbf{x}) = \arg \min_{G} \sum^N_{i=1} \overline{\omega}_{mi} I(y_i \neq G(\mathbf{x}_i)) \]

接下来求 \(\alpha_m\), 指数损失中的式子可以变形为:

\[\begin{aligned} \sum^N_{i=1} \overline{\omega}_{mi} \exp [-y_i \alpha G(\mathbf{x}_i)] &= \sum_{y_i = G_m(\mathbf{x}_i)} \overline{\omega}_{mi} e^{-\alpha} + \sum_{y_i \neq G_m(\mathbf{x}_i)} \overline{\omega}_{mi} e^{\alpha} \\ &= (e^{\alpha} - e^{-\alpha}) \sum^N_{i=1} \overline{\omega}_{mi} I(y_i \neq G_m(\mathbf{x}_i)) + e^{-\alpha}\sum^N_{i=1} \overline{\omega}_{mi} \end{aligned} \]

将已求解的 \(G_m(\mathbf{x})\) 代入上式, 并对 \(\alpha\) 求导并置 \(0\),

\[(e^{\alpha} + e^{-\alpha}) \sum^N_{i=1} \overline{\omega}_{mi} I(y_i \neq G_m(\mathbf{x}_i)) - e^{-\alpha}\sum^N_{i=1} \overline{\omega}_{mi} = 0 \]

注意到分类误差率为:

\[e_m = \frac{\sum^N_{i=1} \overline{\omega}_{mi} I(y_i \neq G_m(\mathbf{x}_i))}{\sum^N_{i=1} \overline{\omega}_{mi}} \]

代入可以得到使其最小的 \(\alpha_m\)

\[\alpha_m = \frac{1}{2} \log\frac{1-e_m}{e_m} \]

这里的 \(\alpha_m\) 与 Adaboost 中完全一致.

最后来看每一轮样本权值的更新, 由 \(f_{m}(\mathbf{x}) = f_{m-1}(\mathbf{x}) + \alpha_{m}G_{m}(\mathbf{x})\) 以及 \(\overline{\omega}_{mi} = \exp[-y_i f_{m-1}(\mathbf{x}_i)]\) 可以得到:

\[\overline{\omega}_{{m+1},i} = \overline{\omega}_{m,i} \exp[-y_i \alpha_{m}G_{m}(\mathbf{x})] \]

这与 Adaboost 中的样本权值更新仅相差一个规范化因子, 因此等价.

AdaBoost 算法小结

AdaBoost 算法具有很高的精度, 不容易发生过拟合, 并且在 AdaBoost 的框架下, 可以使用各种模型来构建弱学习器, 例如对于决策树, AdaBoost 分类用了 CART 分类树, 而 AdaBoost 回归使用了 CART 回归树.

但是 AdaBoost 对异常样本敏感, 异常样本在迭代中可能会获得较高的权重, 影响最终的强学习器的预测准确性.

scikit-learn Adaboost 类库

在 scikit-learn 中 Adaboost 类库中, AdaBoostClassifier 用于分类, AdaBoostRegressor 用于回归. AdaBoostClassifier 使用了两种 Adaboost 分类算法的实现, SAMME 和 SAMME.R. 而 AdaBoostRegressor 则使用了 Adaboost 回归算法 (Adaboost.R2) 的实现. 当对 Adaboost 进行调参时, 主要要对两部分内容进行调参, 第一部分是对 Adaboost 的框架进行调参, 第二部分是对所选择的弱分类器进行调参.

REFERENCE

  1. 李航. 统计学习方法[M]. 清华大学出版社, 2012.
  2. AdaBoost算法详述
  3. 集成学习之Adaboost算法原理小结
  4. Zhu J , Arbor A , Hastie T . Multi-class AdaBoost[J]. Stats & Its Interface, 2006, 2(3):349-360.
  5. Yoav, Freund, and, et al. A Decision-Theoretic Generalization of On-Line Learning and an Application to Boosting[J]. Journal of Computer & System Sciences, 1997.
  6. Drucker, Harris. (1997). Improving Regressors Using Boosting Techniques. Proceedings of the 14th International Conference on Machine Learning.
posted @ 2020-12-07 21:40  肥嘟嘟左衛門  阅读(418)  评论(0)    收藏  举报