集成学习
一个模型不够好,就用一群。但"用一群"有两种完全相反的做法:Bagging 让每个成员各自独立地犯错,再把错误平均掉;Boosting 让每个成员专门去修上一个成员没修好的地方。前者对付方差,后者对付偏差。搞混这两件事,是集成学习里最常见的误用。
LAB 01
Bagging 与方差
同一份数据反复重采样,看单模型的抖动怎么被平均掉
树与树之间的方差—
如果完全独立,平均后应该只剩—
单独一棵树的误差—
平均以后的误差—
把"平均多少棵树"从 1 拖到 60,盯住最后两行读数。单独一棵树的误差是 0.107,平均 20 棵之后降到 0.054——正好减半。画面上也看得很清楚:灰色的每一棵树都在乱跳,而它们的平均(橙线)光滑得多,也更贴近蓝色的真实曲线。关键在于每棵树看到的数据不一样。Bagging 的做法是有放回地重采样:每棵树的训练集都是从原数据里抽出来的一份,大约 63% 的样本会被抽中,剩下的没见过。于是每棵树犯的错互不相同,一平均就抵消掉了一部分。但注意:误差并没有按 1/B 下降。读数第二行给出的是"完全独立时应该剩下的方差",它比实际小得多。原因是这些树并不独立——它们用的是同一份原始数据,训练集之间高度重叠,所以错误也高度相关。平均只能消掉不相关的那一部分。这直接引出了随机森林的动机:既然相关性限制了 Bagging 的效果,那就再加一重随机(每次分裂只看一部分特征)把树推得更不一样。最后把树的深度拖到 2 再看:浅树本身方差就小,Bagging 几乎没有改进空间——Bagging 只在高方差的基学习器上才有意义。
LAB 02
Boosting 的逐轮修正
每一轮只学上一轮的残差,看决策边界一步步长出来
最后的训练误差—
最后的测试误差—
测试误差最低出现在—
那时的测试误差—
这一轮开始时的残差均方—
把轮数从 1 一格一格往上推,看橙色的模型怎么一点点长出形状。第 1 轮它还是一条近乎水平的线;十几轮之后大致的起伏出来了;几十轮之后细节也补上了。每一轮做的事只有一件:拿上一轮的残差当作新的目标,再训练一棵小树,然后按学习率加一点点上去。这就是梯度提升——它其实是在函数空间里做梯度下降,而那棵小树就是这一步的"方向"。下面那张图是重点:训练误差一路向下,测试误差先降后升。绿色竖线标出了测试误差的最低点。过了这个点,模型开始记住训练集里的噪声——Boosting 是会过拟合的,这一点和 Bagging 很不一样(Bagging 加更多的树几乎不会变坏)。把学习率从 0.5 降到 0.05 再看。曲线下降得更慢,但最低点更低、更平坦,过拟合也来得更晚。这就是"小学习率 + 多轮数"这条经验规则的来源:每一步走得小,等于给模型加了正则。代价是要算更多轮——这是一个纯粹的时间换精度的交易。 新加的第三张图,画的是「这一轮到底在拟合什么」。蓝点是第 rounds 轮开始时每个样本还差多少(也就是残差),灰虚线是这一轮拟合出来的那棵树 h(x),红实线是真正加进模型的 lr·h(x)。横轴和第一张图严格对齐,可以上下对着看。把轮数从 1 往上拖。默认参数下残差均方是 1.582 → 0.876(5 轮)→ 0.317(20 轮)→ 0.215(60 轮):蓝点一层层被压平贴到零线上,而灰虚线也越来越矮——后期那棵树已经找不到什么结构可拟合,它开始在噪声里找形状了。再把学习率从 0.10 调到 0.50。红实线和灰虚线的落差立刻收窄(学习率缩的就是这个),60 轮后残差均方从 0.215 掉到 0.102——训练集上确实拟合得更狠了,但测试误差同时从 0.316 涨到 0.386。这就是提升法里最值得记住的一条经验:学习率小、轮数多,几乎总是比学习率大、轮数少更稳。小步长让每一轮只能修一点点,模型有机会在过拟合之前被第二张图上的最优轮数截住;大步长则可能一轮就冲过头,而冲过头的部分后面的轮数是修不回来的。
LAB 03
随机森林的两重随机
样本随机 + 特征随机,少了哪一个森林就退化
森林的测试准确率—
单独一棵树的准确率—
树与树之间的平均相关性—
当前用的随机—
把"用哪几重随机"逐个切一遍,主要看"树间相关性"这一行。两个都不要时,每棵树用同样的数据、同样的全部特征,于是它们几乎完全一样:相关性接近 1,三十棵树和一棵树没有区别——集成完全失效。只加样本随机(Bagging),相关性降下来一截,准确率随之上升。再加上特征随机,相关性进一步降低,准确率通常还能再涨一点。随机森林的全部秘密就在这一行数字里。集成的误差可以粗略写成「单个模型的误差 × 相关性 + 一项随树数下降的部分」:树数只能压掉第二项,而第一项由相关性卡死——这就是为什么 Breiman 要额外引入特征随机。注意还有一个代价:特征随机会让每棵树单独变弱(读数第二行会掉一点),但整体变强。这是一个非常反直觉、也非常重要的取舍:为了让成员更不一样,值得让每个成员更差一点。(在人的组织里也有对应的说法:一个都是同类专家的委员会,判断力并不比其中一个人强多少。) 新加的第二张图是这一台真正该看的东西:树和树有多像。第 (a, b) 格是第 a 棵树与第 b 棵树在测试集上预测值的相关系数,色越深越雷同。森林的预测方差大约是 ρσ² + (1−ρ)σ²/B —— 加树只能消掉后面那一项,真正决定下限的是树间相关性 ρ,而自助采样和随机选特征存在的唯一理由就是把 ρ 压下去。把「当前用的随机」这个下拉挨个切一遍,盯住 ρ。实测:两个都没有是 1.0000(所有树一模一样,整片深色),只有样本随机是 0.9250,只有特征随机是 0.8945,两重随机是 0.8461。两条路都在去相关,但不成比例——自助采样把 ρ 从 1.0000 压到 0.9250,特征随机一步压到 0.8945;在这个二维问题上换一批重采样的点,树切出来的位置动得不多,真正的主力是特征随机。两重随机下矩阵会显出明显的棋盘纹路,那是因为每个结点重抽一次候选特征,碰巧多用了同一个特征的树就更像,用了不同特征的树就不像。这块纹路本身就是「特征随机」在图上的样子。还有一件值得留意的事:两重随机下森林的准确率是 97.25%,而它自己每一棵树只有 96.25%——一堆各自弱一点、但错得不一样的树,平均起来比其中任何一棵都强,这就是集成的道理。但这道题上它的余地极小:同样的数据,一棵不做任何随机的深树就能到 97.00%,森林只多赢 0.25 个点。别被「随机森林通常更好」这句话带着走——好多少,完全取决于问题。二维、两个特征都有用的问题上,森林本来就没多少发挥空间;它真正的主场是特征几十上百、且大量特征互相冗余的场合。
LAB 04
弱学习器要多弱
树深从 1 加到 10,Boosting 的最佳点在哪里
最好的树深度—
那时的测试误差—
在第几轮取到—
最深的那条跑满以后的误差—
五条曲线,五种"弱"的程度。深度 1 的树只能做一刀切(决策树桩),弱到几乎什么都学不会;深度 8 的树单独就能拟合得相当好。直觉上应该用强的,结果恰恰相反。深度 1 的曲线最低,0.307,而且在第 179 轮才到底;深度 8 最好也只有 0.341,第 19 轮就到底了,之后一路上翻到 0.508。原因很清楚:Boosting 靠的是"很多个小步",每一步只修一点点,整个过程本身就是一种正则化。基学习器太强,一步就把残差吃掉一大块,连噪声一起吃了——于是几轮之内就过拟合,而且再多的轮数只会更糟。这正是 Friedman 那句经典建议的来源:梯度提升的树深度通常取 2 到 6,而且深度控制的其实是"交互阶数"——深度 1 的模型是可加的(每个特征各管各的),深度 2 才开始有两两交互,深度 3 有三阶交互。所以选深度不是在选"强度",是在选"你相信特征之间有几阶交互"。这个视角比"深一点拟合能力强一点"有用得多。
这一页想说的
Bagging 和 Boosting 解决的是不同的问题。Bagging 平均掉方差,要求基学习器高方差(深树),加成员几乎不会变坏,可以并行;Boosting 逐步削减偏差,要求基学习器弱(浅树),加轮数会过拟合,必须串行。随机森林的关键不是树多,而是树之间的相关性低——为此宁可让每棵树单独变弱。而 Boosting 的树深度实际上在选择交互阶数,不是在选择拟合能力。