机器学习之决策树算法

摘自周志华老师的《机器学习》
一、整段代码理解
输入与输出
-
输入:
-
训练集 $D$:包含了 $m$ 个样本,每个样本有一组特征 $\boldsymbol{x}$(比如:颜色、大小、敲击声)和一个确定的标签 $y$(比如:是好瓜、不是好瓜)。
-
属性集 $A$:也就是特征的集合,包含了 $d$ 个可用于划分数据的属性(比如 $a_1=$颜色,$a_2=$根蒂等)。
-
-
输出:一棵以
node为根节点的决策树。
2. 核心过程 (TreeGenerate 递归函数)
第 1 步:创建节点 (Line 1)
-
每次调用这个函数,首先都会生成一个新的节点
node。这个节点接下来要么变成带有最终判断结果的“叶节点”,要么变成继续向下分叉的“内部节点”。
第 2 步:判断是否满足停止条件一(纯度最高)(Lines 2-4)
-
逻辑:如果当前数据集 $D$ 里的所有样本都属于同一个类别 $C$(比如全是“好瓜”)。
-
操作:那就不需要再分了!直接把当前节点标记为类别 $C$ 的叶节点,然后返回。
第 3 步:判断是否满足停止条件二(属性用完 或 样本特征完全一样)(Lines 5-7)
-
逻辑:如果属性集 $A$ 为空(已经没有特征可以用来分类了),或者 $D$ 中所有样本在当前剩下所有属性上的取值都完全一样(特征长得一模一样,但类别可能不同,无法区分)。
-
操作:把当前节点标记为叶节点。既然无法继续分,就采用少数服从多数的原则,把它标记为当前数据集 $D$ 中样本数最多的那个类别。
第 4 步:选择最优划分属性 (Line 8)
-
逻辑:如果上面两个停止条件都没满足,说明还能继续分。此时要从当前的属性集 $A$ 中,挑选出一个“最好”的属性 $a_*$ 来作为分类的标准。(注:这里的“最优”通常是通过信息增益、增益率或基尼指数等指标计算出来的)。
第 5 步:根据最优属性进行分支并递归 (Lines 9-16)
-
选定最优属性 $a_*$ 后,假设这个属性有几个不同的取值(比如“颜色”有“青绿”、“乌黑”、“浅白”三个值),就用一个
for循环为每个取值 $a_*^v$ 拉出一条分支(Line 9-10):-
划分数据:把 $D$ 中在属性 $a_*$ 上取值为 $a_*^v$ 的样本挑出来,组成一个新的子集 $D_v$。
-
停止条件三(处理空集)(Lines 11-12):如果挑出来的子集 $D_v$ 是空的(比如训练集里刚好没有“浅白”颜色的瓜)。这时候要把这个分支也变成叶节点,类别标记为父节点数据集 $D$ 中最多的类。这其实是一种处理未见样本的“先验”防范机制。
-
继续递归 (Lines 13-15):如果 $D_v$ 不为空,就把这个子集 $D_v$ 和剩下的属性集 $A \setminus \{a_*\}$(注意:用过的特征通常就不再用了)作为新的输入,递归调用
TreeGenerate函数,生成下一层的子树。
-
在学习这段伪代码时,最容易混淆也是考试最爱考的地方是三种导致递归返回(生成叶节点)的情形及其背后的逻辑:
-
节点纯了(Line 2):样本全是一类,无需再分。
-
没法分了(Line 5):属性用光了,或者样本特征长得完全一样。此时类别设为当前节点的多数类。
-
分支没数据了(Line 11):某个特征取值下没有样本。此时类别设为父节点的多数类。
二、第三种return变成叶节点的解释
我们先设定一个场景(例子)
假设我们在构建决策树的某个中间节点。在这个节点上,我们手里还有10个西瓜的数据(这就是代码里的数据子集 $D$)。
这10个西瓜中:8个是好瓜,2个是坏瓜。所以,如果在这个节点停下来,多数类是**“好瓜”**。
现在,我们选定了一个属性来划分这些瓜(代码里的 $a_*$):西瓜的纹理。
纹理这个属性在我们的“常识数据库”里有三个可能的取值(就像颜色有青绿、乌黑、浅白一样):
-
清晰
-
稍糊
-
模糊
然而,巧合的是,在这节点剩余的10个西瓜里,没有任何一个西瓜的纹理是“模糊”的。它们要么是清晰的,要么是稍糊的。
下面是根据你提供的算法流程,发生的故事:
请看下面这张图,它展示了第9-16步的循环过程:
图解说明:
如图所示,我们在父节点(最上面那个框)有10个瓜。我们决定用“纹理”来分家。
-
左边分支(纹理=清晰):我们挑出了6个瓜。这里有数据,所以我们按照算法第14步,继续递归(在这6个瓜里再选新属性来分),生成下一层的树。
-
中间分支(纹理=稍糊):我们挑出了4个瓜。同样有数据,继续递归。
-
右边分支(纹理=模糊):这就是问题的关键! 在父节点的10个瓜里,我们想挑出纹理是模糊的瓜,结果发现个数是0。
为什么会出现空集 $D_v$ ?
是因为我们在进行数据划分(Line 10)时,当前节点的数据子集里,恰好没有这个属性取值的样本。
怎么处理这个空集(Lines 11-12)?
-
不能不管:虽然训练数据里没有“模糊”纹理的瓜,但我们在将来预测新西瓜时,万一遇到了一个纹理模糊的瓜呢?如果没有这个分支,决策树就不知道怎么判断了。所以,我们必须给这个取值硬造一个“叶节点”。
-
不能递归:因为 $D_{模糊}$ 是空的(没瓜),我们没办法在0个瓜里再去统计信息增益、选新属性、进行下一次递归调用。
-
借用智慧(父节点的多数类):既然这个分支自己没有数据,它就失去了判断能力。此时,它决定向上一级(父节点)求助。
-
这个分支会说:“我这里没样本,我不知道纹理模糊的瓜是好是坏。但我知道,在分出我之前,我的父节点里大部分(8/10)都是好瓜。”
-
于是,这个空的“纹理=模糊”分支就被强制标记为叶节点,类别设定为父节点 $D$ 的多数类——好瓜。图中的虚线箭头清晰地展示了这种类别标记的传递过程。
-
总结:什么是“处理未见样本的先验防范机制”?
这是一种兜底策略(Fallback strategy)。
它的逻辑是:如果在这个分支下,我们的训练集(经验)是一片空白,那我们就保守一点,认为在这个特定条件下,西瓜的品质更有可能接近我们在上一步看到的整体情况。这就像如果某种新类型的西瓜你没见过,你最合理的猜测就是它跟大多数已知的西瓜一样(在父节点层面是好瓜)。
这确保了我们的决策树对所有可能的特征取值组合都有一个预定义的判断路径,避免了遇到新情况时的卡顿。
更多推荐
所有评论(0)