写在前面的

以前我写机器学习笔记时,往往会直接进入算法本身。但决策树这部分涉及不少基础概念,所以这次我想先把几个核心名词讲清楚。

决策树就是帮你从混乱中做出决策的。学习各种树的过程就是学习决策树本身。

目前要学习以下3个树。

算法用什么选特征/切分做什么任务树的形状
ID3信息增益(Information Gain)分类多叉树
C4.5信息增益率(Gain Ratio)分类多叉树
CART分类看基尼,回归看误差分类 + 回归二叉树

1 概念

决策树(Decision Tree)是一种树形结构的监督学习算法,广泛用于分类和回归任务。

它通过分而治之的策略,自根至叶将数据集划分为更纯的子集。树的内部节点代表特征属性测试,分支代表测试输出,叶节点代表最终决策结果。因其白盒模型特性,易于理解、可视化和解释。

它的核心思想非常简单:通过不断地问简单的问题,把范围一步步缩小,最终得到一个确定的答案

大概就是。你今天下班回家,想亲手做顿饭放松一下。但你不确定具体要做什么,你的大脑其实就会自动构建一棵决策树来帮你做决定。你通过问一系列只要回答『是』或『否』的小问题,把一个复杂的大决定(吃什么),拆解成了一步步的路径。比如下面的例子。

第一个问题:今天有充足的时间吗?

  • 是 ➡️ 顺着树枝往下走,遇到下一个问题:冰箱里有肉吗?
    • 回答『有』 ➡️ 结论:做个耗时的炖肉。
    • 回答『没有』 ➡️ 结论:做个精致的素菜。
  • 否 (想快点吃上饭) ➡️ 顺着另一根树枝往下走,遇到下一个问题:非常饿吗?
    • 回答『是』 ➡️ 结论:快速煮个面条。
    • 回答『否』 ➡️ 结论:拌个简单的沙拉。

决策树长什么样?

根节点(Root Node): 树的最顶端,也就是你问的第一个也是最关键的问题比如『今天有充足的时间吗?』。

内部节点(Internal Node): 树枝中间的那些后续问题比如『冰箱里有肉吗?』。

叶子节点(Leaf Node): 树的最末端,也就是最终的决定或分类结果比如『煮个面条』。到了叶子这里,问题就问完了,游戏结束。

感觉就是⬇️

决策树基础| Javen Chen's Blog

2 分类

这里原本写的是学习必备基础,但是后来想一下,其实按照具体的树来看会比较好。利用概念学习具体的树进行计算会学得更快。

  • ID3 ➡️ 信息熵 信息增益的概念
  • C4.5 ➡️ 信息增益率的概念
  • CART树 ➡️ 基尼指数

3 ID3

了解了决策树是什么之后,下一步就是思考:怎样才能把最重要的特征放在根节点上?这样就知道下一步又是什么节点了。

比如对于一些人来说,长得帅就是比有钱重要的多多多!!那我们如何去选择最重要的那个特征第一选择呢?这就需要引入 ID3 中最核心的两个概念:信息熵(Entropy) 和 信息增益(Information Gain)。

3-1 信息熵 Information Entropy

在决策树中,信息熵是用来衡量一个数据集的『混乱度』或『不纯度』的指标。

  • 熵越小:数据越纯,越整齐(比如一筐全是苹果,毫无悬念)。
  • 熵越大:数据越乱,越难预测(比如一筐里有 5 个苹果、5 个橘子,随便抓一个,你很难确定是什么)。

为什么会出现信息熵?

接着上面的比喻来说。这棵树怎么知道第一个问题应该问『时间充不充足』,而不是问『今天穿了什么颜色的衣服』呢?

这就回到我们『信息熵』了。机器在构建这棵树时,会在每一步挑问题。它挑选的标准就是:哪个问题能让剩下的选项变得最清晰、最不混乱?(也就是让信息熵下降最多)。

因为『今天穿了什么颜色的衣服』对决定晚饭吃什么毫无帮助(信息熵没有下降)。而『时间充不充足』能瞬间帮你排除掉一大半不现实的菜谱,让你的目标变得非常纯净,所以它成了最完美的『根节点』。

那如何计算呢?

计算信息熵步骤

假设我们有一个数据集 D,里面有 c 种不同的类别。第 i 种类别在数据集中所占的比例(概率)是 pi。那么这个数据集的信息熵 H(D) 的公式是

H(D)=−∑i=1cpilog⁡2(pi)H(D) = - \sum_{i=1}^{c} p_i \log_2(p_i)
  • pi某个类别的概率。
  • log代表 以 2 为底的对数。因为 pi 肯定是0-1之间的小数。所以出来的对数必定是负数或 0。
  • 前面的负号为了把最终结果变成正数,方便我们比较。
  • 把所有类别的 pi 和log2(pi) 算出来后,全部加在一起。
[feature, label]
[a, x]
[b, x]
[b, y]
[c, y]
[c, y]

⚠️ 记住一个很重要的理论,总体的信息熵是对于 标签 的,比如上面,那么就只关注x和y,不关注feature。

⬆️ 什么玩意儿?不会算,那么直接给例子。

假设我们有一个装了 10 个球的盲盒,球只有两种颜色:红色和蓝色。

  • 极端情况 1:最混乱的状态(5 红 5 蓝)

    • 红球概率 p1 = 5/10 = 0.5 = 1/2
    • 蓝球概率 p1 = 5/10 = 0.5 = 1/2
    H(D)=−[p1log⁡2(p1)+p2log⁡2(p2)]H(D) = - [ p_1 \log_2(p_1) + p_2 \log_2(p_2) ] H(D)=−[0.5×(−1)+0.5×(−1)]H(D) = - [ 0.5 \times (-1) + 0.5 \times (-1) ] H(D)=−[−0.5−0.5]=−[−1]=1H(D) = - [ -0.5 - 0.5 ] = - [ -1 ] = 1

    最后结果就是1。结论➡️当两种类别势均力敌(各占 50%)时,混乱度最高,信息熵达到最大值 1。

  • 极端情况 2:最纯粹的状态(10 红 0 蓝)

    • 红球概率 p1 = 10/10 = 1

    • 蓝球概率 p2 = 0/10 = 0

      H(D)=−[1×log⁡2(1)+0]H(D) = - [ 1 \times \log_2(1) + 0 ] H(D)=−[1×0+0]=0H(D) = - [ 1 \times 0 + 0 ] = 0

    最后结果就是0。当数据里只有一种东西时,没有任何不确定性,信息熵为 0。

  • 一般情况:偏向某一边(7 红 3 蓝)

    • 红球概率 p1 = 7/10 = 0.7
    • 蓝球概率 p2 = 3/10 = 0.3
    H(D)=−[0.7log⁡2(0.7)+0.3log⁡2(0.3)]H(D) = - [ 0.7 \log_2(0.7) + 0.3 \log_2(0.3) ]

    这里就不能口算log了,那么就是计算器计算

    log⁡2(0.7)≈−0.515\log_2(0.7) \approx -0.515 log⁡2(0.3)≈−1.737\log_2(0.3) \approx -1.737

    最后继续计算

    H(D)≈−[(0.7×−0.515)+(0.3×−1.737)]H(D) \approx - [ (0.7 \times -0.515) + (0.3 \times -1.737) ] H(D)≈−[−0.3605−0.5211]≈0.8816H(D) \approx - [ -0.3605 - 0.5211 ] \approx 0.8816

    你可以看到,随着红球变多(从 5 个变成 7 个),数据集变得稍微纯了一点,所以信息熵从最大值 1 下降到了 0.8816。

    重点1 只是关注label,也就是结果。不关心feature

    重点2 计算公式要记牢

3-2 信息增益 Information Gain

如果把『信息熵』比作房间的混乱程度,那么『信息增益』就是你打扫了一次房间后,混乱程度减少了多少。也就是上面我说的

决策树在每一次要分叉(提问)的时候,都会把所有能问的问题在心里默默算一遍,然后挑出一个能让『信息增益』最大(也就是让混乱度下降最多)的问题。接下来就是有点难的公式理解了

我们一般用 D 代表我们要处理的数据集,用 a 代表我们用来分类的某个特征(比如『大小』或『颜色』)

信息增益的正式数学公式是这样的⬇️

Gain(D,a)=H(D)−∑v=1V∣Dv∣∣D∣H(Dv)Gain(D, a) = H(D) - \sum_{v=1}^{V} \frac{|D^v|}{|D|} H(D^v)

依然还是不懂怎么计算的话,就接着看例子。

下面给一个盲盒例子。总共 10 个球:7 个红球,3 个蓝球。大球有 5 个:全是红球(5 红 0 蓝)。小球有 5 个:有红有蓝(2 红 3 蓝)。整理成表格是这样的。

编号 (ID)属性:大小 (feature)结果:颜色 (label)
1大红
2大红
3大红
4大红
5大红
6小红
7小红
8小蓝
9小蓝
10小蓝

现在我们的计算目的就是

通过『按大小分类』,我们到底获得了多少『信息增益』?

计算信息增益

① 计算分开前的总信息熵(总混乱度)

在没按大小分类前,我们面对的是一堆混在一起的 10 个球。

  • 红球概率:p1 = 7/10 = 0.7
  • 蓝球概率:p2 = 3/10 = 0.3

我们套用信息熵公式

H(总)=−(0.7log⁡2(0.7)+0.3log⁡2(0.3))H(\text{总}) = - \left( 0.7 \log_2(0.7) + 0.3 \log_2(0.3) \right)

借助计算器算一下对数。然后代入进去

H(总)=−((0.7×−0.5146)+(0.3×−1.7370))H(\text{总}) = - \left( (0.7 \times -0.5146) + (0.3 \times -1.7370) \right) H(总)=−(−0.3602−0.5211)=0.8813H(\text{总}) = - \left( -0.3602 - 0.5211 \right) = 0.8813

② 分别计算分开后的子节点信息熵

按大小分开后,变成了两堆球,我们挨个算它们的混乱度。

⚠️ 要注意这里计算的是特征之后的标签哦!!不是只看特征!!!

1. 大球堆(5 个球,5 红 0 蓝)

  • 红球概率:p1 = 5/5 = 1

  • 蓝球概率:p2 = 0/5 = 0

    H(大球)=−(1log⁡2(1)+0)=0H(\text{大球}) = - \left( 1 \log_2(1) + 0 \right) = 0

    (合理,完全不乱,混乱度为 0。)

2. 小球堆(5 个球,2 红 3 蓝)

  • 红球概率:p1 = 2/5 = 0.4

  • 蓝球概率:p2 = 3/5 = 0.6

    H(小球)=−(0.4log⁡2(0.4)+0.6log⁡2(0.6))H(\text{小球}) = - \left( 0.4 \log_2(0.4) + 0.6 \log_2(0.6) \right)
log⁡2(0.4)≈−1.3219\log_2(0.4) \approx -1.3219 log⁡2(0.6)≈−0.7370\log_2(0.6) \approx -0.7370 H(小球)=−(−0.5288−0.4422)=0.9710H(\text{小球}) = - \left( -0.5288 - 0.4422 \right) = 0.9710

小球堆里红蓝比例接近一半一半,所以比较混乱,数值接近 1。

③ 计算分开后的『加权平均』信息熵

现在我们有了大球的混乱度(0)和小球的混乱度(0.9710)。因为大球和小球各占了总数的一半(5 个),我们需要按比例把它们加起来。

  • 大球堆占总数的权重:5/10 = 0.5
  • 小球堆占总数的权重:5/10 = 0.5
加权总熵=(0.5×H(大球))+(0.5×H(小球))\text{加权总熵} = (0.5 \times H(\text{大球})) + (0.5 \times H(\text{小球})) 加权总熵=(0.5×0)+(0.5×0.9710)=0.4855\text{加权总熵} = (0.5 \times 0) + (0.5 \times 0.9710) = 0.4855

按大小分类后,整体的混乱度降到了 0.4855。

④ 计算最终的信息增益

这就是最后一步减法了。

信息增益 = 信息熵 - 分类后的加权信息熵

信息增益=0.8813−0.4855=0.3958\text{信息增益} = 0.8813 - 0.4855 = 0.3958

最终答案: 通过问『球是大的还是小的』,我们把混乱度减少了 0.3958,这就是这个条件带来的信息增益!

拆解公式

为了让这个公式更有通用性,下面把它拆开来理解

公式的左半边:老规矩,算总账

  • Gain(D, a):这就是我们要算的最终结果——在数据集 D 上,按属性 a 划分带来的『信息增益』。
  • H(D):划分前,整个大盲盒的初始『信息熵』(也就是我们刚才算出来的总混乱度 0.8813 例子:红蓝球7/3)。

公式的右半边:算分家后的加权平均

Gain(D,a)=H(D)−∑v=1V∣Dv∣∣D∣H(Dv)Gain(D, a) = H(D) - \sum_{v=1}^{V} \frac{|D^v|}{|D|} H(D^v)

右边这一大坨 其实就是我们在第三步算的『加权平均混乱度』。

∑v=1V∣Dv∣∣D∣H(Dv)\sum_{v=1}^{V} \frac{|D^v|}{|D|} H(D^v)
  • V:属性 a 分出了几个岔路。比如按『大小』分,只有大和小两路,那么 V = 2。
  • v:代表具体的某一条岔路(比如第 1 路是大球,第 2 路是小球)。
  • |D|:盲盒里总共的球数(10 个)。
  • |D^v|:分家后,跑到第 v 条岔路里的球数(比如大球有 5 个)。
  • D^v| / |D|:这就是权重比例(比如 5/10 = 0.5)。
  • H(D^v):这条岔路自己内部的『信息熵』(比如大球堆的混乱度 0,小球堆的混乱度 0.9710)。
  • sum (求和符号):意思是把每一条岔路的『权重 * 内部混乱度』挨个算出来,然后全部加在一起。

把我们的盲盒例子代入公式

如果把我们刚才算的具体文字替换进这个公式里,它长这样

Gain(盲盒,大小)=H(总盲盒)−(∣大球堆∣∣总盲盒∣H(大球堆)+∣小球堆∣∣总盲盒∣H(小球堆))\text{Gain}(\text{盲盒}, \text{大小}) = H(\text{总盲盒}) - \left( \frac{|\text{大球堆}|}{|\text{总盲盒}|} H(\text{大球堆}) + \frac{|\text{小球堆}|}{|\text{总盲盒}|} H(\text{小球堆}) \right)

把数字填进去,

Gain=0.8813−(510×0+510×0.9710)=0.3958Gain = 0.8813 - \left( \frac{5}{10} \times 0 + \frac{5}{10} \times 0.9710 \right) = 0.3958

所有的数学符号,最终都落在了这个非常接地气的逻辑上

原先的混乱度,减去按比例算出来的现在的混乱度,就是我赚到的清晰度(信息增益)。

上面这种**用信息增益(Information Gain)**来选择切分特征的决策树方法,就是 ID3 的核心思路。

0.971 - 0.551 = 0.420

0.971 - 0.361 = 0.610 ⬅️ 选这个 因为最后减幅最大

4 C4.5树

只看信息增益会有一个明显问题:它容易偏向那些取值很多的特征。

比如『编号』『身份证号』这类特征,几乎可以把样本切得非常碎,看起来纯度很高,但其实没有泛化能力。

为了修正这个问题,C4.5 引入了 信息增益率(Gain Ratio)。

4-1 ID3弊端

上面说的单纯的计算信息增益的算法是古老的ID3树系列的,到底ID3只看信息熵的弊端在哪里呢?就要理解下面的例子

假设有 4 个周末,我们记录了天气和最终是否去游乐园的数据。

日期编号 (特征 A)天气 (特征 B)是否去游乐园 (标签 / 结果)
1晴天去
2晴天去
3雨天不去
4雨天不去

在还没有做任何分类前,整体的信息熵(看结果列:2 个去,2 个不去,各占 50%)

H(总)=−(0.5log⁡2(0.5)+0.5log⁡2(0.5))=1H(\text{总}) = - \left( 0.5 \log_2(0.5) + 0.5 \log_2(0.5) \right) = 1

因为有2个特征日期编号和天气,那么就分别计算一下信息熵吧。

  • 按照天气分类来计算 信息增益
    • 晴天堆(2 个数据):全是『去』。这堆的内部信息熵为 0。
    • 雨天堆(2 个数据):全是『不去』。这堆的内部信息熵也是 0。

最后的结果就是 信息增益 = 1 - 0 = 1(完美地消除了所有混乱!)

  • 按照编号分类来计算 信息增益

那么直接切成了 4 堆(1号、2号、3号、4号堆)。每一堆里面都只有 1 个数据,毫无悬念,纯度极高,每一堆的内部信息熵全都是 0! 最后的结果就是信息增益 = 1 - 0 = 1(跟天气一样,也完美消除了混乱!)

也就是说无论用编号还是天气最后的结果都是一样的,都是很完美的消除了混乱。

因为 ID3 太古老了,它在实际运用中有两个很明显的缺点:

  1. 极度偏心(就像刚才的编号问题): 它极其偏爱那些『选项特别多』的特征(比如身份证号、日期、产品编号)。它总是误以为切得越碎就越纯,很容易变成一个只会死记硬背的傻瓜。
  2. 只会做选择题,不会算连续数字: 原始的 ID3 只能处理『分类』的数据(比如大/小、红/蓝、晴天/雨天)。如果你的表格里有一列是连续的小数(比如温度是 36.5度、价格是 99.8 元),ID3 就不知道该从哪里劈开它了。

这种『只记住过去,完全无法预测未来』的现象,在机器学习里有一个赫赫有名的名字,叫做『过拟合』(Overfitting)。

所以就出来了另外一个计算方式,也就是需要信息增益率 Information Gain Ratio来出场了。

4-2 分裂信息 Split Information / IV

首先要说明一下,C4.5树的特征就是用信息增益率去判断。如果你只是想要单纯的去计算信息增益率,那么就是下面的公式。

Gain_Ratio=GainSplitInfo=GainIVGain\_Ratio = \frac{Gain}{SplitInfo} = \frac{Gain}{IV}

那么问题来了。上面的分子和分母分别是什么呢?

先看分子,分子其实就是和上面的信息熵。也就是ID3用的,那么主要是分母的Split Information。

这里有一个补充,可能会在很多地方看到分母有不同的公式,但其实是一样的。无论是分裂信息还是IV。其实表示的都是一个意思。

Split Information(分裂信息) 和 IV(Intrinsic Value,固有值) 完全是一码事,它们是同一个概念在不同文献或教材中的不同叫法。

官方原名(Split Information): C4.5 算法的发明者 Ross Quinlan 在他最初发表的论文中,给这个惩罚项起的名字就叫 SplitInfo(分裂信息)。顾名思义,它衡量的是特征把数据集「分裂」开来所产生的信息量大小。

后来的别名(Intrinsic Value / IV): 后来的一些机器学习教材或学者在讲解这个公式时,为了强调这个值是特征「本身自带的、固有的」属性(因为它只看特征自己的分布,完全不看标签分类的结果),就开始用 Intrinsic Value(固有值)来称呼它。

SplitInfoA(D)=IV(A)=−∑v=1V∣Dv∣∣D∣log⁡2(∣Dv∣∣D∣)SplitInfo_A(D) = IV(A) = -\sum_{v=1}^{V} \frac{|D_v|}{|D|} \log_2 \left( \frac{|D_v|}{|D|} \right)
  • |D|:数据集的总样本数。
  • |Dv|:特征 A 的第 v 个取值所包含的样本数。
  • Dv/D:第 v 个分支的样本数占总样本数的比例。

所以上面是1个意思。那么这个分母也就是分裂信息如何计算呢?其实很简单,就是信息熵的计算公式。

因为它们的计算公式一模一样,唯一的区别在于它们在算哪一列数据。

  • 信息熵 盯着的是『结果(标签)』。它关心的是最终分出来的类别纯不纯(比如去还是不去)。
  • IV 盯着的是『切法(特征本身)』。它关心的是你这一刀下去,把数据切成了多少块、碎不碎。

对着label算就是信息熵,对着feature算就是IV。

接下来有一个例子你可以计算一下。

假设我们有 100 个客户样本,我们来计算两个不同特征的固有值。特征是性别。50 男,50 女。特征『性别』把数据分成了 2 份。

  • 男性的比例是 50/100 = 0.5
  • 女性的比例是 50/100 = 0.5

代入公式计算:

IV(性别)=−(0.5×log⁡2(0.5))−(0.5×log⁡2(0.5))IV(性别) = - (0.5 \times \log_2(0.5)) - (0.5 \times \log_2(0.5)) IV(性别)=−(−0.5)−(−0.5)=1.0IV(性别) = - (-0.5) - (-0.5) = 1.0

『性别』的固有值是 1.0。

再来一个例子。

100 个客户,有 100 个不同的身份证号。特征『身份证号』把数据分成了 100 份,每份只有 1 个人。

  • 每个分支的比例都是 1/100 = 0.01

代入公式计算(需要连加 100 次):

IV(身份证号)=−∑v=11000.01×log⁡2(0.01)IV(身份证号) = - \sum_{v=1}^{100} 0.01 \times \log_2(0.01) IV(身份证号)=−100×(0.01×−6.64)IV(身份证号) = - 100 \times (0.01 \times -6.64) IV(身份证号)≈6.64IV(身份证号) \approx 6.64

『身份证号』的固有值高达 6.64。

对于**『性别』**这种正常特征,它的信息增益(Gain)被除以 1.0,影响不大,能够正常反映它对分类的帮助。

对于**『身份证号』这种看似能把数据分得很完美的毒瘤特征,虽然它的信息增益(Gain)算出来非常大,但在最后一步,它必须除以高达 6.64 的固有值(IV)**

4-3 信息增益率 Information Gain Ratio

既然知道了特征熵本质和信息熵没什么区别,只是计算的数据列不同一样。那么下面继续就蹦出来一个新的概念,那就是信息增益率。

它的计算公式就是,中文和英文如下。

信息增益率=信息增益分裂信息\text{信息增益率} = \frac{\text{信息增益}}{\text{分裂信息}} Gain Ratio=Information GainSplit InformationGain\ Ratio = \frac{Information\ Gain}{Split\ Information}

假设有 4 个周末,我们记录了天气和最终是否去游乐园的数据。

日期编号 (特征 A)天气 (特征 B)是否去游乐园 (标签 / 结果)
1晴天去
2晴天去
3雨天不去
4雨天不去

『特征熵』不看去不去游乐园,只看天气本身这列。

1️⃣天气把这 4 行数据分成了两半:2 个晴天(占 0.5),2 个雨天(占 0.5)。

IV(天气)=−(0.5log⁡2(0.5)+0.5log⁡2(0.5))=1IV(\text{天气}) = - \left( 0.5 \log_2(0.5) + 0.5 \log_2(0.5) \right) = 1

IV为 1。 这说明切法很老实,没切得太碎。最终得分(信息增益率)⬇️

信息增益率=信息增益特征熵=11=1\text{信息增益率} = \frac{\text{信息增益}}{\text{特征熵}} = \frac{1}{1} = 1

2️⃣编号把这 4 行数据分成了4个,各占1/4。

IV(编号)=−(0.25log⁡2(0.25)×4)IV(\text{编号}) = - \left( 0.25 \log_2(0.25) \times 4 \right) log⁡2(0.25)=−2\log_2(0.25) = -2 IV(编号)=−(0.25×−2×4)=2IV(\text{编号}) = - \left( 0.25 \times -2 \times 4 \right) = 2

IV高达 2! 裁判发现了端倪,这个特征把数据切得太碎了,必须重罚!最终得分(信息增益率)⬇️

信息增益率=信息增益特征熵=12=0.5\text{信息增益率} = \frac{\text{信息增益}}{\text{特征熵}} = \frac{1}{2} = 0.5

虽然『天气』和『编号』带来的信息增益都是 1。

但因为『编号』把数据切成了 4 份,它的IV比『天气』的特征熵大了一倍。

在最终除以IV之后,『天气』的综合得分就完爆了『编号』的综合得分。这就是 C4.5 算法利用『特征熵』成功防作弊的完美过程。

5 CART树

5-1 C4.5弊端

出现了新的树,那肯定是原来的树有问题。

  • 痛点一:对数运算的性能瓶颈(数学与算力的妥协)

在计算信息熵时,必须频繁使用对数运算log2. 在计算机科学底层,对数运算(尤其是涉及到大量浮点数时)是非常消耗 CPU 算力的。

Entropy=−∑pilog⁡2(pi)Entropy = -\sum p_i \log_2(p_i)
  • 痛点二:多叉树导致的数据碎片化

允许生成多叉树。假设有一个特征是『天气』,包含『晴、阴、雨、雪』四个值,C4.5 可能会直接在这个节点上劈出四个分支。

这听起来很合理,但会导致一个严重问题:数据被过快地切分了。树只要稍微深一点,底层的叶子节点可能就只剩下极少数的样本,极易导致过拟合(Overfitting)。

  • 痛点三:只能做分类

C4.5 诞生之初主要是为了解决分类问题(虽然也有变种处理连续值,但核心机制基于概率和熵)。如果目标变量是连续的数值(比如预测房价、预测你游泳 1000 米所需的时间),C4.5 就显得力不从心了。

这个时候新的树就出现了。那就是CART树。

CART树(Classification And Regression Tree)如名字一样,既可以做分类也可以搞回归。它每次只做二叉切分(binary split),一种通过『不断提问题,把数据一步一步切开』来做预测的树模型。

  • 分类(classification)
  • 回归(regression)

你可以把 CART 想成一个不断问问题的流程。比如判断一个人会不会买东西:

  1. 年龄 > 30 吗?
  2. 收入 > 1 万吗?
  3. 最近 7 天登录过吗?

每问一次,就把人群分成两边。最后分到某个叶子节点(leaf node)时,就给出结果 1️⃣会买 不会买 or 2️⃣预测消费金额是多少。这就是树模型的基本思想。

很多时候大家说『决策树』,常常默认就是 CART 风格的树。CART 有一个很重要的特点:每次只做二叉分裂(binary split)。也就是每次分成两边,不会一次分三边四边。这就是 CART 的典型风格。

  • age <= 30 走左边
  • age > 30 走右边

5-2 基尼指数 Gini impurity

CART用的是什么进行分类的呢?答案就是基尼指数

一个节点里,类别混得有多厉害。

  • 越纯,基尼越小
  • 越乱,基尼越大
节点类别分布Gini解释
10 正,0 负0.00完全纯
8 正,2 负0.32比较纯
5 正,5 负0.50很混乱

基尼指数和信息熵很像啊?你可以把它们当成两种不同的『混乱评分法』。就像两个老师都在给班级纪律打分

  • 老师 A 用一种标准
  • 老师 B 用另一种标准

虽然打分公式不同,但他们都在看这个班到底乱不乱,所以结论往往相似。 反正结论就是

  • 基尼指数和信息熵都在衡量节点纯度
  • 越纯越小,越乱越大
  • 基尼常见于 CART,信息熵常见于 ID3 / C4.5

计算公式

Gini=1−∑k=1Kpk2Gini = 1 - \sum_{k=1}^{K} p_k^2
  • K = 类别数
  • pk = 第 k 类在这个节点里的比例

下面是一个例子。比如下面全是数字1。最后计算结果是0,说明这个节点非常纯。

  • 1 类比例 = 1
  • 0 类比例 = 0
Gini=1−(12+02)=0Gini = 1 - (1^2 + 0^2) = 0

如果一个节点里一半 0,一半 1 说明比较乱。

Gini=1−(0.52+0.52)=1−(0.25+0.25)=0.5Gini = 1 - (0.5^2 + 0.5^2) = 1 - (0.25 + 0.25) = 0.5
  • Gini 越小,节点越纯
  • CART 会选那个能让切分后整体更纯的特征和阈值

一个生活化理解。想象你要把一堆苹果和橘子分两筐。

差的切法。⬇️那就很乱,不利于分类。

  • 一半苹果
  • 一半橘子

好的切法。⬇️ 那就很纯,分类效果好。基尼指数就是在量化这种『纯不纯』。

一筐几乎全是苹果,另一筐几乎全是橘子。

总结

其实我个人感觉就是3个树,和几个计算公式。

ID3。计算信息熵和信息增益。

信息熵 ➡️ 只看label结果

H(D)=−∑i=1cpilog⁡2(pi)H(D) = - \sum_{i=1}^{c} p_i \log_2(p_i)

信息增益 ➡️ 信息增益 = 信息熵 - 分类后的加权信息熵

分类后的加权信息熵 就是特征之后的label结果。加权就是乘以总数占比

Gain(D,a)=H(D)−∑v=1V∣Dv∣∣D∣H(Dv)Gain(D, a) = H(D) - \sum_{v=1}^{V} \frac{|D^v|}{|D|} H(D^v)

C4.5。计算信息增益率。

信息增益率

Gain_Ratio=GainSplitInfo=GainIVGain\_Ratio = \frac{Gain}{SplitInfo} = \frac{Gain}{IV}

分裂信息计算 ➡️ 本质就是信息熵,但是只看feature,跟结果无关。

SplitInfoA(D)=IV(A)=−∑v=1V∣Dv∣∣D∣log⁡2(∣Dv∣∣D∣)SplitInfo_A(D) = IV(A) = -\sum_{v=1}^{V} \frac{|D_v|}{|D|} \log_2 \left( \frac{|D_v|}{|D|} \right)

CART树。计算基尼指数

基尼指数

Gini=1−∑k=1Kpk2Gini = 1 - \sum_{k=1}^{K} p_k^2