第 28 章 · 番外

经典机器学习:决策树与随机森林

这本书一路都在讲神经网络,但它并不是机器学习的全部。第 26 章那张“模型家族表”里, 有一支叫树模型——到 2026 年,它在表格数据(银行风控、广告排序、销量预测、工业质检)上依然常常比神经网络更好用。 这一章就把这支讲清楚:一棵决策树是怎么学出来的,为什么单棵容易过拟合,以及随机森林梯度提升树怎么用“很多棵树”把它救回来。

读前须知:这是并行世界,不是主线延续

前面 27 章的神经网络和这一章的树模型,是机器学习里两条并行的路线,不是谁进化成谁。 这一章不依赖前面的反向传播、梯度下降——树模型压根不用求导。它更像给你补上“另一半地图”: 知道除了神经网络,业界还常年在用什么、为什么用。本章仍以原理和直觉为主,暂无配套 C++ 代码。

读完这一章,你会明白

  • 一棵决策树到底在学什么——其实就是把一串 if-else 从数据里自动长出来;
  • 它凭什么决定“先问哪个问题”:基尼不纯度 / 信息增益是怎么打分的;
  • 整棵树是怎么训练出来的——贪心 + 递归地反复问“下一刀切哪最划算”,全程不求导;
  • 为什么单棵树特别容易过拟合,以及“剪枝”在干嘛;
  • 随机森林怎么用“很多棵各自有偏见的树投票”把误差压下去(Bagging);
  • 梯度提升树(GBDT)又是另一种思路:一棵接一棵地专门纠错(Boosting);
  • kNN 这个“不训练”的惰性模型怎么靠邻居投票判类;SVM / 逻辑回归 / 朴素贝叶斯速览,以及它们分别适合什么场景、承担什么作用

1. 先从一个问题说起:20 个问题

你小时候大概玩过“猜东西”游戏:我心里想一个动物,你只能问“是/否”问题来猜。聪明的玩法是—— 每次都问那个最能把可能性劈成两半的问题:“它是哺乳动物吗?”“它比猫大吗?”“它会飞吗?”…… 问不了几轮,答案就锁定了。

决策树就是这个游戏的自动版。给它一堆带标签的数据(比如很多条贷款申请,每条标了“最后有没有还上”), 它会自己找出“该按哪些特征、按什么顺序去问”,最后长成一棵能对新样本做判断的树。它和神经网络最大的不同是: 你能一眼读懂它的每一步决策——这也是它在金融、医疗这类“必须解释为什么”的场景里长盛不衰的原因。

2. 决策树:把 if-else 学出来

假设我们要判断“要不要给一个人批贷款”,手上每条历史数据有几个特征:收入是否有房信用历史长度, 以及标签最终是否违约。一棵学出来的决策树可能长这样:

月收入 > 1 万? 根节点(先问这个) 名下有房? 信用历史 > 3 年? 还能接着问 拒绝违约多 批准有抵押 拒绝记录太短 批准高收入+信用好 从根节点一路问下来,落到哪个叶子,就给哪个答案 紫=判断节点(问一个特征)  绿/红=叶子(最终结论)

一棵决策树:每个内部节点就是一个“问一个特征”的判断,每条是答案,每个叶子给出最终结论。预测时,新样本从根节点开始按特征一路往下走,落到哪片叶子就输出哪个答案。

注意:树的形状、先问哪个特征、在哪个数值上切,都不是人写死的,而是从数据里“学”出来的。 那么问题来了——它凭什么决定“根节点先问收入,而不是先问有没有房”?

2.1 怎么选“该问哪个问题”:基尼与信息增益

核心思想一句话:选那个能把数据分得“最干净”的问题。“干净”指的是——分完之后,每一堆里尽量都是同一类 (要么几乎全是“会还款”,要么几乎全是“会违约”)。衡量“不干净”程度的常用指标是基尼不纯度(Gini impurity):

Gini = 1 − Σk pk2 p_k 是这一堆里第 k 类所占比例。全是一类时 Gini=0(最干净);两类各占一半时 Gini=0.5(最乱)

举个数字:一个节点里有 10 条样本,如果 10 条全是“会还款”,那 Gini = 1 − 1² = 0,纯净到不用再问了; 如果 5 条还款、5 条违约,Gini = 1 − (0.5² + 0.5²) = 0.5,乱成一团。 决策树会逐个特征、逐个切分点试一遍,算出“切完之后左右两堆的加权平均 Gini 下降了多少”, 下降最多的那个切法就是这一步的最优提问。然后对切出来的每一堆递归重复,直到足够干净——树就这样一层层长出来了。

信息增益:换一把尺子,思路一样

另一套经典指标(ID3 / C4.5 算法用)是信息增益,把“不纯度”换成信息论里的熵(entropy) H = −Σ pk log pk,再看“分裂后熵减少了多少”。尺子不同,目标完全一致:让每一刀都尽量把混在一起的类别分开。

2.2 怎么把整棵树种出来:贪心 + 递归

上一节解决的是“某一个节点该按哪个特征、哪个切分点分”。那整棵树呢?答案是一句话: 在每个节点都用上面的打分选一个当下最优的切法,切完之后对切出来的每一小堆重复同样的动作。 这种“每一步都只挑眼前最好、不回头”的策略叫贪心(greedy),配合“对子问题重复自己”的递归(recursion),树就长出来了。写成步骤:

决策树训练:递归分裂(伪代码)
训练一个节点(落在这个节点的样本集合 D):
  1. 若 D 已经足够纯(几乎全一类)或满足停止条件:   1
        把这个节点设成叶子,输出 D 里最多的那一类,返回
  2. 否则,遍历每个特征 × 每个可能的切分点:          2
        算“按它切开后,左右两堆的加权平均不纯度”
  3. 选出让不纯度下降最多的那个 (特征, 切分点)        3
  4. 用它把 D 分成左、右两堆                          4
  5. 对左堆、右堆各自递归调用“训练一个节点”           5
  1. 递归的出口:纯了就不用再问,直接当叶子。停止条件还包括“深度到顶”“样本太少”等(下一节剪枝会展开)。
  2. 穷举打分:这是树“学习”的核心动作——它不靠求导,而是把所有候选切法都试一遍,用 §2.1 的基尼/信息增益给每种切法打分。
  3. 贪心选择:只挑当前这一步分得最干净的,不考虑“将来会不会更好”。这让训练很快,但也是单棵树容易长歪的原因之一。
  4. 一分为二:比如“收入 > 1 万”成立的样本进右堆,不成立的进左堆。
  5. 对子问题重复自己:左右两堆各自又是一个更小的训练问题,套用同一套流程,直到触发出口。

所以决策树的“训练”和神经网络完全是两码事:它没有权重可调、不做反向传播、也没有学习率, 整个过程就是“不停地问:下一刀切在哪最划算?”。下面用一个最小的例子,把“打分”这一步真正算一遍。

动手算一次:这一刀到底降了多少不纯度

设一个节点有 10 条样本:6 条会还款、4 条会违约,当前不纯度 Gini = 1 − (0.6² + 0.4²) = 0.48。现在试一个切法“月收入 > 1 万?”,把样本分成两堆:

  • 右堆(收入>1万):5 条,4 还款 / 1 违约 → Gini = 1 − (0.8² + 0.2²) = 0.32
  • 左堆(收入≤1万):5 条,2 还款 / 3 违约 → Gini = 1 − (0.4² + 0.6²) = 0.48

切完的加权平均不纯度 = (5/10)×0.32 + (5/10)×0.48 = 0.40,比切之前的 0.48 下降了 0.08。决策树会对每个特征的每个切分点都算一遍这个“下降了多少”, 最后挑下降最多的那一刀落下去。这就是它每一步在“学”的全部内容。

2.3 什么时候停:过拟合与剪枝

如果让树无限往下长,它最终能给训练集里每一条样本都单独切一片叶子——训练准确率 100%。 但这恰恰是灾难:它把训练数据里的噪声和巧合也当成规律背了下来,一遇到新样本就露馅。 这就是第 10 章讲过的过拟合,在树模型里尤其严重。

常用的两类刹车:

但即便剪枝,单棵决策树依然有个顽疾:不稳定。训练数据只要变动一点点(去掉几条样本), 它可能就从根节点开始选了完全不同的特征,长成另一棵样子完全不同的树。正是这个“不稳定”,催生了随机森林。

3. 随机森林:三个臭皮匠,顶个诸葛亮

既然一棵树又不稳、又爱过拟合,那就种一大片树,让它们投票。这就是随机森林(Random Forest), 它用的通用套路叫 Bagging(Bootstrap Aggregating)。关键是要让每棵树都不一样、犯各自独立的错,靠两重随机做到:

预测时:分类问题让所有树投票取多数,回归问题取所有树输出的平均。

训练数据 有放回抽样 树 1 树 2 … 树 N 批准 拒绝 批准 投票 / 平均 多数说“批准” 批准

随机森林:从同一份数据反复抽样训出许多各不相同的树,预测时让它们投票 / 取平均。单棵树各有各的偏见和错误,但把大量独立的错平均掉后,整体反而又准又稳。

为什么“投票”会更准?

想象一群人估西瓜重量:每个人都会估偏,有人偏高有人偏低。但只要大家的错误方向各异、互相独立, 把所有人的估计一平均,正负就抵消了,群体结果往往比任何一个专家都准。随机森林靠“样本随机+特征随机”刻意制造这种独立性, 所以它几乎不用怎么调参就很能打,是表格数据上最好用的“开箱即用”模型之一。

4. 梯度提升树:一棵接一棵地纠错

随机森林是并行种一堆树再平均(Bagging);还有另一条思路正好相反——串行地一棵接一棵种, 每棵新树都专门去修正前面所有树加起来还没做对的部分。这就是 Boosting, 它的代表是梯度提升树(GBDT):

你可能已经嗅到熟悉的味道了——“看还差多少,朝减小误差的方向挪一小步”,这正是第 5 章梯度下降的思路, 只不过这里每一步挪的不是数字参数,而是加进来一棵新树XGBoost、LightGBM 就是 GBDT 的高效工业实现, 在 Kaggle 竞赛和真实表格业务里常年是夺冠常客

随机森林(Bagging)梯度提升树(Boosting)
树之间并行、独立,互不知道串行、接力,后一棵补前面的错
每棵树长得比较深、比较强通常很浅(弱学习器),靠数量取胜
主要降低方差(让结果更稳、不过拟合)偏差(让结果更准、拟合更细)
脾气不太挑参数,稳健好用更准,但要小心调参、否则会过拟合

同样是“很多棵树”,Bagging 靠“平均独立的错”求稳,Boosting 靠“接力纠错”求准。两者是表格数据上的两大主力。

5. kNN:一个“不训练”的模型

讲完树,再看一个思路截然相反、却同样经典的模型——k 近邻(k-Nearest Neighbors,kNN)。 它的想法朴素到有点“耍赖”:要判断一个新样本是哪一类,就看它周围离得最近的 k 个老样本大多是什么类,少数服从多数。 “物以类聚,人以群分”,说的就是它。

特征 1 特征 2 ? k=3:最近 3 个里 2 橙 1 蓝 → 判为橙类 A 类 B 类

kNN 判类:找出离待判样本(?)最近的 k 个邻居,让它们投票。k=3 时这里 2 橙 1 蓝,于是判成橙类。

kNN 最有意思的一点是——它几乎没有“训练”这回事:

简单的代价:又慢又怕“维度灾难”

kNN 思想极简、也不需要训练,但代价是预测慢:每判一个新样本都要和全部训练数据比一遍距离,数据一大就吃不消。 而且它高度依赖“距离有意义”——当特征维度很高时,所有点的距离会变得差不多(维度灾难), 近邻也就失去了意义。所以 kNN 更适合维度不高、数据量不大的场景,以及作为快速验证想法的基线。

6. 其他常见的经典模型(速览)

树和 kNN 之外,还有几位“深度学习之前的主力”,至今在合适场景里依然好用。这里各给一句话直觉,建立个印象即可:

模型一句话直觉擅长
逻辑回归加权求和再过一个 Sigmoid,输出“属于某类的概率”快、稳、极好解释;是很多系统的基线
SVM 支持向量机找一条“间隔最大”的分界线;必要时用核函数映到高维再切中小规模、高维数据,理论漂亮
朴素贝叶斯用贝叶斯公式算概率,假设各特征“互相独立”(所以叫朴素)文本分类、垃圾邮件过滤,又快又意外地好用
K-means 聚类没有标签,自动把数据聚成 K 堆第 27 章,属于无监督
你其实早就见过逻辑回归了

逻辑回归 = “加权求和 Σ w·x + b → 过 Sigmoid → 输出概率”。对照第 2 章的一个神经元你会发现: 一个带 Sigmoid 的神经元,本质上就是一个逻辑回归。所以神经网络并不是凭空冒出来的新物种——它更像是把这些经典的“小砖块”大规模堆叠、再让它们端到端一起学

7. 一张速查表:它们分别用在哪

经典模型不是“老古董”,更像一套工具箱。它们的差别不只是准不准,还包括训练成本、预测速度、可解释性、对数据形态的要求。 下面这张表可以当成第一版选型地图:

模型典型场景主要作用不太适合
决策树 小中型表格数据;规则审核;需要解释每一步的风控/运营策略 把数据里的判断规则变成一串可读的 if-else,方便人检查、改规则、做合规说明 数据噪声大、特征很多且关系复杂时,单棵树容易过拟合、不稳定
随机森林 表格分类/回归;想先拿一个稳健基线;不想花太多时间调参 用很多棵树投票/平均,把单棵树的偶然错误平均掉;常用于快速判断“这个问题能不能从特征里学出来” 追求极致精度、模型要很小、或需要每条预测都有非常短的解释链路时
GBDT / XGBoost / LightGBM 银行风控、广告点击率、推荐排序、销量/价格预测等表格业务 一棵接一棵纠错,通常是表格数据上的高精度主力;还能输出特征重要性,帮人发现哪些字段最有用 原始图片、语音、长文本这类需要自动学表示的非结构化数据
kNN 数据量不大、维度不高、距离有意义的分类/检索;快速做 demo 或基线 不训练,直接靠“最近的老样本”投票;也常用于相似案例查找、简单推荐、异常点初筛 大数据量预测会慢;高维特征里距离容易失真;线上低延迟服务通常不直接裸用
逻辑回归 二分类风控、广告点击率、转化率预估、医疗风险评分;需要概率和可解释系数 给出“属于某类的概率”,训练快、上线便宜、系数可解释;非常适合作为生产基线和可解释评分卡 强非线性关系很多、特征交叉复杂且不想手工做特征工程时
SVM 中小规模、高维稀疏特征;文本分类、传统图像特征分类、生物信息等 找最大间隔分界面,小数据上常很稳;核函数能处理一部分非线性边界 百万级以上大数据、需要频繁增量训练、或需要自然输出概率的场景
朴素贝叶斯 垃圾邮件过滤、新闻分类、舆情标签、关键词很有信号的文本任务 用词/特征出现的概率快速判类;训练和预测都极快,小数据也能跑出可用结果 特征之间强相关、需要理解上下文语义、或类别边界很复杂的任务
K-means 没有标签时做用户分群、商品分组、图片颜色聚类、数据探索 先把样本粗分成几群,帮助人看结构、做分层运营,或给后续模型造特征 不知道该分几群、簇形状弯弯绕绕、离群点很多的场景

选模型时先问三件事:数据是表格还是图文语音?数据量是小中大?业务要不要解释?答案通常已经能排除一大半模型。

一个实用顺序

真做项目时,别一上来就拿大模型压。表格任务可以先用逻辑回归做可解释基线, 再用随机森林看非线性信号是否存在,最后用GBDT冲精度; 图像、语音、长文本这类原始感知数据,再优先考虑 CNN / Transformer / 大模型。

8. 到底什么时候用树、什么时候用神经网络?

这是最实用的问题。别被“深度学习最先进”带偏了——选模型要看数据长什么样:

你的数据 / 场景更推荐为什么
表格数据(Excel 那种:一行样本、多列特征)树模型 / GBDT特征各有含义、量纲不同、还常有缺失,树天然能吃;通常又快又准
图像、语音、视频神经网络(CNN 等)原始像素/波形需要自动学层次化特征,树很难处理
长文本、对话、翻译神经网络(Transformer)需要理解顺序和长距离依赖
数据量很小(几百上千条)经典模型 / 树神经网络容易过拟合、也不划算
必须能解释每一步(风控、医疗合规)决策树 / 逻辑回归决策路径人能读懂,神经网络更像黑盒
数据海量、且是原始感知信号深度学习 / 大模型数据越多、结构越原始,端到端表示学习优势越大

一个常被验证的经验:在中小规模表格数据上,调好的 GBDT 往往打平甚至超过深度网络,而且训练快得多。所以“用不用神经网络”,先看数据,而不是先看潮流。

小结

  • 决策树 = 从数据里自动长出来的一串 if-else;预测就是从根节点按特征一路走到叶子。
  • 选“先问哪个特征”靠基尼不纯度 / 信息增益:哪一刀把类别分得最干净,就选哪一刀。
  • 整棵树靠贪心 + 递归训练:每个节点穷举所有切法挑最优,再对左右两堆重复;不求导、无学习率。
  • 单棵树容易过拟合、不稳定,靠剪枝缓解,但根治要靠“很多棵树”。
  • 随机森林(Bagging):样本随机 + 特征随机种一堆独立的树,投票/平均求稳。
  • 梯度提升树(Boosting/GBDT):串行接力,每棵新树专补前面的错,求准;XGBoost/LightGBM 是工业主力。
  • kNN 不训练,把计算全留到预测时靠最近邻投票;逻辑回归、SVM、朴素贝叶斯各有擅长,一个带 Sigmoid 的神经元就是逻辑回归
  • 经典模型各有位置:逻辑回归做可解释概率基线,随机森林做稳健基线,GBDT 冲表格精度,kNN 做近邻检索/小数据验证,SVM 适合中小高维数据,朴素贝叶斯适合快速文本分类。
  • 选型看数据:表格数据优先树模型,图像/语音/长文本优先神经网络,不是越“深”越好。

动手与思考

问题 1:一个节点里 8 条样本全是“会还款”,它的基尼不纯度是多少?说明什么?

Gini = 1 − 1² = 0。说明这堆已经完全纯净(全一类),不需要再分裂,可以直接作为叶子给出结论。

问题 2:随机森林为什么要“特征随机”?只做“样本随机”不行吗?

如果只做样本随机,一旦存在某个特别强的特征,几乎每棵树都会先拿它来分裂,结果所有树长得很像、错误高度相关,平均起来降不了多少方差。加上“每次分裂只在随机特征子集里挑”,才能强制让树彼此不同、错误更独立,投票才真正有效。

问题 3:随机森林和梯度提升树,最本质的区别是什么?

随机森林是并行、独立地种很多树再平均,主要降低方差(求稳);梯度提升树是串行接力,每棵新树专门拟合前面所有树的残差,主要降低偏差(求准)。一个靠“平均独立的错”,一个靠“接力纠错”。

问题 4:手上是一份 5000 行、30 列的银行客户表格,要预测会不会违约,你先试哪个模型?

先试树模型 / GBDT(如 XGBoost、LightGBM)。这是典型的中小规模表格数据,特征有含义、量纲不一、可能有缺失,树模型天然适配、训练快、还相对好解释;神经网络在这种场景通常没有优势,还更容易过拟合。

番外读完 · 另一半地图补上了

现在你手里有了完整的两张地图:一边是这本书主讲的神经网络 / 深度学习, 另一边是树模型和经典机器学习。真实世界里它们常常并肩作战—— 大模型负责理解图文语音,树模型负责稳稳地啃表格。知道什么时候用哪个,比只会一种更值钱。

返回目录 / 重读某章