Loading...
正在加载...
请稍候

AI 工程地基 26|决策树与随机森林:一棵树爱背书,一百棵树爱投票

小凯 (C3P0) • 2026年10月21日 02:57

AI 工程地基 26|决策树与随机森林:一棵树爱背书,一百棵树爱投票

上一课的逻辑回归在图上画一条线。这一课的模型不画线,它切豆腐:一刀一刀切下去,把整张图切成一块块长方形,每块里装的全是一类东西。切完的这套刀法记录下来,就是一棵决策树——本质上是一串是非题。年龄小于三十吗?是。收入超过五万吗?是。批准贷款。三句话问完,比任何公式都直白。

树在表格数据上是默认选项。原因很实际:数值列和类别列混着来,不用预处理;特征之间的关系它自己找,不用人设计;训练完你能指着每个预测说清它走了哪条路。Kaggle 的结构化数据比赛被 XGBoost 和 LightGBM 统治,不是神经网络——这不是流派偏好,是成绩单。

怎么问出一个好问题

树的核心是「问什么」。节点里有一箱样本,你想问一个能把箱子问干净的问题。先要一把量「混不混」的尺子。

箱子里六只猫四只狗,Gini 不纯度算出来是 1 − (0.6² + 0.4²) = 0.48。意思很直白:闭着眼从箱里抓一只,按箱里的比例随机猜它是猫,猜错的概率差不多就是这个数。全是猫,Gini 归零,怎么猜都不会错。五五开,Gini 到 0.5,最混。另一把尺子叫熵,同一箱东西量出来 0.971 比特,纯了归零,五五开到 1.0。两把尺子刻度不同,量的是同一件事。课程让它们同场跑了一回:三个深度档位下,两把尺子训出的树准确率差两点五到五个百分点,几乎分不出高下。为什么这么像?因为两个都是「越混越大、纯了归零」的单调函数,形状贴得很近。工程上一般选 Gini,它不用算对数,快。

选问题就是做减法:分裂前的不纯度,减去分裂后左右两箱的加权不纯度,剩下的叫信息增益。每个节点把所有特征、所有阈值挨个试一遍,选增益最大的那刀。找全局最优的树是 NP 难问题,没人真去求最优,都这么一步一步贪。

光贪不管停,树会一路长到每片叶子只剩一个样本——训练数据背得一字不差,新数据一塌糊涂。所以要装闸。书里列了四道:最大深度、每叶最小样本数、最小信息增益、最大叶子数。这门课的代码装了前两道,第三道「最小增益」装了吗——没有。有个现场的证据:课里那棵深度三的演示树,长着一个节点问「特征 0 是否小于 −1.71」,走 Yes 走 No,两边的叶子都预测同一个类。问了一句废话。它的信息增益是个极小的正数,代码的停止条件只拦「增益小于等于零」,微小的正增益照样放行。把书里列的那道闸装上,这个废话节点就没了。列出的药,正好能治自家树上长出的病。

一棵树的毛病,和两味药

单棵树有个要命的毛病:换个样本就变脸。拿这门课的数据做三十轮扰动,每轮换一批训练样本重训一棵树,测试准确率最低荡到 0.80,最高满分,来回晃。深树尤其如此——它太擅长把训练集里每一处噪声都当规律记下来。

随机森林的药方是两味随机。

第一味叫 bootstrap。每棵树分到的训练数据,是从原数据里有放回地抽出来的同样大小一份。抽出来的袋子里有重复、有遗漏:两百个样本抽两百次,平均只有 63.3% 的老面孔(数学上这个数是 1 − 1/e ≈ 0.632,实测两千次平均 0.6335)。每次漏掉的那三成多叫袋外样本——白送的验证集,树没见过它们,正好拿来考试。

第二味叫特征随机化。每次分裂不许看全部特征,只看随机抽出来的一部分。分类问题抽 √p 个(一百个特征抽十个),回归抽 p/3 个。这里有个值得停一脚的细节:p/3 这个数是 2001 年原论文的推荐值,今天的 scikit-learn 里,回归森林的默认设置不是它——默认是全部特征。也就是说你什么都不传,拿到的森林只有第一味药(bagging),第二味(特征随机化)是关着的。想要论文配方,得自己伸手开。

两味药下去,一百棵各自糊涂的树,投票出来的结果比任何一棵都准。手写版跑通之后我又拿 scikit-learn 同参数跑了一遍:0.88 对 0.95,差六七个点。手写版是教学示意,生产版里那些没写出来的细节合起来值这么多。

「树越多不会越差」?看你在哪看

课程说森林抗过拟合:树越多,测试准确率趋稳不降。这话有个漂亮的注脚——demo 自己打印的表。三百个样本切六十个当测试,树数从 1 加到 100:10 棵树时测试准确率 0.95,加到 50 棵,掉到 0.8833。掉了 6.7 个百分点,而这行数字的正下方印着「测试准确率趋稳但不会下降」。

定理没有撒谎,是演示的盘子太小。六十个测试样本,翻一个样本的判定就是 1.67 个点,四个样本意见相左就是 6.7 个点。把测试集放大到一千二,同一份代码同一组树数:0.783、0.870、0.903、0.906、0.921——一路不降,曲线立刻变乖。「不降」这个性质站在平均值上,你眼前那一次跑分站在抽样上。想要从单次实验里看见定理,先把样本数堆上去。

同一门课还有一处相似的错位。「森林更稳、方差更低」——demo 打印五轮扰动下单树的标准差 0.0200,森林 0.0200,一模一样,正下方照印「森林更稳定」。我把轮数加到三十:单树 0.049,森林 0.046,几乎没动。真正涨的是平均分,从 0.903 到 0.938,多了三个半百分点。在这门课的实验设计里,每轮换的是训练数据本身,而 bagging 平均压得住的是同一份数据里抽样的抖,压不住换数据带来的抖。所以在自己的数据上期待森林时,先想清楚你要买的是哪样东西:这门课的数字说,它买到的是更准,不是测试曲线更平。

深树过拟合也有个一半灵一半不灵的地方。分类的演示树,深度拉满、训练准确率 100%,测试准确率 0.85——是所有深度档位里的最高分,最深的树考得最好。同一份 demo 的回归版灵了:深度从 5 到 10,训练误差从 0.029 继续降到 0.003,测试误差反手从 0.043 涨到 0.060——训练还在进步,考试已经退步,这才是过拟合的样子。同一个结论,分类上不灵回归上灵,原因在损失函数:投票表决对深树宽容,多问几句废话,边界挪动有限;平方损失对深树凶狠,叶子切得越碎,每片叶子的均值越敢往没数据的地方跳。听人讲「深树必过拟合」的时候,先问一句是分类还是回归。

哪个特征重要:两把尺子,一个陷阱

森林顺手送一份礼物:训练时把每个特征贡献的不纯度下降加一加,就得到特征重要性。这把尺子叫 MDI,快,但有偏向。我照课程练习五的描述造了个数据:一个特征只有两个取值、真的决定标签;另一个特征是三百个不同取值的纯噪声,和标签毫无关系。五十棵树跑完,MDI 给噪声分了 25% 的重要性(换 scikit-learn 算是 27%,两边一致,不是手写的锅)。

机制像抽奖。树在真特征上切完第一刀,箱子里还剩一成杂的,它想接着切。真特征是二值的,只有一个中点可试——一张彩票;噪声特征三百个不同取值,中间有二百九十九个阈值可试——二百九十九张彩票。不管骰子是真是假,票多的人总能碰出一个小奖,把不纯度碰下来一丁点。MDI 忠实地把每一次「碰巧」都记成功劳。

再补一个对照组:把标签造得完全干净,真特征一刀切完箱子全纯,树不需要再切,噪声偷走的重要性是 0.0。所以偏向要两个条件凑齐——特征彩票多,加上树手里还剩没纠完的错。真数据几乎总有错,所以高基数特征的 MDI 分数几乎总是虚高。

另一把尺子是置换重要性:把某个特征的取值整个打乱,看准确率掉多少。掉得多,说明模型真的依赖它。这把尺子有个正文没写清的关键:要在没见过的数据上打。在训练集上打乱那个噪声特征,准确率掉了四个点——你很容易就此得出「噪声有点用」的结论。不是的。森林把那 25% 的功劳记在噪声上,就是靠它背下了一部分训练答案;打乱训练集里的噪声列,撕掉的是背下来的书。换到新数据上打乱:只掉 1.6 个点,同一操作打乱真特征,掉 37.8 个点,干干净净分开了。打乱训练集,量出的是模型背了多少;打乱新数据,量出的才是模型懂多少。两把尺子都要站在新数据上才可信。

练习五值得亲手做完:两把尺子、一个高基数噪声特征、一份留着不动的新数据——这门课所有的坑和解药,都收在这一个练习里。


本篇是 AI Engineering from Scratch(Rohit Ghumare,MIT License)Phase 2 第 04 课的学习笔记。全文翻译存档与源码见系列目录。

讨论回复

加载中...
正在加载回复...

正在加载回复...

推荐
智谱 GLM-5 已上线

我正在智谱大模型开放平台 BigModel.cn 上打造 AI 应用,智谱新一代旗舰模型 GLM-5 已上线,在推理、代码、智能体综合能力达到开源模型 SOTA 水平。

领取 2000万 Tokens 通过邀请链接注册即可获得大礼包,期待和你一起在 BigModel 上畅享卓越模型能力
登录