剪枝:决策树为什么会学过头
约 14 分钟
决策树有个致命毛病:如果不加限制,它一定会过拟合。
为什么必然过拟合
只要一直切下去,决策树总能把训练集分得完全干净——极端情况下,每个叶子只装一个样本,训练准确率 100%。
但这棵树学到的是「张三买了、李四没买」这种个体记忆,不是规律。换一批人来预测,立刻崩溃。
这是第一章讲的过拟合在决策树上最典型的表现:模型容量太大,把噪声也当成了信号。
预剪枝:边长边限制
在训练时就设置停止条件,最常用四个:
| 参数(sklearn) | 含义 | 典型值 |
|---|---|---|
max_depth |
树最深几层 | 3–10 |
min_samples_split |
节点样本少于这个数就不再切 | 10–50 |
min_samples_leaf |
叶子至少要有几个样本 | 5–20 |
max_leaf_nodes |
最多几个叶子 | 视数据量 |
最常用的是 max_depth。 一个经验起点:先设 3–5,看验证集表现,再往上调。
预剪枝的优点是快(不用长出完整的树再砍),缺点是可能过早停止——某一刀当下增益不大,但切完之后下一刀增益很大,预剪枝就错过了。
后剪枝:先长满,再砍
先让树完全长成,然后自底向上考察每个节点:把这棵子树换成一个叶子,验证集表现会变差吗? 不变差就砍掉。
后剪枝通常效果更好(因为它看的是砍完之后的实际效果),代价是计算量大。
sklearn 提供代价复杂度剪枝(ccp_alpha 参数):
是误差, 是叶子数, 是惩罚系数。 越大,越倾向于小树。 这个式子的思路和正则化完全一样:在「拟合得好」和「模型简单」之间取平衡。
怎么选参数:验证曲线
from sklearn.model_selection import validation_curve
train_scores, val_scores = validation_curve(
DecisionTreeClassifier(), X, y,
param_name='max_depth', param_range=range(1, 21), cv=5)
把训练分数和验证分数画在同一张图上,你会看到典型的形状:
- 深度小:两条线都低 → 欠拟合
- 深度适中:验证分数最高 → 最佳点
- 深度大:训练分数接近 1,验证分数掉下来 → 过拟合
选验证分数最高的那个深度。 这张图是理解偏差-方差权衡最直观的方式,值得亲手画一次。
决策树的另一个弱点:不稳定
训练数据变一点点,树的结构可能完全变样。 因为顶部某个节点的选择一变,下面整棵子树都跟着变。
这个「高方差」的特点,正是下一节要解决的问题——而解决办法出人意料地简单:多种几棵树。
练习:用 sklearn 内置的鸢尾花数据集,画一条 max_depth 从 1 到 15 的验证曲线,找出最佳深度。
决策树为什么不加限制必然过拟合?预剪枝和后剪枝各自的优缺点是什么?
登录 后可看答案