Machine Learning · Decision Tree

从零构建一棵决策树
CART 算法的 Gini 分裂全流程

本页以"西瓜是否好瓜"分类任务为例,逐步演示 CART 决策树如何通过计算 Gini 不纯度与基尼增益,逐层选择最优分裂特征,最终生成一棵完整的分类决策树。每一步都附有可交互的计算工具。

8 条训练样本
3 个特征维度
2 层分裂深度
3 个叶子节点
01

Gini 不纯度基础

公式与含义

Gini 不纯度(Gini Impurity)是 CART 决策树用于衡量节点混乱程度的核心指标。其计算公式为:

Gini 不纯度
$$\mathrm{Gini} = 1 - \sum_{i} p_i^2$$

其中 $p_i$ 表示第 $i$ 类样本在当前节点中所占的比例。

i
直观理解:Gini 等于从节点中随机抽取两个样本,它们类别不同的概率。Gini 越小,节点越"纯净"(同一类样本占绝大多数);Gini 越大,节点越混乱(各类样本混杂)。

简单算例

全红球 Gini = 0

10 个全是红球:$p_{\text{红}}=1$

$$\mathrm{Gini}=1-1^2=0$$

完全纯净

5红5蓝 Gini = 0.5

$p_{\text{红}}=0.5,\ p_{\text{蓝}}=0.5$

$$\mathrm{Gini}=1-0.5^2-0.5^2=0.5$$

混乱程度最大

6红4蓝 Gini = 0.48

$p_{\text{红}}=0.6,\ p_{\text{蓝}}=0.4$

$$\mathrm{Gini}=1-0.36-0.16=0.48$$

较为混乱

交互式 Gini 计算器

输入各类别的样本数量,实时观察 Gini 不纯度的变化。

0.375
Gini 不纯度
较为混乱

分裂准则:基尼增益

决策树每次分裂时,会尝试所有可用特征和分割点,计算分裂后的加权 Gini,然后与分裂前的 Gini 比较,差值称为"基尼增益":

基尼增益
$$\text{基尼增益} = \mathrm{Gini}(\text{分裂前}) - \text{加权Gini}(\text{分裂后})$$

加权 Gini 按子节点样本数量加权计算:

加权 Gini
$$\text{加权Gini} = \frac{n_{\text{左}}}{n_{\text{总}}}\times\mathrm{Gini}(\text{左}) + \frac{n_{\text{右}}}{n_{\text{总}}}\times\mathrm{Gini}(\text{右})$$
i
决策树永远选择基尼增益最大的特征作为本次分裂条件。增益越大,说明这次分裂把节点"提纯"得越有效。
02

数据集与分类任务

任务定义

分类目标:根据西瓜的外观特征,判断该西瓜是否为"好瓜"(标签:是 / 否)。

用于判断的特征共 3 个:

纹理
清晰 / 模糊
根蒂
蜷缩 / 硬挺
敲声
浊响 / 沉闷

训练数据集

训练集共包含 8 条样本:

表 1 西瓜分类训练数据集(共 8 条样本)
编号纹理根蒂敲声是否好瓜
1清晰蜷缩浊响
2清晰蜷缩沉闷
3清晰硬挺浊响
4清晰硬挺沉闷
5模糊蜷缩浊响
6模糊蜷缩沉闷
7模糊硬挺浊响
8模糊硬挺沉闷
!
统计:8 条样本中,好瓜 2 条(编号 1、2),坏瓜 6 条(编号 3、4、5、6、7、8)。好瓜占比 25%,坏瓜占比 75%。
03

根节点 Gini 计算(分裂前)

在进行任何分裂之前,全部 8 条样本都在根节点中。我们先计算根节点的 Gini 不纯度,作为后续比较的基准。

1
统计各类别数量
好瓜数量:2 条(样本 1、2) | 坏瓜数量:6 条(样本 3–8) | 总样本数:8 条
2
计算各类别比例
$p_{\text{好}} = 2/8 = 0.25$, $p_{\text{坏}} = 6/8 = 0.75$
3
代入公式计算 Gini
$$\begin{aligned}\mathrm{Gini}(\text{根}) &= 1 - p_{\text{好}}^2 - p_{\text{坏}}^2 \\ &= 1 - 0.25^2 - 0.75^2 \\ &= 1 - 0.0625 - 0.5625 \\ &= \mathbf{0.375}\end{aligned}$$
i
根节点的 Gini 不纯度为 0.375。接下来,我们分别尝试用三个特征对根节点进行分裂,计算每个特征的基尼增益。
04

第一层分裂:逐个特征计算基尼增益

决策树依次尝试"纹理""根蒂""敲声"三个特征,对每个特征都执行:分组统计 → 子节点 Gini 计算 → 加权 Gini 计算 → 基尼增益计算,最后选择增益最大的特征。

按【纹理】分裂

分组统计:

纹理 = 清晰 4 条

样本:1、2、3、4

好瓜 2 坏瓜 2

纹理 = 模糊 4 条

样本:5、6、7、8

好瓜 0 坏瓜 4

1
"清晰"子节点 Gini
$p_{\text{好}}=2/4=0.5,\ p_{\text{坏}}=2/4=0.5$, $\mathrm{Gini}(\text{清晰})=1-0.5^2-0.5^2=\mathbf{0.5}$
2
"模糊"子节点 Gini
$p_{\text{好}}=0,\ p_{\text{坏}}=1$, $\mathrm{Gini}(\text{模糊})=1-0^2-1^2=\mathbf{0}$(全部坏瓜,完全纯净)
3
加权 Gini
$\text{加权Gini}=(4/8)\times0.5+(4/8)\times0=0.25+0=\mathbf{0.25}$
4
基尼增益
$\text{基尼增益}(\text{纹理})=\mathrm{Gini}(\text{根})-\text{加权Gini}=0.375-0.25=\mathbf{0.125}$

按【根蒂】分裂

分组统计:

根蒂 = 蜷缩 4 条

样本:1、2、5、6

好瓜 2 坏瓜 2

根蒂 = 硬挺 4 条

样本:3、4、7、8

好瓜 0 坏瓜 4

1
"蜷缩"子节点 Gini
$p_{\text{好}}=2/4=0.5,\ p_{\text{坏}}=2/4=0.5$, $\mathrm{Gini}(\text{蜷缩})=1-0.5^2-0.5^2=\mathbf{0.5}$
2
"硬挺"子节点 Gini
$p_{\text{好}}=0,\ p_{\text{坏}}=1$, $\mathrm{Gini}(\text{硬挺})=1-0^2-1^2=\mathbf{0}$(全部坏瓜,完全纯净)
3
加权 Gini
$\text{加权Gini}=(4/8)\times0.5+(4/8)\times0=0.25+0=\mathbf{0.25}$
4
基尼增益
$\text{基尼增益}(\text{根蒂})=0.375-0.25=\mathbf{0.125}$

按【敲声】分裂

分组统计:

敲声 = 浊响 4 条

样本:1、3、5、7

好瓜 1 坏瓜 3

敲声 = 沉闷 4 条

样本:2、4、6、8

好瓜 1 坏瓜 3

1
"浊响"子节点 Gini
$p_{\text{好}}=1/4=0.25,\ p_{\text{坏}}=3/4=0.75$, $\mathrm{Gini}(\text{浊响})=1-0.25^2-0.75^2=\mathbf{0.375}$
2
"沉闷"子节点 Gini
$p_{\text{好}}=1/4=0.25,\ p_{\text{坏}}=3/4=0.75$, $\mathrm{Gini}(\text{沉闷})=1-0.25^2-0.75^2=\mathbf{0.375}$
3
加权 Gini
$\text{加权Gini}=(4/8)\times0.375+(4/8)\times0.375=0.1875+0.1875=\mathbf{0.375}$
4
基尼增益
$\text{基尼增益}(\text{敲声})=0.375-0.375=\mathbf{0}$
!
敲声的基尼增益为 0,说明按敲声分裂后,两个子节点的好坏瓜比例与根节点完全相同(都是 1:3),分裂没有带来任何"提纯"效果。因此敲声是一个无效特征,决策树不会选择它。

第一层分裂结果对比与选择

纹理
0.125
基尼增益
根蒂
0.125
基尼增益
敲声
0
无效特征
i
纹理和根蒂的基尼增益相同(均为 0.125),任选其一即可。本例选择【纹理】作为根节点的分裂特征。

分裂后各子节点状态

纹理 = 模糊 叶子节点

样本:5、6、7、8(全部坏瓜)

$\mathrm{Gini}=0$,节点纯净,停止分裂,预测"坏瓜"

纹理 = 清晰 继续分裂

样本:1、2、3、4(好瓜 2,坏瓜 2)

$\mathrm{Gini}=0.5$,节点仍然混乱,需要继续分裂

05

第二层分裂:纹理清晰子节点

当前节点状态

进入第二层的是"纹理 = 清晰"子节点,包含样本 1、2、3、4,共 4 条:

好瓜
2 条
样本 1、2
坏瓜
2 条
样本 3、4
$$\mathrm{Gini} = 1 - (2/4)^2 - (2/4)^2 = 1 - 0.25 - 0.25 = \mathbf{0.5}$$
!
纹理特征已经在上一层使用过,本层不再重复使用。可用特征为"根蒂""敲声"

按【根蒂】分裂

根蒂 = 蜷缩 2 条

样本:1、2 → 好瓜 2 坏瓜 0

Gini = 0(完全纯净)

根蒂 = 硬挺 2 条

样本:3、4 → 好瓜 0 坏瓜 2

Gini = 0(完全纯净)

1
两个子节点 Gini
$\mathrm{Gini}(\text{蜷缩})=1-1^2-0^2=0$, $\mathrm{Gini}(\text{硬挺})=1-0^2-1^2=0$
2
加权 Gini 与基尼增益
$\text{加权Gini}=(2/4)\times0+(2/4)\times0=\mathbf{0}$
$\text{基尼增益}(\text{根蒂})=0.5-0=\mathbf{0.5}$
i
按根蒂分裂后,两个子节点的 Gini 均为 0,全部纯净——这是一次完美分裂,基尼增益达到 0.5(最大值)。

按【敲声】分裂

敲声 = 浊响 2 条

样本:1、3 → 好瓜 1 坏瓜 1

Gini = 0.5

敲声 = 沉闷 2 条

样本:2、4 → 好瓜 1 坏瓜 1

Gini = 0.5

1
加权 Gini 与基尼增益
$\text{加权Gini}=(2/4)\times0.5+(2/4)\times0.5=\mathbf{0.5}$
$\text{基尼增益}(\text{敲声})=0.5-0.5=\mathbf{0}$
!
敲声在本层依然没有区分能力,基尼增益为 0。两个子节点都是 1 好 1 坏,与分裂前完全相同。

第二层分裂结果选择

根蒂
0.5
基尼增益(完美分裂)
敲声
0
无效特征

选择【根蒂】作为第二层分裂特征。分裂后:

根蒂 = 蜷缩

样本 1、2,全部好瓜,Gini = 0

叶子节点,预测"好瓜"

根蒂 = 硬挺

样本 3、4,全部坏瓜,Gini = 0

叶子节点,预测"坏瓜"

i
至此,所有叶子节点的 Gini 均为 0,全部纯净,决策树停止生长
06

最终决策树结构

经过两层分裂,最终得到的决策树结构如下:

模糊 清晰 蜷缩 硬挺 纹理? Gini = 0.375 · 8条 预测:坏瓜 Gini=0 · 4条样本 根蒂? Gini = 0.5 · 4条 预测:好瓜 Gini=0 · 2条样本 预测:坏瓜 Gini=0 · 2条样本
树结构文字描述
根节点:纹理?
├── 纹理 = 模糊 ──→ 叶子节点:预测【坏瓜】(Gini=0,4条样本)
└── 纹理 = 清晰 ──→ 根蒂?
    ├── 根蒂 = 蜷缩 ──→ 叶子节点:预测【好瓜】(Gini=0,2条样本)
    └── 根蒂 = 硬挺 ──→ 叶子节点:预测【坏瓜】(Gini=0,2条样本)
i
整棵树共有 3 个叶子节点,训练集 8 条样本全部被正确分类。
07

新样本预测过程

训练完成后,对新样本进行预测时,不需要再计算任何 Gini 值,只需将新样本的特征值沿决策树的判断规则逐层向下走,直到到达叶子节点,输出该叶子的预测类别即可。

交互式预测工具

选择一个新西瓜的特征值,点击"开始预测",观察决策树如何逐层判断。

预测示例 1

新来一个西瓜,特征为:纹理 = 清晰,根蒂 = 蜷缩,敲声 = 沉闷

1
到达根节点,判断纹理
纹理 = 清晰 → 进入右分支(纹理清晰子节点)
2
到达第二层节点,判断根蒂
根蒂 = 蜷缩 → 进入左分支,到达叶子节点
3
输出预测结果
该叶子节点预测类别为 好瓜

预测示例 2

新西瓜:纹理 = 模糊,根蒂 = 蜷缩,敲声 = 浊响

1
纹理 = 模糊 → 直接到达叶子节点
无需继续判断根蒂和敲声,预测结果为 坏瓜
!
当纹理为模糊时,根蒂和敲声的值不会被使用,因为在树的结构中,纹理模糊的分支直接就是叶子节点。这体现了决策树特征选择的稀疏性——不是所有特征都会被用到。
08

关键要点总结

分裂规则

  • 决策树每次分裂时,遍历所有可用特征,计算每个特征的基尼增益,永远选择增益最大的特征进行分裂。
  • 基尼增益 = 分裂前 Gini − 分裂后加权 Gini,增益越大说明分裂越有效。

特征有效性

  • 一个特征必须与标签存在统计关联,才会产生正的基尼增益。
  • 如果特征与标签完全无关(如本例的敲声),分裂后子节点的类别比例与父节点相同,基尼增益为 0,决策树不会选用该特征。
  • 决策树只学习数据中的统计关联,不判断因果关系。特征是否"有道理"不影响算法选择,只看数据分布。

加权 Gini 的重要性

  • 比较分裂效果时,必须使用加权 Gini(按子节点样本数量加权),而不是单独看某个子节点的 Gini。
  • 样本多的子节点对整体混乱度的贡献更大。

停止条件

  • 节点样本全部属于同一类(Gini = 0,纯净),停止分裂。
  • 节点样本数量过少(低于阈值),停止分裂。
  • 树的深度达到预设上限,停止分裂(防止过拟合)。
  • 所有可用特征的基尼增益均为 0,停止分裂。

训练与预测的区别

训练阶段

需要反复计算 Gini 和基尼增益,选择最优分裂特征,构建树结构。计算量大,是"学习"的过程。

预测阶段

不需要计算任何 Gini,只需将新样本沿树的判断规则走到叶子节点,输出叶子的类别即可。速度极快。