跳到正文
本地阅读 · 决策树与随机森林

决策树与随机森林

机器学习 · 机器学习 · P0
本章目录

学完后,你应能独立完成

  • 手算所有候选阈值的叶均值与 SSE
  • 解释树的容量、尺度与外推局限
  • 推导平均方差并说明 OOB 的边界

前置建议:损失、泛化与优化 · 时间验证与模型选择

改变一个条件,观察发生什么

浏览器内即时教学计算;Python 实验结果另列于代码区。图形与数值一起核对。

01

一个叶为什么预测均值

固定分组后,回归叶用常数 a 最小化 Σ(y_i−a)²;对 a 求导得叶均值。CART 回归比较分裂后的左右 SSE,分类比较加权 Gini 或熵。分类叶的概率是训练叶内类别比例,而不是回归均值的随意替代。

候选阈值放在相邻不同特征值之间。重复 x 不能按 y 人为分开;先按 x 排序,再扫描合法候选。贪心局部分裂不保证整棵树的全局最优。

\[\mathrm{SSE}_{child}=\sum_{i\in L}(y_i-\bar y_L)^2+\sum_{i\in R}(y_i-\bar y_R)^2\]
02

分裂增益要与父节点比较

x=1…6、y=[0,0,1,4,5,5],父均值2.5,父 SSE=33.5。阈值3.5给左均值1/3、右均值14/3,子 SSE=4/3,增益约32.1667。只有看完所有合法阈值,才知道该刀优于其他候选。

分类用 Gini=1−Σp_c²或熵−Σp_c log p_c。左右不纯度按样本占比加权,不能直接平均。这个样本中若前后各三项是不同类别,3.5会分出纯叶。

03

容量与外推是结构带来的

深度限制最长路径,叶数限制区域数,叶最小样本控制局部估计的粗糙程度。深度3的二叉树最多8叶,但不一定有8叶。行数多不代表叶内独立日期多,金融面板需额外检查跨期覆盖。

精确顺序阈值分裂通常不依赖单位;正单调变换保留候选样本分组。直方图、精度、并列和缺失规则可能改变实现结果。分段常数叶不会像线性斜率那样向训练范围之外连续外推。

04

平均只减少非共同波动

设 B 个基预测各方差 σ²,两两同相关 ρ。这只是帮助理解的简化假设。平均的方差来自 B 项单树方差和 B(B−1) 项协方差;增加 B 无法消去共享成分。

\[\mathrm{Var}(\bar f)=\sigma^2\left[\rho+\frac{1-\rho}{B}\right]\]
  1. 平均预测是 Σf_b/B。
  2. 方差对 B² 归一化,协方差不能忽略。
  3. B→∞ 时仍留下 ρσ²。
  4. RF 的随机子特征有助去相关,也可能削弱单树,需要平衡而非最大随机化。
05

bootstrap 与 OOB 不等于未来验证

有放回抽 n 次,一行未抽中的概率 (1−1/n)^n趋于e⁻¹≈.368。OOB 用没抽到该行的树产生预测,在相应 iid 条件下可用于内部误差诊断。

它只排除某一行,仍可能见该日其他股票、相邻重叠标签或之后市场状态。主要研究结论应使用时间合法的外部验证。训练分裂重要性还偏向有很多候选切点的特征,相关列也会分摊贡献。

从算法到一次真实运行

代码在本地 Python 中执行,HTML 内展示参考实现和本轮运行结果。请先独立完成练习,再展开完整参考文件。

trees.py / 核心函数
def best_split(x, y, min_leaf=1):
    """One-feature squared-error stump. None means no positive valid gain."""
    x, y = np.asarray(x,float), np.asarray(y,float)
    if x.ndim != 1 or y.shape != x.shape or min_leaf < 1:
        raise ValueError("Expected matching 1D arrays and min_leaf>=1")
    if len(x)==0 or not np.isfinite(x).all() or not np.isfinite(y).all():
        raise ValueError("Expected nonempty finite data")
    order = np.argsort(x,kind="stable"); xs, ys = x[order], y[order]
    parent = np.sum((ys-ys.mean())**2)
    best = None; best_sse = parent
    for i in range(min_leaf, len(x)-min_leaf+1):
        if xs[i-1] == xs[i]:
            continue
        left, right = ys[:i].mean(), ys[i:].mean()
        sse = np.sum((ys[:i]-left)**2)+np.sum((ys[i:]-right)**2)
        if sse < best_sse-1e-12:
            best_sse = sse
            best = (float((xs[i-1]+xs[i])/2), float(left), float(right), float(sse))
    return best
下载本节 .pypython trees.py依赖版本见首页,示例只使用合成数据。
查看本轮本地运行记录 · 2026-10-12
{
  "threshold": 3.5,
  "left_mean": 0.3333333333333333,
  "right_mean": 4.666666666666667,
  "child_sse": 1.3333333333333335,
  "parent_sse": 29.5,
  "averaging_variance_rho_0_8_B_100": 0.802
}

先回答,再看提示和答案

Q01

子 Gini=.2/.4、左右人数2/8,加权子不纯度多少?

一级提示

权重是节点内样本占比。

参考答案与条件

.2×.2+.8×.4=.36。不是(.2+.4)/2。

Q02

ρ=1 时增加树数能降低简化平均方差吗?

一级提示

先写出目标、信息集和所需条件。

参考答案与条件

不能,方差仍为 σ²。去掉非共享波动才是平均的收益。

Q03

树不需标准化,意味着预处理可以随便做吗?

一级提示

先写出目标、信息集和所需条件。

参考答案与条件

不意味着。时点、缺失、分箱及分类编码仍需检查;不缩放只是特定顺序分裂的性质。

把知识迁移到一个新任务

写单特征回归树桩,返回阈值、左右叶值、子 SSE。测试重复值、常数 x、常数 y、未排序输入和 min_leaf。再解释为什么 OOB 无法替代股票未来验证。

这里保存学习笔记,不在浏览器执行 Python。A/B/C 由你按独立完成程度填写。

参考与进一步阅读

在线文档可能比本地固定版本更新;API 行为以已验证代码和版本记录为准。

掌握状态与复习

关掉资料独立完成后记 A;提示后完成记 B;需要重学记 C。

记录尽量保存在当前浏览器,建议定期导出备份。