树模型与集成学习核心20 分钟kp-011#集成学习#随机森林#Bagging

随机森林与 Bagging

进度

一句话定义

Bagging 对训练集做自助重采样训练多个模型并取平均(分类投票),随机森林在此基础上让每棵树的每次分裂只看随机特征子集,用「去相关的多棵深树」把方差压到单树的零头。

为什么重要

随机森林是「开箱即用」的强基线:调参少、对特征尺度与异常值鲁棒、并行训练快、自带 OOB 评估与特征重要性。在表格数据任务中它常是第一个值得认真跑的模型,也是理解「为什么集成有效」的最佳教具。

前置知识

决策树:信息增益、增益率与基尼指数 的决策树;偏差-方差分解与过拟合 的方差概念。

核心概念

  • 自助采样(bootstrap):有放回抽 n 个样本,约 36.8% 样本不进该棵树的训练集(OOB 部分)。
  • Bagging:bootstrap 聚合,多个「脾气不同」的模型投票/平均。
  • 特征随机子集:每次分裂只从 √p(分类)或 p/3(回归)个特征中选——关键的去相关机制。
  • OOB 误差(Out-of-Bag):每棵树用没见过它的样本评估,再汇总,相当于免费的交叉验证。
  • 并行集成:各树独立可并行(与 Boosting 的串行相对)。

直观类比

会诊:一个医生(单树)看诊有个人偏见(高方差),请 500 个各自见过不同病人(bootstrap)、且每人只被允许看部分检查单(特征子集)的医生投票——个别人的怪判断被稀释。如果所有医生看同样的材料(完全相关的树), averaging 几乎无效:去相关是平均起效的前提。

原理与机制

对 B 个方差 σ2、两两相关系数 ρ 的模型的平均,方差为:

Var(f̄) = ρ σ2 + 1 - ρB σ2

B → ∞ 时第一项存留——平均消不掉相关性带来的方差下限。Bagging 只做重采样,ρ 仍很高(树总是先切最强的那个特征);随机森林用特征子集强制去相关,压低 ρ,从而突破 Bagging 的下限。代价:单棵树有效信息变少、偏差略升,通常净收益显著为正。集成几乎不改变偏差(平均的期望仍是期望),这是它「治方差不治偏差」的理论根据。

公式与推导

回归下的平均:f̂avg(x) = 1B∑b=1B f̂b(x),

𝔼[(f̂avg - 𝔼f̂)2] = 1B2∑b Var(f̂b) + 2B2∑b < b' Cov(f̂b, f̂b')

同方差相关结构下化简为 ρσ2 + (1-ρ)σ2/B。分类按多数票/平均概率,直觉相同。OOB 估计的理论依据:每棵树的 OOB 样本与训练样本同分布且独立于该树,汇总后近似交叉验证的无偏估计。

图示

          训练集 D
   ┌────┬────┬────┬────┐
   ▼    ▼    ▼    ▼    ▼      bootstrap 采样
  D*₁  D*₂  D*₃  D*₄  D*B
   │    │    │    │    │      每棵树分裂时只看 √p 个特征
  树₁  树₂  树₃  树₄  树B     (独立并行训练)
   └────┴────┴───┬┴────┘
                 ▼
        平均 / 多数投票 → 预测
   (OOB 样本旁路评估每棵树 → OOB 误差)

实例或案例

对单树与森林在同一数据上量化方差差异:

from sklearn.datasets import load_breast_cancer
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
import numpy as np

X, y = load_breast_cancer(return_X_y=True)
accs = {"单树": [], "森林": []}
for seed in range(30):                                   # 30 次不同划分,看成绩波动
    X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, random_state=seed)
    t = DecisionTreeClassifier(random_state=seed).fit(X_tr, y_tr)
    f = RandomForestClassifier(n_estimators=300, random_state=seed, n_jobs=-1).fit(X_tr, y_tr)
    accs["单树"].append(t.score(X_te, y_te)); accs["森林"].append(f.score(X_te, y_te))
for k, v in accs.items():
    print(f"{k}: 均值={np.mean(v):.3f} 标准差={np.std(v):.3f}")

典型结果:均值相近或森林略高,但森林的跨划分标准差小得多——方差被压掉的直接证据。

常见误区

  • 认为「树越多越好,但必须大量调参」:B 加到误差平台即可,默认参数常已可用;真正值得调的是 max_features(去相关强度)与树深。
  • 把不纯度重要性当真(高基数/连续特征虚高):诊断用置换重要性(见 kp-014)。
  • 用随机森林做时间序列外推:树只能输出训练集见过的数值范围,无法外推趋势(分段常数本质)。

与其他知识点的关系

偏差-方差分解与过拟合 的方差公式是本节的数学骨架;Boosting 与 AdaBoost/梯度提升树 GBDT 与 XGBoost 是另一条集成路线(串行降偏差);树模型可解释性:特征重要性与 SHAP 的置换重要性提供更可信的森林解读;超参数调优:网格、随机与贝叶斯搜索 中随机森林的超参数搜索空间通常很小——这是它工程友好的原因。

自测题

  1. Bagging 与随机森林最关键的区别是什么,为什么这个区别重要?

- 要点:分裂时随机特征子集强制树间去相关;由 ρσ2 + (1-ρ)σ2/B,相关性下限不降则平均收益封顶。

  1. OOB 误差为什么能替代验证集?

- 要点:每棵树的 OOB 样本未参与该树训练,同分布独立,汇总后近似 k 折 CV,免费且无重复建模成本。

  1. 随机森林主要降低偏差还是方差?

- 要点:方差(平均不改变期望);单树已是低偏差模型,森林在其上收窄波动。

延伸阅读

Breiman, Random Forests(Machine Learning, 2001);周志华《机器学习》第 8 章。