跳到主要内容

随机森林 — 一群树的投票

这一章讲三件事: 单棵树怎么学(挑让数据最「纯」的切口,反复分下去); 一群树为什么比一棵树强(投票的数学);以及怎么强迫一群树「彼此不同」。 随机森林是把多个模型综合成更强模型的方法——同一个思路家族里还有梯度提升——一棵接一棵、每棵只管纠正前面的错—— 后者在机器学习竞赛里人气极高1。这一章学到的「委员会」思想,在所有算法里都适用。

1. 顶层全景

一份训练数据
↓ Bootstrap:抽样放回,造出几百份「大同小异」的数据
↓ 每棵树再随机只看一部分特征
几百棵彼此不同的决策树,各自给答案
↓ 多数表决:按票数定结果
最终预测 + 白送一份「哪些特征重要」的排名

图说:先造「有差异的群众」,再开「投票」。多样性是全章的题眼。

随机森林的目标:利用多个决策树模型,拿到比单棵树更高的预测精度;单棵树性能未必高,但多棵汇总,「一定能创建出泛化能力更强的模型」2

2. 单棵决策树:不断挑「切得最纯」的一刀

决策树是按条件分支划分数据来解决分类问题的方法:像玩「二十个问题」游戏,每问一个问题(比如「花瓣长 > 2.5 cm 吗?」)就把数据分成两堆,问得越准,分出的堆越「纯」3。衡量「纯不纯」的数叫不纯度:一堆数据里标签越五花八门,不纯度越高;全是同一标签,不纯度为 04

原书选来量不纯度的,是基尼系数:把每个标签的数据占比 p 算出来,基尼系数 = 1 − Σp²(c 是标签数)5。直觉一句话:从这堆里随机抽两个点,标签不同的概率越大,这堆越乱。两类各占一半时 1 − 0.5² − 0.5² = 0.5(最乱);清一色时 = 0(最纯)。

主走查:三个切口,0.5 → 0.44 → 0.25

原书图 2-31 用 6 个点(3 个 ○、3 个 ×)演示了同一批数据的三种切法,加权平均基尼系数分别是多少(逐格推算过程为演示补算,分组数字与结果均取自原书)6:

切法一:不切(分割前)
一堆 6 点(3○3×):1 − (3/6)² − (3/6)² = 0.5

切法二:切成 3 点 + 3 点(每堆 1○2× 和 2○1×)
左堆:1 − (1/3)² − (2/3)² = 4/9;右堆同为 4/9
加权:(3/6)×(4/9) + (3/6)×(4/9) ≈ 0.44

切法三:切成 4 点 + 2 点(1○3× 和 2○0×)
左堆:1 − (1/4)² − (3/4)² = 0.375;右堆:清一色 → 0
加权:(4/6)×0.375 + (2/6)×0 = 0.25 ← 最纯,选它!

图说:切法三把所有 × 都关进左堆、所有 ○ 关进右堆,
一步就把数据切干净了。加权 = 每堆的基尼系数 × 该堆数据量占比。

决策树的学习就是把这个动作循环到底:算出所有特征、所有候选切法的不纯度 → 选不纯度减小最多的一刀切下去 → 对切出的每堆再来一遍7。切到每堆足够纯(或树够深)为止。

单棵树的毛病也在这:为了把训练数据切干净,它可以一路切出深度惊人的「怪问题」——这正是第 02 章见过的过拟合的又一副面孔。

3. 投票的数学:三棵 60% 的树,投出 64.8%

一群树投票为什么能赢过单棵?原书给了一笔能口算的账。假设有 3 棵彼此独立的树,每棵正确率 0.6,投票取多数8:

表决失败 = 至少 2 棵错:
3 棵全错: (1 − 0.6)³ = 0.064
恰好 2 错: 3 × (1 − 0.6)² × 0.6 = 0.288
表决正确 = 1 − 0.064 − 0.288 = 0.648

0.648 > 0.6,一群平庸的评委投出了高于任何单个评委的正确率。这正是多数表决(少数服从多数、按票数定结果)在机器学习里的样子,原书把它比作「找别人商量事情,不只听一个人的意见」9

但账里那个前提——「彼此独立」——才是真正的难点。机器学习从同样的数据用同样的方法学,结果基本一样:100 棵长得一模一样的树,投票投出来的还是同一棵树的意见,表决毫无意义10

4. 造出「不同」的两招

随机森林用两招强迫树与树不同11:

招式做法制造的差异
Bootstrap对训练数据随机抽样放回、重复多次,给每棵树造一份「大同小异」的数据——原书称之为「虚增」训练数据每棵树看到的样本不同(有的点被抽中多次,有的没被抽到)
随机选特征每次切分时只从一部分特征里挑切法每棵树关注的角度不同

两招叠加,几百棵树就成了几百位「从不同角度看过案情」的评委——多数表决的数学前提这才成立。

白送的礼物:特征重要度

森林还附带一份报告:每个特征对预测的重要度。算法是把所有树里「以某特征分割时减掉的不纯度」取平均——经常能大幅降不纯度的特征得分高,切了也白切的特征得分低12。重要度低的特征可以直接删掉。

原书拿葡萄酒分类验证:得分最高的特征是 color_intensity(色泽),而「色泽对葡萄酒分类很重要」这个结论直观,让人信服13——重要度排名不光有用,还能拿常识对账,这是它比其他「黑箱分数」讨喜的地方。

5. 作者的判断与证据

说法性质依据
3 棵 0.6 的树投票得 0.648书内给完整概率演算数字链在正文8
0.44 与 0.25 的两种切法对比书内给出计算式演算可见6
「多棵汇总一定能创建泛化更强的模型」注意:书内这句说得过满——它依赖树之间足够独立,而独立程度没有保证书内断言2 + 判断块
color_intensity 重要度最高书内实验输出 + 常识印证图示结果13
随机森林与梯度提升同属「综合多模型」作者的分类陈述,梯度提升未展开一句带过1

判断(我们的,不是书里的): 原书「多个决策树汇总起来,一定能创建出泛化能力更强的模型」这句话,置信度应打折扣。投票数学的前提是评委彼此独立、错误不相关;Bootstrap 和随机特征只能制造「不完全相关」,不是真独立。实践中随机森林几乎总是不差于单棵树,但「一定更强」是营销口吻,不是定理。 如果错,会错在: 若树之间高度相关(比如某个特征压倒性重要,每棵树都围着它转),投票退化为重复计票,提升会趋近于零;遇到这种数据,应调大「每次随机选特征」的比例限制,而不是怀疑投票本身。

6. 边界与局限

  • 原书没有讲树该长多深、多少棵树合适——树数够多时投票结果会稳定,但深度不控照样集体过拟合(补充:不在书里,来自通用知识)。
  • 特征重要度有已知偏差:取值多、类别多的特征容易虚高——原书完全没提,用的时候别拿它当唯一证据(补充:不在书里,来自通用知识)。
  • 投票能修「方差大」的树(不稳定、换一组数据就变样),修不了「偏差大」的树(问题本身没建模对)——这正是梯度提升那一族后来补的位置,原书只留了一个名字1
  • 版本提示:原书 RandomForestClassifier() 默认参数在葡萄酒数据上正确率 0.944414

7. 可带走的

  1. 决策树 = 反复挑「让不纯度降最多」的切口;不纯度用基尼系数(1 − Σp²)量;
  2. 基尼系数的直觉:随机抽两个点标签不同的概率;清一色为 0,一半对一半为 0.5;
  3. 投票数学:3 棵各 0.6 的树 → 0.648;评委平庸没关系,关键是别犯一样的错;
  4. 多样性是投票的前提:同数据同方法的 100 棵树等于 1 棵;
  5. Bootstrap(抽样放回「虚增」数据)+ 随机选特征 = 强迫树与树不同;
  6. 特征重要度 = 所有树里该特征切割时的不纯度改善取平均;重要度低的可删;
  7. 重要度排名要拿常识对账(色泽对葡萄酒重要——通过了);
  8. 随机森林与梯度提升同族;前者各判各的、同时开票,后者一棵接一棵串行纠错,本书只展开前者;
  9. 「一定更强」别当定理听:评委相关性高时,提升趋近于零。

8. 原文地图

主题原书章原文位置
多模型综合、梯度提升2.7 算法7:随机森林text/12-ch02-07-2-7-7.txt:2(搜「将多个模型综合起来」) · text/12-ch02-07-2-7-7.txt:3(搜「梯度提升」)
比单棵树精度高2.7 算法7:随机森林text/12-ch02-07-2-7-7.txt:8(搜「比单个决策树更高的预测精度」)
决策树与不纯度2.7 算法7:随机森林text/12-ch02-07-2-7-7.txt:39(搜「不纯度的数值」) · text/12-ch02-07-2-7-7.txt:40(搜「相同的标签时,不纯度会变小」)
基尼系数定义2.7 算法7:随机森林text/12-ch02-07-2-7-7.txt:42(搜「本节利用基尼系数」) · text/12-ch02-07-2-7-7.txt:48(搜「数据数量占数据总数的比例」)
三种切法 0.5/0.44/0.252.7 算法7:随机森林text/12-ch02-07-2-7-7.txt:49(搜「加权平均基尼系数」) · text/12-ch02-07-2-7-7.txt:65(搜「= 0.25」)
学习三步循环2.7 算法7:随机森林text/12-ch02-07-2-7-7.txt:71(搜「不纯度减小最多」)
三棵树投票 0.6482.7 算法7:随机森林text/12-ch02-07-2-7-7.txt:79(搜「每棵的正确率为」) · text/12-ch02-07-2-7-7.txt:82(搜「0.064」) · text/12-ch02-07-2-7-7.txt:83(搜「0.288」)
100 棵一样的树无意义2.7 算法7:随机森林text/12-ch02-07-2-7-7.txt:87(搜「即使有 100 棵决策树」)
多样性重要2.7 算法7:随机森林text/12-ch02-07-2-7-7.txt:28(搜「要具备多样性」)
Bootstrap 与随机特征2.7 算法7:随机森林text/12-ch02-07-2-7-7.txt:91(搜「随机的抽样放回」) · text/12-ch02-07-2-7-7.txt:93(搜「只随机选取部分特征」)
特征重要度2.7 算法7:随机森林text/12-ch02-07-2-7-7.txt:151(搜「不纯度并取平均值」) · text/12-ch02-07-2-7-7.txt:153(搜「去除非」)
color_intensity 最高2.7 算法7:随机森林text/12-ch02-07-2-7-7.txt:157(搜「直观,让人信服」)
wine 示例 0.94442.7 算法7:随机森林text/12-ch02-07-2-7-7.txt:143(搜「0.94444444」)
多数表决像找人商量2.7 算法7:随机森林text/12-ch02-07-2-7-7.txt:24(搜「不只听一个人的意见」)

Footnotes

  1. 出处:「2.7 算法7:随机森林」第 2 段(text/12-ch02-07-2-7-7.txt:2,搜「将多个模型综合起来」)与第 3 段(text/12-ch02-07-2-7-7.txt:3,搜「梯度提升」)。 2 3

  2. 出处:「2.7 算法7:随机森林」第 8 段(text/12-ch02-07-2-7-7.txt:8,搜「比单个决策树更高的预测精度」)与第 9 段(text/12-ch02-07-2-7-7.txt:9,搜「一定能创建出泛化能力更强的模型」)。 2

  3. 出处:「2.7 算法7:随机森林」第 38 段(text/12-ch02-07-2-7-7.txt:38,搜「按条件分支进行划分」)。「二十个问题」是我们加的比方。

  4. 出处:「2.7 算法7:随机森林」第 39 段(text/12-ch02-07-2-7-7.txt:39,搜「不纯度的数值」)与第 40~41 段(搜「相同的标签时,不纯度会变小」)。

  5. 出处:「2.7 算法7:随机森林」第 42 段(text/12-ch02-07-2-7-7.txt:42,搜「本节利用基尼系数」)与第 48 段(text/12-ch02-07-2-7-7.txt:48,搜「数据数量占数据总数的比例」)。

  6. 出处:「2.7 算法7:随机森林」第 49 段(text/12-ch02-07-2-7-7.txt:49,搜「加权平均基尼系数」);0.5、≈0.44、0.25 三个数值在第 53~65 段的计算式里(text/12-ch02-07-2-7-7.txt:65,搜「= 0.25」)。逐堆展开是我们补的推算。 2

  7. 出处:「2.7 算法7:随机森林」第 70~72 段(text/12-ch02-07-2-7-7.txt:71,搜「不纯度减小最多」)。

  8. 出处:「2.7 算法7:随机森林」第 79 段(text/12-ch02-07-2-7-7.txt:79,搜「每棵的正确率为」);0.064、0.288、0.648 三个数在第 82~84 段(搜「0.064」「0.288」)。 2

  9. 出处:「2.7 算法7:随机森林」第 24 段(text/12-ch02-07-2-7-7.txt:24,搜「不只听一个人的意见」)。

  10. 出处:「2.7 算法7:随机森林」第 87 段(text/12-ch02-07-2-7-7.txt:87,搜「即使有 100 棵决策树」)。

  11. 出处:「2.7 算法7:随机森林」第 9095 段:Bootstrap 的定义在第 9092 段(text/12-ch02-07-2-7-7.txt:91,搜「随机的抽样放回」),随机选取特征在第 93 段(text/12-ch02-07-2-7-7.txt:93,搜「只随机选取部分特征」)。

  12. 出处:「2.7 算法7:随机森林」第 151 段(text/12-ch02-07-2-7-7.txt:151,搜「不纯度并取平均值」)与第 153 段(text/12-ch02-07-2-7-7.txt:153,搜「去除非」)。

  13. 出处:「2.7 算法7:随机森林」第 156 段(text/12-ch02-07-2-7-7.txt:156,搜「color_intensity 表示色泽」)与第 157 段(text/12-ch02-07-2-7-7.txt:157,搜「直观,让人信服」)。 2

  14. 出处:「2.7 算法7:随机森林」第 143 段(text/12-ch02-07-2-7-7.txt:143,搜「0.94444444」)。