随机森林 + Boosting:让一群弱学习器变成超人
单棵树平庸,一群树投票就能逆天。Kaggle 十年霸主 XGBoost 的来历,就在这一篇。
L2-04 结尾我说”单棵树弱、集成起来无敌”——这一篇展开讲。
集成学习(Ensemble Learning)的核心思想:
多个”差不多”的弱模型组合起来,能远超单个强模型。
这不是 ML 独创——人类社会也是。陪审团(多人独立判断)比单个法官准。专家组(专家共识)比单个专家强。算法世界把这个原则发挥到了极致。
两大思路
集成学习有两大流派,完全不同的”组合方式”:
| 流派 | 中文 | 核心思想 | 代表 |
|---|---|---|---|
| Bagging | 装袋 | 训 N 个独立模型,投票 | 随机森林 |
| Boosting | 提升 | 训 N 个串行模型,后者纠正前者的错 | XGBoost、LightGBM |
两者都用决策树作为”基模型”——但组合方式根本不同。
一、Bagging 和随机森林
Bagging 原理
Bagging = Bootstrap Aggregating。
- 从训练数据有放回采样,构造 N 份”略有差异”的子数据集
- 在每份上独立训练一棵树
- 预测时让 N 棵树投票(分类)或求平均(回归)
关键:每棵树都是在”略有不同”的数据上训出来的,所以它们的错误不会相关——投票时错误互相抵消。
随机森林(Random Forest)
随机森林 = Bagging + 额外的随机性:
每棵树训练时,每次节点分裂只考虑随机选的部分特征(不是全部)。
这一招让每棵树更”独立”,投票效果更好。
用 sklearn
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 100 棵树的随机森林(默认值就很好)
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X_train, y_train)
print(f"准确率: {rf.score(X_test, y_test):.3f}") # 通常 96-97%
L2-04 的单棵决策树拿到 93%——改一行代码,提升到 97%。这就是集成的威力。
重要超参数
| 参数 | 推荐起点 |
|---|---|
n_estimators | 100-500(树越多越稳,但慢) |
max_depth | None(让树长满)或 10 |
max_features | ’sqrt’(每次分裂用 sqrt(N) 个特征) |
min_samples_leaf | 1-5 |
随机森林的优势
✅ 几乎不需要调参就能跑出好结果 ✅ 不容易过拟合(树多 = 投票更稳) ✅ 提供特征重要度(决策树的优势保留) ✅ 能并行训练(每棵树独立)
❌ 慢(100 棵树 vs 1 棵树) ❌ 模型大(要存 100 棵树)
二、Boosting 和 XGBoost
Boosting 原理
完全相反的思路。串行训练:
- 训第 1 棵树
- 看它错在哪——把”错的样本”权重提高
- 训第 2 棵树(用调整后的权重)—— 它专注修正第 1 棵的错
- …重复 N 次
- 最终预测 = N 棵树的加权和
关键直觉:每棵新树都在”补”前面所有树留下的错。
Gradient Boosting
更优雅的版本——把”修正错误”用梯度形式表达:
- 当前预测和真实值的差 = 残差
- 训一棵新树拟合残差
- 加到当前预测上
听起来奇怪?想想 L1-03 的梯度下降——Gradient Boosting 在函数空间做梯度下降。每加一棵树就是沿着损失函数的”负梯度方向”走一步。
XGBoost / LightGBM / CatBoost
XGBoost 是 Gradient Boosting 的”工程化奇迹”——2014 年陈天奇开源后席卷 Kaggle。
后来 Microsoft 出了 LightGBM(更快),Yandex 出了 CatBoost(处理类别特征好)。
今天工业界三巨头:XGBoost、LightGBM、CatBoost——它们的算法都基于 Gradient Boosting,工程优化和细节不同。
用 XGBoost
# 需要先 pip install xgboost
import xgboost as xgb
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
model = xgb.XGBClassifier(
n_estimators=200,
learning_rate=0.05,
max_depth=4,
random_state=42
)
model.fit(X_train, y_train,
eval_set=[(X_test, y_test)],
verbose=False)
print(f"准确率: {model.score(X_test, y_test):.3f}") # 通常 97-98%
一行配置,就能拿到深度学习级别的效果。
重要超参数
| 参数 | 作用 | 调参方向 |
|---|---|---|
n_estimators | 树的数量 | 100-1000 |
learning_rate | 每棵树的贡献权重 | 0.01-0.1(小则需更多树) |
max_depth | 单棵树深度 | 3-8(不像随机森林那么深) |
subsample | 每棵树用多少比例样本 | 0.6-1.0 |
colsample_bytree | 每棵树用多少比例特征 | 0.5-1.0 |
reg_lambda | L2 正则化 | 0-1 |
XGBoost 调参是个艺术,但用默认值通常已经很好——别一上来就调参。
Bagging vs Boosting:怎么选
| 维度 | Random Forest | XGBoost |
|---|---|---|
| 训练速度 | 慢(独立但棵数多) | 慢(串行无法并行) |
| 调参敏感度 | 低 | 高 |
| 过拟合风险 | 低 | 中(需要 early stopping) |
| 性能上限 | 中等-高 | 最高 |
| 推荐场景 | 新项目 baseline | 调好了能赢 Kaggle |
我的经验法则:
- 时间紧 → Random Forest(一行搞定不亏)
- 追求最优 → XGBoost(值得花时间调)
- 数据巨大 → LightGBM(最快)
为什么集成这么强
数学直觉:
如果 N 个模型的错误互相不相关(独立),那么投票后的错误率 ≈ 单模型错误率的 N 次方。
假设单模型对率 70%。 11 个独立模型投票,多数对的概率 ≈ 91%! 21 个 → 97%!
这就是为什么 Kaggle 上集成模型几乎永远赢。
但有个前提:模型必须独立且比随机好。如果都犯同样错,投票也救不了。
现实:模型之间往往不完全独立——它们用同一份数据、同类算法。所以实际收益没有理论那么夸张。但仍然显著比单模型好。
Stacking:终极组合
更狠的玩法:用一个模型来学”怎么组合其它模型”。
- 训练 N 个不同的基模型(决策树、神经网络、线性回归、SVM…)
- 用一个”元模型”(meta-learner)学习”怎么权衡这 N 个的输出”
from sklearn.ensemble import StackingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
stack = StackingClassifier(
estimators=[
('rf', RandomForestClassifier()),
('xgb', xgb.XGBClassifier()),
('svc', SVC(probability=True))
],
final_estimator=LogisticRegression()
)
stack.fit(X_train, y_train)
Kaggle 顶级选手用这一招的多——但工业部署难(模型多、推理慢)。
工业真实情况
Kaggle 比赛 70%+ 的 winning solution 都基于 GBDT 类算法(XGBoost / LightGBM / CatBoost)——尤其是表格数据。
神经网络在结构化表格数据上通常打不过 GBDT——除非数据极大(百万+)且特征复杂。
这是为什么 ML 工程师面试必考 XGBoost——它是真正的”产线武器”。
2023 年某大厂的推荐系统经历过:
- 第一代:手工特征 + 逻辑回归
- 第二代:手工特征 + GBDT → 显著提升
- 第三代:手工特征 + 深度学习 → 仅小幅提升,运维成本爆炸
- 最终选择:手工特征 + GBDT 作为主线 + 深度学习做局部增强
结论:在很多业务上,GBDT 仍然是更经济的选择。深度学习不是万灵药。
下一篇:《K-Means 聚类:最经典的无监督算法》 —— 离开监督学习,进入无标签的世界。
读到这里说明你认真在学 🎯
订阅每周精选 —— 下一篇新文章 / 新可视化第一时间送到邮箱。
讨论区
· 用 GitHub 账号登录评论src/components/Comments.astro 顶部填入
仓库 ID 和分类 ID(见组件注释里的配置步骤)。