Lesson 09
集成方法:组合弱学习器变强
单棵决策树容易过拟合,但把多棵树组合起来就能大幅提升泛化能力。本章涵盖 Bagging(随机森林)、Boosting(GBDT)和 Stacking 三大集成范式。
本章细分学习地图
| 模块 | 拆细学习单元 | 完成后应产出 | 掌握标准 |
|---|---|---|---|
| Bagging | 自助采样、并行训练、投票/平均。 | 随机森林代码。 | 能说清 Bagging 降低方差的机制。 |
| Boosting | 串行纠错、学习率、迭代次数。 | GBDT 代码。 | 能说清 Boosting 降低偏差的机制。 |
| Stacking | 元学习器、交叉验证生成元特征。 | Stacking 示例。 | 能解释 Stacking 和投票的区别。 |
| 特征重要性 | feature_importances_ 解读。 | 重要性排序输出。 | 能解释不纯度重要性的偏差和替代方案。 |
学习目标
集成方法分类
1Bagging(并行)
2Boosting(串行)
3Stacking(元学习)
本章完成度
已完成 0/4
Bagging 与随机森林
Bagging(Bootstrap Aggregating)的核心思想:从训练集中有放回地采样多份子集,各自训练一棵树,最后投票(分类)或平均(回归)。
随机森林 = Bagging + 特征随机
每次分裂时只考虑随机选出的一部分特征,进一步降低树之间的相关性,减少方差。
为什么降方差
多个独立模型的平均预测比单个模型更稳定。自助采样和特征随机让每棵树尽可能"不同"。
from sklearn.datasets import load_wine
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
X, y = load_wine(return_X_y=True)
rf = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=42)
scores = cross_val_score(rf, X, y, cv=5)
print(f"随机森林准确率: {scores.mean():.3f} ± {scores.std():.3f}")
# 特征重要性
rf.fit(X, y)
feature_names = load_wine().feature_names
for name, imp in sorted(zip(feature_names, rf.feature_importances_),
key=lambda x: -x[1])[:5]:
print(f" {name}: {imp:.3f}")
Boosting 与 GBDT
Boosting 串行训练弱学习器,每一轮新模型重点关注前一轮预测错误的样本,逐步降低偏差。
| 算法 | 核心思想 | sklearn 类 |
|---|---|---|
| AdaBoost | 调整样本权重,让下一棵树关注难样本。 | AdaBoostClassifier |
| Gradient Boosting | 每棵树拟合前一轮的残差(梯度方向)。 | GradientBoostingClassifier |
| HistGradientBoosting | 基于直方图的快速 GBDT,大数据集首选。 | HistGradientBoostingClassifier |
from sklearn.datasets import load_wine
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import cross_val_score
X, y = load_wine(return_X_y=True)
gb = GradientBoostingClassifier(
n_estimators=100, learning_rate=0.1, max_depth=3, random_state=42
)
scores = cross_val_score(gb, X, y, cv=5)
print(f"GBDT 准确率: {scores.mean():.3f} ± {scores.std():.3f}")
学习率与树的数量
learning_rate 越小,每棵树的贡献越小,需要更多树(n_estimators 更大)才能收敛。通常 learning_rate=0.1 + n_estimators=100~500 是不错的起点。
Stacking
Stacking 用多个不同类型的模型(基学习器)做预测,再用一个元学习器(meta-learner)学习如何组合这些预测。
from sklearn.datasets import load_iris
from sklearn.ensemble import StackingClassifier, RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score
X, y = load_iris(return_X_y=True)
estimators = [
("rf", RandomForestClassifier(n_estimators=50, random_state=42)),
("svc", SVC(kernel="rbf", probability=True, random_state=42)),
]
stack = StackingClassifier(
estimators=estimators,
final_estimator=LogisticRegression(max_iter=1000),
cv=5,
)
scores = cross_val_score(stack, X, y, cv=5)
print(f"Stacking 准确率: {scores.mean():.3f} ± {scores.std():.3f}")
Bagging vs Boosting 对比
| 维度 | Bagging(随机森林) | Boosting(GBDT) |
|---|---|---|
| 训练方式 | 并行,互不依赖。 | 串行,后一棵依赖前一棵。 |
| 降什么 | 降方差(减少过拟合)。 | 降偏差(提升拟合能力)。 |
| 对噪声 | 更鲁棒。 | 对噪声和离群点更敏感。 |
| 调参 | n_estimators、max_depth。 | n_estimators、learning_rate、max_depth。 |
练习题
第 1 题:随机森林中"特征随机"的作用是什么?
参考思路:让每棵树在不同特征子集上分裂,降低树之间的相关性,从而使集成的方差降得更低。如果每棵树都用最强特征分裂,树会很相似,集成效果有限。
第 2 题:GBDT 的 learning_rate 设得太大会怎样?
参考思路:每棵树的贡献过大,容易过拟合,且收敛不稳定。通常搭配较大的 n_estimators 使用较小的 learning_rate。
检查点
离开本章前,请确认:
- 能解释 Bagging 降方差和 Boosting 降偏差的核心机制。
- 能用 RandomForestClassifier 和 GradientBoostingClassifier 完成分类。
- 能从 feature_importances_ 中解读并排序特征重要性。
- 能说清 Stacking 与简单投票的区别。