目录
一、决策树
1.1 什么是决策树?
1.2 为什么需要决策树?
1.3 如何使用决策树
1.4 分裂准则:树怎么从数据里长出来?
1.5 实际案例
1.6 决策树在现实生活中的应用
二、随机森林
2.1 什么是随机森林?
2.2 为什么需要随机森林?
2.3 如何使用随机森林
2.4 分裂与训练:和单棵树有何不同?
2.5 实际案例
2.6 随机森林在生活中的应用
一、决策树
1.1 什么是决策树?
决策树是一种可解释的分类(或回归)模型。它不做「加权求和」,而是把特征空间切成一块块区域,每一块对应一条 if-else 规则——比如「若 收入 ≤ 5万 且 负债比 > 0.6 → 违约」。预测时,从根节点顺着问题往下走,落到哪个叶子,就输出那个叶子的结论。
一句话总结,决策树(Decision Tree) 用来分类或回归——分类时会问「落到哪一类?」,规则像人写的判断流程。
1.2 为什么需要决策树?
我们都知道:逻辑回归是什么


意思是:所有特征线性组合后过Sigmoid,得到概率,在二维平面上,决策边界是一条直线。
但是它能干什么?
两个指标就能分两类、还要概率——逻辑回归很合适。边界大致是直线时,简单、快、可解释(看系数
)。
但是换到另一个场景:就不行了
真实数据里,边界常常是弯的、阶梯状的,不是一条直线。 比如:「收入高 且 负债低 → 不违约;收入中等 但 信用分低 → 违约」——这是分段规则,不是「全体特征乘一个
再加起来」能轻松表达的。
硬用逻辑回归:要么准确率上不去,要么得手工造
、
等特征,费时且不好维护。
所有一句话: 逻辑回归=全局一条(超)平面;很多业务规则 = 先问 A,再问 B,再下结论——问法不同,模型结构就该不同。
所以在上述场景下就有了:决策树
不再学一组
,而是学一串分裂问题:
根:「特征1 ≤ 0.5?」→ 左 / 右
左子:「特征2 ≤ -1.2?」→ 再分……
直到叶子:「这里 80% 是类 1」→ 预测类 1
所以决策树补上的,就是「用 if-else 规则做分类,边界可以是矩形阶梯,且树本身就能画给人看」。
1.3 如何使用决策树
步骤一:从根节点出发
每个内部节点存一条规则:选某个特征
,和阈值
,问「
」
步骤二:向左或向右
是 → 走左子树
否 → 走右子树
步骤三:到达叶子
叶子不再分裂,存该节点的多数类(分类)或平均值(回归)。
分类预测:
=leaf_calss(x)
即新样本从根往下走,第一条走不通的路尽头,就是预测结果。
1.4 分裂准则:树怎么从数据里长出来?
训练不是算
,而是递归选「哪个特征、哪个阈值」分裂,让子节点更「纯」。
分类:Gini(基尼)不纯度(sklearn 默认)
节点里各类比例为
,Gini:

全是同一类 → G=0G=0(最纯)
两类各半 → G=0.5G=0.5(最混)
训练目标: 每次分裂选使加权 Gini 下降最多的特征和阈值。
另一种:信息熵

分裂后子节点熵越小越好。Gini 与熵在实践中往往接近。
同时必须防住:过拟合
树可以一直长到「每个叶子只有一个样本」——训练集 100% 对,测试集可能崩。
| max_depth | 限制树最深几层 |
| min_samples_leaf | 叶子至少几个样本 |
| min_samples_split | 节点至少几个样本才允许分裂 |
| 剪枝 | 长完再砍掉不划算的枝 |
所以树不是越深越好;浅一点的树 = 更简单的规则 = 往往泛化更好。
1.5 实际案例
第一步:获取数据
我有一组三百个数据
| 样本ID | 特征1![]() |
特征2![]() |
是否正类![]() |
| 1 | 0.733246 | -1.43101 | 0 |
| 2 | 0.656043 | 0.842841 | 1 |
| 3 | 0.537983 | -2.05655 | 0 |
| 4 | 1.289308 | -0.07902 | 1 |
| … | … | … | … |
| 300 | 1.715959 | 1.168337 |
1 |
300 条、2 个特征——专门为了能把决策边界和整棵树画出来。
第二步:训练
tree = DecisionTreeClassifier(max_depth=3, random_state=42)
tree.fit(X_train, y_train)
max_depth=3:最多 3 层,避免树太复杂。
第三步:运行结果
树的最大深度(设置): 3 实际叶子数: 7 测试集准确率: 0.9733
- precision recall f1-score support
- 类 0 0.97 0.97 0.97 38
- 类 1 0.97 0.97 0.97 37
- accuracy 0.97 75
- macro avg 0.97 0.97 0.97 75
- weighted avg 0.97 0.97 0.97 75
准确率 97.3%:测试集 75 条里错 2 条(73 条判对)。分类报告里两类精确率、召回率都在 0.97 左右,说明浅树已经把这组二维数据分得很干净。
第四步:看图

绝大多数点落在「与自己颜色一致」的背景区;仅 2 个点跨到了对面——和 97.3% 准确率一致。这 2 个错分点分别落在矩形交界附近(例如 x1≈1.66、x2≈0.19 一带),属于「刚好卡在阈值边上」的样本,浅树分错可以接受。

该叶子里多数类的占比——越深说明这片区域越「纯」,max_depth=3,共 7 片叶子;从根到叶最深 3 层,规则简短,业务能逐条念出来。
(对应主要代码见决策树与随机森林.py 中 demo_decision_tree())
1.6 决策树在现实生活中的应用
场景一:信贷规则引擎
-
输出: 通过 / 拒绝 + 可审计的规则路径
-
价值: 监管、业务都能读懂「为什么拒贷」
场景二:医疗筛查
-
输出: 高风险 / 低风险
-
价值: 「若 年龄>60 且 指标X>阈值 → 建议复查」
场景三:运营策略
-
输出: 用户分群后的不同策略
-
价值: 树的路径 = 可直接变成运营 if-else
共同特点:需要规则可读,而不只是黑盒分数。
二、随机森林
2.1 什么是随机森林?
随机森林 = 很多棵决策树组成的「委员会」。每棵树在略有不同的数据、略有不同的特征子集上训练;预测时,分类任务多数投票,回归任务取平均。它保留了树模型处理非线性的能力,又通过集成降低单棵树的过拟合风险。
一句话总结,随机森林(Random Forest) 是Bagging+决策树 的经典组合——问的是「多棵树一起,结论是什么?」
2.2 为什么需要随机森林?
我们都知道:单棵决策树是什么
从根到叶走 if-else,落到叶子取多数类——好懂、好画。
但是它能干什么?
数据不多、要快速出规则、要给业务讲清楚——一棵浅树很合适。
但是换到另一个场景:就不行了
单棵树太「任性」:
- 训练集改几个样本,树形状可能大变(高方差)
- 深度不限时,训练集准确率可以 100%,测试集却掉很多(过拟合)
- 特征一多,单棵树容易只盯着少数特征,稳定性差
你要的是:精度更高、对新数据更稳、还能看特征重要性——一棵树的短板正好在这些地方。
所以单棵决策树 = 一个专家;
而随机森林 = 多个专家独立判断再投票——集成换稳定与精度。
所以有了:随机森林
训练B棵树(如 B=100),每棵树:
或
个特征里选最优预测:
(分类,投票)
随机森林补上的,就是「多棵树的集体智慧 + 特征重要性 + 通常更好的泛化」。
2.3 如何使用随机森林
训练阶段(每棵树独立):
- 抽一份 Bootstrap 训练子集
- 在这份子集上建一棵决策树(通常不剪枝或浅剪枝)
- 分裂时在随机子集的特征里选最佳分裂
预测阶段:
- 每个测试样本进每一棵树,各得一个预测
- 分类: 票最多的类获胜
- 回归: 所有树预测值平均
| n_estimators | 多少棵树 |
| max_depth | 每棵树最大多深 |
| max_features | 分裂时最多看几个特征 |
| random_state | 随机种子,可复现 |
2.4 分裂与训练:和单棵树有何不同?
单棵树内部的分裂准则不变(仍是 Gini / 熵)。 随机森林的「随机」体现在两层:
| 样本随机(Bootstrap) | 每棵树看的数据略有不同,降低相关性 |
| 特征随机 | 每棵树不能总在同一个特征上分裂,更均衡 |
为什么有效? 多棵相关度低的树集成 → 误差相互抵消 → 方差下降,测试表现往往优于单树。
特征重要性: 看每个特征在所有树的所有分裂中,让 Gini 下降累计多少——不用单独做特征工程也能知道「谁更重要」。
2.5 实际案例
上述四小节内容应该听着很抽象,不理解,那么下面的实际案例可以帮助更好的理解随机森林。
第一步:获取数据
4 个特征(年龄、收入、负债比、信用分)→ 是否违约,500 条——更接近真实表格风控场景。
| 样本ID | 年龄![]() |
收入![]() |
负债比![]() |
信用分![]() |
是否违约![]() |
| 1 | -2.42315 | -3.03102 | -2.5106 | 1.22719 | 0 |
| 2 | -2.31301 | -2.93084 | -2.24104 | 1.336992 | 0 |
| 3 | 0.158133 | -0.47869 | -0.82108 | 0.069002 | 0 |
| … | … | … | … | … | … |
| 500 | 0.257668 | -0.36222 | -0.45123 | 0.228743 | 0 |
第二步:训练
rf = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=42)
rf.fit(X_train, y_train)
第三步:运行结果
- 树的数量 n_estimators: 100
- 测试集准确率: 0.9760
- precision recall f1-score support
- 不违约 0.98 0.97 0.98 63
- 违约 0.97 0.98 0.98 62
- accuracy 0.98 125
- macro avg 0.98 0.98 0.98 125
- weighted avg 0.98 0.98 0.98 125
测试集 125 条里错 3 条。不违约、违约两类的精确率、召回率都在 0.97~0.98,F1 约 0.98——对模拟信贷表来说,随机森林已经是很强的结果。
第四步:特征重要性图

- 横条越长:该特征在所有树的分裂里,累计让 Gini 下降越多 → 对「是否违约」预测越关键。
- 本次排序:
- 年龄_x1 ≈ 65.5%——遥遥领先,是头号因素;
- 收入_x2 ≈ 16.4%——次之;
- 负债比_x3 ≈ 9.2%、信用分_x4 ≈ 8.9%——也有贡献,但明显弱于前两项。
那么从图中可以看出,若要做风控策略,会优先盯「年龄 + 收入」,再辅以负债、信用分;这和 97.6% 测试准确率一致——模型主要凭前两个特征就把两类分开了。
第五步:与单棵树对比

三根柱里,绿色「随机森林」最高(0.976)——同一批信贷数据上,集成投票比单棵树更稳。
而不限制深度的单棵树训练集 100%、测试只有 93.6%,中间差了一截——说明它把训练集「背」下来了,泛化不如森林。
(对应主要代码见 demo_random_forest() 与 demo_tree_vs_forest())
2.6 随机森林在生活中的应用
场景一:信贷违约评分
- 输出: 违约概率(如 0.82)+ 通过 / 拒绝建议 + 特征重要性排序(本次例子里「年龄」「收入」贡献最大)
- 价值: 精度比单棵树更高、对新客户更稳(多棵树投票,不怕个别样本把整棵树带偏);向风控和监管说明「主要依据哪些字段」,比纯黑盒分数好交代——但不能像单棵树那样只给一条 if-else 路径,必要时再抽几棵代表性树作辅助解释
场景二:医疗风险分层
- 输出: 高风险 / 低风险(或并发症概率)+ 各类别得票比例
- 价值: 年龄、化验指标、病史等多因素非线性叠加,森林能综合判断;投票机制减少「某一两个异常值就误判」的情况;特征重要性可提示「本次模型最看重哪些检查项」,供医生参考——规则是统计意义上的集体结论,不是一条写死的「若 A 且 B」
场景三:客户流失与运营分群
- 输出: 流失概率 + 按概率排序的优先干预名单
- 价值: 海量用户批量打分,按概率分层推送不同策略(高概率流失 → 专属优惠,低概率 → 常规触达);特征重要性告诉运营「该从哪个抓手入手」(如本次数据里年龄影响最大);比单棵树更抗噪声、换一批用户数据后分数更稳——策略是「按概率分层」,不是把某棵树的路径直接抄成运营 if-else
共同特点:需要表格数据上准且稳、能看特征重要性,接受「多棵树投票」的集成结论,而不强求像单棵树那样一条规则走到底。







