← 返回模块
Q2.6.2.2beta 可读 · 未来付费内容校验中内容版本 2026-05-26

Bagging 与随机森林

2.6.2 · 树模型与核方法 · 数学与统计能力

周五午盘,一家 50 亿规模的 CN 私募把一份沪深300 alpha 数据甩到你工位:30 个特征、日频次日超额收益作标签。上一课那棵深度 15 的 CART 树样本内方向准确率 100%、样本外只有 51%——比抛硬币好不了多少,Sharpe 几乎为零。你把它换成 500 棵在 bootstrap 样本上独立训练的深树取平均,样本外跳到 57%。这一跳,就是 bagging 的方差减少效应。但 500 棵原始 bagged 树并未榨干方差;在每次分裂上做特征子采样、把树间相关性进一步压低,还能再挤两到三个百分点——这是随机森林的第二级杠杆。本课讲清这两件事。

Bagging:bootstrap 样本上的并行学习器

给定训练集 D={(xi,yi)}i=1n\mathcal{D} = \{(x_i, y_i)\}_{i=1}^n,Breiman (1996) 的 bootstrap aggregation(缩写 bagging,中文「装袋」)做三步:(1) 从 D\mathcal{D} 有放回抽取 BB 个大小为 nn 的样本 Db\mathcal{D}^*_b;(2) 在每个 Db\mathcal{D}^*_b 上独立训练一个高方差基学习器(high-variance base learner,通常是不剪枝的深 CART 树)hbh_b;(3) 用平均或多数投票聚合:

hbag(x)=1Bb=1Bhb(x)(回归)hbag(x)=argmaxkb=1B1{hb(x)=k}(分类).h_{\text{bag}}(x) = \frac{1}{B} \sum_{b=1}^{B} h_b(x) \quad \text{(回归)} \qquad h_{\text{bag}}(x) = \operatorname*{argmax}_{k} \sum_{b=1}^{B} \mathbf{1}\{h_b(x) = k\} \quad \text{(分类)}.

单棵深树偏差本就低——训练能拟到 100%——但跨训练子集预测剧烈跳动。bagging 不动偏差,只把跨样本抖动平均掉;与上一课剪枝(pruning)正交。

方差减少恒等式

设每棵树在固定 xx 处预测方差为 σ2\sigma^2、两两之间平均相关系数(average pairwise correlation)为 ρ\rho,展开 Var[1Bbhb(x)]\operatorname{Var}\left[\frac{1}{B} \sum_b h_b(x)\right] 收齐协方差项得到

Var[hbag(x)]=ρσ2+1ρBσ2.\operatorname{Var}[h_{\text{bag}}(x)] = \rho\, \sigma^2 + \frac{1 - \rho}{B}\, \sigma^2.

三种极端:ρ=1\rho = 1(树完全一样)方差不动;ρ=0\rho = 0(独立同分布)方差以 1/B1/B 线性收缩;实际 ρ(0.3,0.7)\rho \in (0.3, 0.7),第一项 ρσ2\rho \sigma^2 是 bagging 的方差地板(floor),不随 BB 减小。要榨干 variance,必须把 ρ\rho 拉下来。

Formula Explorer

rho * sigma_sq + (1 - rho) * sigma_sq / B

拖到 ρ=0.5\rho = 0.5σ2=0.04\sigma^2 = 0.04B=100B = 100,读数 0.02020.0202——方差从 0.040.04 砍到 0.020.02,但已贴近地板。这就是下一步登场的舞台。

随机森林:特征子采样降相关

Breiman (2001) 把 bagging 推到下一层:每个内部节点分裂时,只允许从 pp 个特征中随机不放回抽取 m<pm < p 个候选,其余照 CART 原样。这就叫​​随机森林​​。两条经验默认值要记住:分类 m=pm = \lfloor \sqrt{p} \rfloor、回归 m=p/3m = \lfloor p/3 \rfloor

为什么 work?每棵树被迫用「不一样的特征组合」,ρ\rho 显著下降。代价是单树方差 σ2\sigma^2 略升,但幅度小(CART 贪心搜索本来就常落在「第二最好」特征上),远不及 ρ\rho 下降的收益。代入恒等式:σ2\sigma^2 涨 5%、ρ\rho0.70.7 降到 0.30.3,整体方差从 0.7σ20.7\sigma^2 跌到 0.315σ2\approx 0.315\sigma^2,再砍一半。

这与因子模型(factor model)里看到的 alpha 衰减(alpha decay)同构:大家都用同一批动量(momentum)信号时,策略间相关性飙升,「平均」就没 alpha 可拿;多样化特征源等于降低 ρ\rho、等于真正减方差。

​图位​​:横轴 BB11500500)、纵轴样本外误差。三条线:(a) 单棵深树水平参考;(b) bagged trees 在 ρ0.7\rho \approx 0.7 时下行后趋于明显高于零的渐近;(c) 随机森林在 ρ0.3\rho \approx 0.3 时下行更深、渐近更低。

袋外误差(out-of-bag, OOB)

Db\mathcal{D}^*_b 是有放回抽 nn 次,单个观测被「漏掉」的概率为

Pr[(xi,yi)Db]=(11n)nne10.368.\Pr[(x_i, y_i) \notin \mathcal{D}^*_b] = \left(1 - \tfrac{1}{n}\right)^n \xrightarrow{n \to \infty} e^{-1} \approx 0.368.

每个样本平均被 0.37B\approx 0.37 B 棵树漏看。把「漏看了 (xi,yi)(x_i, y_i) 的那部分树」的预测取出来评估再全样本平均,就是​​袋外误差​​——一种「免费的交叉验证」:不必切验证集、不必重训,一次训练同时给出训练表现与泛化估计。CN 私募里,袋外 IC(information coefficient)与样本外 IC 是并列报告的两个核心数字。

提醒:时间序列金融数据下 bootstrap 的 i.i.d. 假设会泄漏未来信息、OOB 会高估样本外表现;purged / embargoed 修正属于模块 2.6.5。

特征重要性:两种定义、两个坑

  1. ​Gini 重要性​​(mean decrease in impurity):把用到特征 jj 的所有分裂带来的不纯度减少累加再对树平均,训练时顺带算好。​​坑​​:对高基数(high-cardinality)类别或连续变量有系统偏差——候选切点更多就被高估。
  2. ​置换重要性​​(permutation importance):随机打乱 OOB 样本上特征 jj 的取值,看准确率下降多少;直接对应「模型靠它赚到多少」。​​坑​​:两个特征强相关(如 12126633 个月动量是同一信号变体)时,单独打乱一个会被另一个救回,重要性被低估。

实战:两者并列报。若沪深300 因子面板上 Gini 把「行业代码」捧到第一而 permutation 排到第十,几乎可断 Gini 高估了高基数类别。

一个小算例

Exercise

σ2=0.04\sigma^2 = 0.04ρ=0.5\rho = 0.5B=100B = 100,按方差恒等式算 bagged 预测器在固定 xx 处的方差;再把 ρ\rho 换成随机森林典型值 0.20.2 算第二次。哪项主导?BB 推到 10001000,多出的 900900 棵树是免费午餐吗?

提示
第一项 ρσ2\rho \sigma^2BB 无关;第二项 (1ρ)σ2/B(1 - \rho)\sigma^2 / BBB 衰减。两组分别代值算具体数,再看 BB \to \infty 时余项是谁。
提示
ρ=0.5\rho = 0.5:0.02+0.0002=0.02020.02 + 0.0002 = 0.0202;ρ=0.2\rho = 0.2:0.008+0.00032=0.008320.008 + 0.00032 = 0.00832BB 推到 10001000 第二项几近零,第一项 ρσ2\rho \sigma^2 完全不动——这就是随机森林相对纯 bagging 的额外收益。

课末练习

Exercise

22-33 句话各自回答:(i) 为什么 bagging 不能把整体偏差降到单棵基学习器之下?(ii) 为什么特征子采样让 σ2\sigma^2 略升却仍能净改善整体方差?(iii) 为什么 OOB 误差被称作「essentially free」?

提示
(i) 取期望对线性聚合可交换:E[hbag]=E[hb]\mathbb{E}[h_{\text{bag}}] = \mathbb{E}[h_b],偏差不变。(ii) 回到方差恒等式,比较 ρ\rho 下降与 σ2\sigma^2 上升的乘积效应——ρ\rho 下降通常远大于 σ2\sigma^2 上升。
提示
(iii) 每棵树本来就只见约 63%63\% 的训练数据,剩余 37%37\% 在训练阶段未被使用;把这部分天然空出的样本当验证集评估,不需额外 CV 折叠、不需重训。

下一步:从「减方差」到「减偏差」

你已经能写出 RandomForestRegressor(n_estimators=500, max_features='sqrt', oob_score=True) 并解释每个参数。但 bagging 与随机森林只解决方差;若基学习器本身偏差就大(如深度 33 的浅树),平均拉不动均值。下一课换路:​​梯度提升​​(gradient boosting)让每棵新树拟合上一轮残差(residual),把弱学习器串起来一点点把偏差压下去。bagging 并行减方差、boosting 顺序减偏差——二者在协方差矩阵(covariance matrix)的对角与非对角分量上各管一边。XGBoost 与 LightGBM 是这条路在产线上的两套主流实现。