查看原文
其他

第8.12节 AdaBoost原理与实现

空字符 月来客栈 2024-01-21

各位朋友大家好,欢迎来到月来客栈,我是掌柜空字符。

本期推送内容目录如下,如果本期内容对你有所帮助,欢迎点赞、转发支持掌柜!

  • 8.12 AdaBoost原理与实现
    • 8.12.1 算法思想
    • 8.12.2 算法原理
    • 8.12.3 示例代码
    • 8.12.4 前向分步加法模型
    • 8.12.5 AdaBoost求解
    • 8.12.6 从零实现AdaBoost算法
    • 8.12.7 小结
    • 引用

8.12 AdaBoost原理与实现

通过第8.9.4节内容的介绍,我们对于Boosting集成学习的基本思想已经有了一定的了解。在本节内容中,笔者将会介绍Boosing算法中第一种常见的提升算法——AdaBoost (Adaptive Boosting) [1]。

8.12.1 算法思想

AdaBoost算法是由Freund 和 Schapire等人于1997年所提出[2],它是一种自适应的提升算法,其核心思想在于AdaBoost会为每个样本赋予一个权重值,在上一个模型中被错分的样本在下一个模型中将具有更高的权重,以此来尽可能保证每个样本都能够被划分正确,最后再将每个模型的预测结果集成起来作为最终的预测输出。下面通过一个实际的示例来介绍AdaBoost算法的思想。

图 8-46. 数据样本分布图
如图8-46所示图中一共有10个样本点,包含方块和圆形两个类别。假定现在通过某种算法构建了模型1(每个样本点具有相等的权重值)并对图8-46中的样本进行分类,得到的分类结果如图8-47所示。

图 8-47. 模型1分类结果图
从图8-47的分类结果可知,样本③和④被划分到了错误的类别中,因此我们可以再次构建模型2并同时赋予样本③和④更高的权重,并对所有样本点进行分类,最终可以得到图8-48中的分类结果。

图 8-48. 模型2分类结果图
从图8-48的分类结果可知,此时样本③和④已经被正确划分了,但是样本⑦和样本⑨却又出现了错误,于是可以再次构建模型3并同时赋予样本⑦和⑨更高的权重,并对所有样本点进行分类,最终可以得到图8-49中的分类结果。

图 8-49. 模型3分类结果图
从图8-49的分类结果可知,此时模型3并没有同时将样本⑦和样本⑨同时都分类正确,同时样本②和④也被误分了。此时,可以再次构建模型4并同时赋予样本②④⑦更高的权重,并对所有样本点进行分类,最终可以得到图8-50中的分类结果。

图 8-50. 模型4分类结果图
从图8-50所示的结果可以看出,模型4为了同时将方形和样本④分类正确,导致样本①②⑥⑦均分类错误。此时可以发现,虽然上述4个模型均没有将所有样本都正确的分类,但是我们最后可以将4个模型的结果集成起来看做一个模型的输出结果,如图8-51所示。

图 8-51. 集成模型分类结果图
根据图8-51可知,以先前的4个模型为基础,然后以某种策略将各个模型的输出结果集成起来作为最终的预测输出,这样便可以得到一个相较于单个模型更好的预测结果(模型1到模型4的分类准确率分别为0.8,0.8,0.7,0.6,而最终集成模型的准确率为0.9)。当然,事实上如果再构建一个模型5便可以实现百分之百的准确率。

以上就是AdaBoost算法的核心思想,从这里也可以看出AdaBoost算法本质上也可以看做是一种模型的训练策略(这也类似于在第12.1节中将要介绍的Self-Training算法),不管是任何模型都可以采用AdaBoost策略来进行建模,只是对于不同的算法在如何融入样本权重来进行建模有不同的做法。

8.12.2 算法原理

在介绍完AdaBoost算法的核心思想后,接下来再来看AdaBoost的具体计算原理[2]。假设个弱分类器,数据集一共有个样本,则AdaBoost算法可以通过如下过程来进行表示:

(1) 初始化每个样本的权重为

(2) 根据式(8.86)~式(8.87)分别计算每个分类器对应下的分类器误差,分类器权重和样本权重及标准化

(3) 将训练得到的个根据式(8.89)中的方式进行集成,然后输出得到样本的预测结果:

其中为指示函数,条件成立是取1,不成立时取0。

从式(8.86)可以看出,如果每个样本都是等权重的话,那么则是计算对应分类结果的错误率。同时,从式(8.86)~式(8.89)的计算过程也可以再次看出,AdaBoost算法并不是某种特定算法的称谓,而是一种模型训练和预测的策略,只是在大多数情况下都是选择决策树作为原始的弱分类器,因此不少人很容易就将AdaBoost与树模型画上了等号。

8.12.3 示例代码

在sklearn中,可以通过sklearn.ensemble中的AdaBoostClassifier来导入AdaBoosting集成学习方法中的分类模型。下面先来介绍一下AdaBoostClassifier类中常见的重要参数及其含义。

1 from sklearn.ensemble import AdaBoostClassifier
2 def __init__(self,
3     base_estimator=None,
4     n_estimators=50,
5    learning_rate=1.):

上述代码是类BaggingClassifier初始化方法中的部分参数,其中base_estimator表示所使用的基模型,如果设置未None则模型使用决策树;n_estimators表示基模型的数量,默认为50个;learning_rate用来控制每个基模型的贡献度,即在式(8.87)的后面再乘以这个系数(这只是sklearn在实现时所新加入的参数),默认为1,即等权重。

下面以决策树作为基模型通过sklearn中的AdaBoostClassifier类来进行Boosting集成学习建模,完整代码见Book/Chapter08/ 04_AdaBoosting.py文件。

1 x_train, x_test, y_train, y_test = load_data()
2 dt = DecisionTreeClassifier(criterion='gini', max_features=4, max_depth=1)
3 model = AdaBoostClassifier(base_estimator=dt, n_estimators=100)
4 model.fit(x_train, y_train)
5 print("模型在测试集上的准确率为:", model.score(x_test, y_test)) # 1.0

在上述代码中,第2行是定义决策树基模型(弱分类器);第3行是定义AdaBoost分类器,并将决策树基模型作为参数传入到类AdaBoostClassifier中。

到此,对于AdaBoost的示例用法就介绍完了。不过细心的读者可能会问,此时基分类器决策树和AdaBoost均有自己的超参数,如果要在上述训练过程中使用网格搜索GridSearchCV该怎么操作呢?关于这部分内容笔者在此就不做介绍,可以直接参见示例代码Book/Chapter08/05_AdaBoosting_gridsearch.py文件。

8.12.4 前向分步加法模型

在第8.12.2节内容中,虽然我们已经完整介绍了AdaBoost算法的计算流程,但有一个疑问便是为什么这样做是有效的。事实上,在AdaBoost算法提出若干年之后Friedman等人才提出从损失函数的视角来给予了它一个合理解释的方法,也被称之为前向分步加法模型(Forward Stagewise Additive Modeling)[3]。在前向分步加法模型中,当使用指数损失作为模型的损失函数时,其最终优化得到结果便是AdaBoost模型。

在许多分类和回归模型中,它们都可以表示为一系列简单模型的线性组合形式,如式(8.90)所示。

其中表示模型个数;表示输入样本;均为模型对应的参数。

通常情况下,所有模型对应的参数都是通过在训练集上最小化某一损失函数优化而来,如式(8.91)所示。

其中式(8.91)的含义是,对于任意一个模型来说,总能在训练样本上找到一组最优的模型参数,即使得整体的损失值最小。

根据式(8.91)的形式可知,如果直接对其进行优化通常来说比较困难,而一种可行的办法则是使用贪婪地做法分步对每个模型进行优化求解,即

例如在第步的优化过程中,待求解的模型为,而整体的损失定义为

其中

这样,在每一步优化结束后都能求解得到对应模型的参数,进而求解得到所有模型对应的参数。同时,需要注意的是式(8.90)中的和这里的并不是一回事。

以上便是前向分步加法模型的整体思想,下面再来看当损失函数为指数损失时的具体情况。

为你认可的知识付费,欢迎订阅本专栏阅读更多优质内容!

8.12.5 AdaBoost求解

继续滑动看下一个

第8.12节 AdaBoost原理与实现

空字符 月来客栈
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存