机器学习基础:集成学习
本文系统介绍了集成学习的概念、分类及典型算法。集成学习通过组合多个弱学习器提升模型性能,主要分为Bagging(如随机森林)和Boosting(如Adaboost、GBDT、XGBoost)两类。详细解析了随机森林的Bootstrap抽样机制、Adaboost的权重调整策略、GBDT的残差拟合方法,以及XGBoost的正则化改进和二阶泰勒展开优化。通过房价预测案例直观展示了GBDT的迭代过程,并提
一、前言
集成学习的内容光靠文本图片是有点难懂的,建议配合视频学习并多尝试自己梳理。但如果是代码层面的话,基本上就是一个API涵盖了。因此,从实际上来说,我们只需要了解就行,无需压力过大
二、集成学习思想
2.1 概念
集成学习是使多个弱学习器组合成一个更强大的学习器,解决单一预测,进步一得到更好性能。
2.2 集成学习分类
2.2.1 Bagging
常见基于Bagging的集成学习算法:随机森林
特点:
① 有放回的抽样(bootstrap抽样)产生不同的训练集,从而训练不同的学习器
② 通过平权投票、多数表决的方式决定预测结果
③ 并行训练
思想图如下:

2.2.2 Boosting
常见基于Boosting的集成学习算法:Adaboost、GBDT、XGBoost、LightGBM
特点:
① 每一个训练器重点关注前一个训练器不足的地方进行训练
② 通过加权投票的方式,得出预测结果
③ 串行训练
④ 随着学习的积累从弱到强,每新加入一个弱学习器,整体能力就会得到提升
思想图如下:

2.2.3 Bagging和Boosting对比

三、随机森林算法
3.1 概念
随机森林是基于 Bagging 思想实现的一种集成学习算法,采用决策树模型作为每一个弱学习器
3.2 流程
1、随机选取m条数据
2、随机选取K个特征
3、训练决策树(默认为CART树,关于CART树是什么可以参考本人于2025/9/5发表的《机器学习基础:决策树》)
4、重复1-3的步骤构造n个弱决策树
5、平权投票集成这n个弱决策树
3.3 问题
Q1:为什么要随机抽样训练集?
A1:如果不进行随机抽样,每棵树的训练集都一样,那么最终训练出的树分类结果也是完全一样。
Q2:为什么要有放回地抽样?
A2:如果不是有放回的抽样,那么每棵树的训练样本都是不同的,都是没有交集的,这样每棵树都是“有偏的”,也就是说每棵树训练出来都是有很大的差异的;而随机森林最后分类取决于多棵树(弱分类器)的投票表决。
总结:随机森林算法中弱学习器的训练样本有交集也有差异数据,更容易发挥投票表决效果
3.4 API
随机森林导包:from sklearn.ensemble import RandomForestClassifier
在RandomForestClassifier( )中常用参数:
—— n_estimators:决策树数量
—— max_depth:指定最大声深度,若不设置即max_depth = None表示树会尽可能生长
其他参数不再例举,可在Pycharm中使用Ctrl+点击函数名自行查看
四、Adaboost算法
4.1 概念
Adaptive Boosting(自适应提升)基于 Boosting思想实现的一种集成学习算法,核心思想是通过逐步提高那些被前一步分类错误的样本的权重来训练一个强分类器。
4.2 相关公式
4.2.1 m个弱学习器集成预测公式:
—— sign称为激活函数(符号函数)
—— a为模型的权重
—— 为预测值
输出结果大于0为正类,sign(x)=1
输出结果小于0为负类,sign(x)=-1
输出结果等于0,sign(x)=0
4.2.2 模型权重的计算公式:
—— 为模型权重
—— 表示第t个弱学习器的错误率
4.2.3 样本权重计算公式:

—— 为样本权重
—— 为归一化值(所有样本权重总和)
—— 为模型权重
五、GBDT梯度树
5.1 相关概念
5.1.1 提升树(Boosting Decision Tree)
每一个弱学习器通过拟合残差来构建强学习器
5.1.2 梯度提升树 (Gradient Boosting Decision Tree 即GBDT)
每一个弱学习器通过拟合负梯度来构建强学习器
5.1.3 残差 & 误差
残差 = 真实值-预测值
误差 = 预测值-真实值
5.2 流程
1、初始化
先建立一个初始的弱模型(比如一棵小决策树)。这个模型通常很简单,在很多GBDT库中,初始模型就是所有训练样本目标值的平均值。
2、循环迭代(构建每一棵树)
① 计算残差(负梯度):用当前已经组合好的模型去预测所有样本,然后计算预测值与真实值之间的差异,这个差异就是“残差”。GBDT巧妙地将求解残差的问题,转化为了计算损失函数的负梯度,这让它可以解决更复杂的问题(比如分类问题)
② 训练一棵新树:让一棵新的决策树去学习拟合上一步计算出来的残差(负梯度)。这棵树的目标不是预测原始值,而是预测残差
③ 更新模型:将新训练的树乘以一个学习率(比如0.1),然后加到之前的组合模型上。学习率是一个很小的数,防止我们一步迈得太大而过头(过拟合)
3、最终预测
将所有树的预测结果(严格来说是,初始模型 + 学习率 * 树1的预测 + 学习率 * 树2的预测 + ...)相加,得到最终的预测结果。
5.3 案例——预测房价
5.3.1 数据集
5.3.2 需求:预测目标值
5.3.3 流程
第一步:初始化
我们用一个最简单的模型:所有房价的平均值。 初始预测值 = (200 + 280 + 320) / 3 ≈ 266.7万。 所以,一开始我们对所有房子的预测都是 266.7万。 计算初始残差(误差):
|
真实房价 |
初始预测 |
残差 |
| 200 | 266.7 |
200 - 266.7 = -66.7 |
| 280 | 266.7 |
280 - 266.7 = 13.3 |
| 320 | 266.7 |
320 - 266.7 = 53.3 |
第二步: 构建第一棵树(Tree1)
现在,我们不让Tree1去学习预测真实房价,而是让它去学习预测上一个模型产生的残差。 它的训练数据变成了:
|
房屋面积(平米) |
目标值(要学的残差) |
| 80 |
-66.7 |
| 120 |
13.3 |
| 140 |
53.3 |
假设Tree1根据面积分裂,学会了这样一个规则:
如果面积 < 100平米,预测残差为 -66.7
如果面积 >= 100平米,预测残差为 (13.3 + 53.3)/2 = 33.3
设定学习率(假设为0.3)并更新模型
现在的预测模型 = 初始模型 + 学习率 * Tree1
(1)对于80平米的房子:
新预测 = 266.7 + 0.3 * (-66.7) = 266.7 - 20 = 246.7万 (真实价格是200万,残差从-66.7减小到了 200-246.7 = -46.7,有进步)
(2)对于120和140平米的房子:
新预测 = 266.7 + 0.3 * (33.3) = 266.7 + 10 = 276.7万 (对于280万的房子,残差变为 280-276.7=3.3;对于320万的房子,残差变为 320-276.7=43.3,误差也都减小了)
第三步:构建第二棵树(Tree2)
现在,我们计算当前组合模型(初始+Tree1)的新残差,然后让Tree2去学习这个新的残差
|
房屋面积 |
真实房价 |
当前预测 |
新残差 |
| 80 |
200 |
246.7 |
200 - 246.7 = -46.7 |
| 120 | 280 |
276.7 |
280 - 276.7 = 3.3 |
| 140 | 320 |
276.7 |
320 - 276.7 = 43.3 |
Tree2的目标就是去拟合 [-46.7, 3.3, 43.3] 这个残差序列
如此一轮一轮地下去,每一棵新树都在学习当前模型还没搞定的那部分误差(残差)
树的数量越多,模型越复杂,拟合得越好(但也要小心过拟合)
六、XGBoost算法
6.1 概念
极端梯度提升树XGBoost(Extreme Gradient Boosting)是对GBDT的改进,并且在损失函数中加入了正则化项:

6.2 构建思想
构建模型的方法是最小化训练数据的损失函数:

此时训练的模型复杂度较高,易过拟合
在损失函数中加入正则化项,用以提高对未知的测试数据的泛化性能:

6.3 推导过程
6.3.1 将目标函数变形

将目标函数分离为前t-1项和第t项的和

请注意,我们是在求解第t棵树的损失函数,也就意味着,前t-1棵树已经构建完毕了,因此,前t-1棵树的正则化项可以视为常数,即:

由于我们之后要使用求导的方法(这在损失函数计算中非常常见),而常数求导等于0,所以我们可以提前将这一项抹除,因此目标损失函数可以化简为:

6.3.2 将损失函数用泰勒二阶展开
泰勒二阶展开公式:

设目标函数的一阶导数为,即:

设目标函数的二阶导数为,即:

那么目标函数通过泰勒二阶展开可化为:

XGBoost是一个基于梯度提升的算法,它通过迭代地添加回归树来逐步改进模型的预测能力。在每一轮迭代中,算法都会:
-
计算当前模型的预测误差(残差)。
-
基于这些残差训练一棵新的回归树。
-
将这棵新树添加到模型中,以减少预测误差。
所以这里的 表示在第 t 轮迭代中添加的这棵回归树(6.3.3中详细介绍),它是一个函数,输入特征向量 x,输出预测值
在第t步时,预测值和真实值
都是已知的,故
实际上也是一个常数,由此我们可以将之前的式子进一步化简为:

6.3.3 转化为叶子节点输出
在上一步中我们提到了 表示在第 t 轮迭代中添加的一棵回归树,其表达式如下:

—— 是长度为T的一维向量,代表树q各叶子结点的权重向量
—— 叶子结点的映射关系,代表一棵树的结构,作用是将输入
映射到某个叶子结点(假设这棵树有T个叶子结点)
现在我们来讨论目标损失函数中的,其公式如下:
![]()
包括两个部分,即叶子结点的数量和叶子结点权重向量的L2范数,标注如下:

其中, 和
仅仅是超参,可以在建立模型的时候由程序员手动输入,其作用是限制树的过度生长,防止过拟合
是为了方便在求导过程中与二次幂抵消(如果你完全没有导数基础,理解为方便计算即可)
例如,在下面这棵树中:

我们将的表达和
的表达式代入目标损失函数,即得到:

在进行下一步之前,我们需要理解这个式子的含义
在理解这个式子之前,我们先构建一棵树如下:

如果一组样本被划分至叶子结点D中,那么他们的值都是相同的,都是
在目标损失函数中,表示样本的预测值,可改写如下:

其中:
表示所有叶子结点中所有样本的总数
和
的分别为损失函数的一阶导、二阶导
表示第
个叶子结点,
表示单个样本,
表示属于
号叶子结点中的所有样本
表示叶子结点总数
那么,这个公式可以这样理解:

同理, 可以化为:

那么目标损失函数可化简如下:



令:


代入得最终目标函数【*】:

如果我们要求目标函数的最(小)值,只需对求导并令公式等于0后求解
即可
解得的最优值为:

代回目标函数表达式【*】可得目标函数的最小值:

该公式也叫做打分函数 (scoring function),从损失函数、树的复杂度两个角度来衡量一棵树的优劣。当我们构建树时,可以用来选择树的划分点,具体操作如下式所示:
![]()


根据Gain值(注意这里Gain值已经进行了【分裂前的损失 - 分裂后的损失】):
① 对树中的每个叶子结点尝试进行分裂
② 如果gain > 0,则分裂之后树的损失更小,会考虑此次分裂;反之不建议分裂
③ 当触发以下条件时停止分裂:达到最大深度;叶子结点数量低于某个阈值;所有的结点在分裂不能降低损失等等...
6.4 XGBoost的安装
开始菜单搜索cmd打开命令提示符,或搜索PowerShell,无论你选用哪个,都右键以管理员身份运行,然后键入:
pip install xgboost -i https://pypi.tuna.tsinghua.edu.cn/simple/
或
pip install xgboost -i https://pypi.douban.com/simple/
回车运行安装即可
6.5 XGB编码风格
支持非sklearn方式,也即是自己的风格;
支持sklearn方式,调用方式保持sklearn的形式。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)