【初中生讲机器学习】13. 决策树算法一万字详解!一篇带你看懂!

创建时间:2024-03-02
最后编辑时间:2024-03-02
作者:Geeker_LStar

你好呀~这里是 Geeker_LStar 的人工智能学习专栏,很高兴遇见你~
我是 Geeker_LStar,一名初三学生,热爱计算机和数学,我们一起加油~!
⭐(●’◡’●) ⭐ 那就让我们开始吧!

emmm,本来打算接着之前的内容把线性回归算法的实现写一下的,但是开学了在学校大部分时间都只能看理论 errrr,so 花了两天啃完了决策树算法,这篇启动!
(决策树不难,至少数学原理不难,不像 SVM(((bushi)

文章目录

  • 简介 & 工作流程
  • 数学原理
    • ID3 决策树
    • C4.5 决策树
    • CART 决策树
  • 剪枝操作
    • 预剪枝
    • 后剪枝
  • 连续值与缺失值处理
    • 连续值
    • 缺失值

简介 & 工作流程

决策树,一个并不难的经典算法,属于监督学习。它仿照人类在判断一个东西的类别时的(一种)思维路径——先判断这个东西是否有 A 特征,若有,再判断是否有 B 特征,以此类推,直到这些特征足够判断这个东西的类别。比如西瓜书上那个经典的例子,我们要把一堆西瓜分成好瓜和坏瓜,此时我们的思维是有路径的,我们可能会先看这个西瓜的色泽如何,如果色泽是青绿色的,再敲一敲它听一下声音;如果色泽不是青绿色的,又进行其它操作…以此类推,直到我们能通过这些特征判断出这个瓜是好的还是坏的

well,先简单复习一下树这种数据结构——它有一个根节点、若干内部节点和若干叶节点,每一个叶节点都对应一个分类结果(不同叶节点对应的分类结果可以重复,相当于不同的判断路径)。决策树要干的事就是寻找一些合理的从根节点到叶节点的路径,完成分类(当然,也可以回归,不过决策树更多还是用在分类上)。

那么,决策树什么时候会到达叶节点呢? 通常有以下三种情况:
(1)当前节点包含的样本全部属于同一类别,即这条分类路径已经很成功了,不用继续分类了。此时会把该节点设为叶节点,叶节点的类别就是这些样本的类别
(2)所有的属性(如上面 “西瓜问题” 中提到的色泽、敲声)都已经用于划分了,没有其它属性可以再继续划分这个节点所包含的样本了;或者,此时把该节点设为叶节点,类别为这些样本中出现次数最多的类别(即后验概率最大的类别)。
(3)用某个属性划分后,没有符合要求的样本,即当前节点包含的样本集合为空。此时把该节点设为叶节点,类别为它的父节点包含的样本中出现次数最多的类别(即先验概率最大的类别)。

知道了以上三种情况,决策树的伪代码就好写了,其实是个递归:

# 训练集:
D = ((x_1, y_1), (x_2, y_2), ..., (x_n, y_n)),其中 $x_i = (x_{i1}, x_{i2}, ... , x_{id})
# 属性集
A = {a_1, a_2, ..., a_n}函数 TreeGenerate (D, A) 如下:
# 生成父节点
生成结点 node;
# 情况 1
if D 中样本全属于同一类别 C then将 node 标记为 C 类叶节点 ; return
end if
# 情况 2
if A =or D 中样本在 A 上取值相同 then将 node 标记为叶节点,其类别标记为 D 中样本数最多的类 ; return
end if
# 否则(递归)
从 A 中选择最优划分属性 a*    # 选择的具体方法在下文
for a* 中的每一个值 do为 node 生成一个分支;把相应的样本放入合适的分支中,用 D_v 表示在 a* 中取值为 a*_v 的样本子集 ;# 情况 3if D_v 为空 then将分支节点标记为叶节点,其类别标记为 D 中样本最多的类 ; returnelse# 递归产生新的子树以 TreeGenerate(D_v, A \ a*) 为分支节点end if
end for

嗯~~!这样应该很清晰啦!至于那个 “最优划分属性” 到底怎么选,往下看!

ok,讲完基本流程,我们把本篇要用的数据集例子放在这~(yes 西瓜书,嘿嘿):

编号色泽根蒂敲声纹理脐部触感好瓜
1青绿蜷缩浊响清晰凹陷硬滑
2乌黑蜷缩沉闷清晰凹陷硬滑
3乌黑蜷缩浊响清晰凹陷硬滑
4青绿蜷缩沉闷清晰凹陷硬滑
5浅白蜷缩浊响清晰凹陷硬滑
6青绿稍蜷浊响清晰稍凹软粘
7乌黑稍蜷浊响稍糊稍凹软粘
8乌黑稍蜷浊响清晰稍凹硬滑
9乌黑稍蜷沉闷稍糊稍凹硬滑
10青绿硬挺清脆清晰平坦软粘
11浅白硬挺清脆模糊平坦硬滑
12浅白蜷缩浊响模糊平坦软粘
13青绿稍蜷浊响稍糊凹陷硬滑
14浅白稍蜷沉闷稍糊凹陷硬滑
15乌黑稍蜷浊响清晰稍凹软粘
16浅白蜷缩浊响模糊平坦硬滑
17青绿蜷缩沉闷稍糊稍凹硬滑

数学原理

决策树算法有三种主要的实现方式——ID3 决策树(基于信息增益)、C4.5 决策树(基于增益率)、CART 决策树(基于基尼指数),每种实现方式的数学原理都不一样,来看看~

ID3 决策树

ID3 决策树基于信息增益。它是最早提出的决策树算法,最简单,不支持剪枝操作,不提供连续值和缺失值处理。不过,它的基本思想被后来的两个决策树算法沿用,so 先从它开始吧!

要想理解信息增益,我们得先来看看信息熵(information entropy)是什么。
“熵” 这个概念你肯定不陌生,在物理/化学中,它表示一个系统的混乱程度,熵越大,说明整个体系越无序;熵越小,说明整个体系越有序。
在决策树中也一样,假设我们有一堆样本 D = ( ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x n , y n ) ) D=((x_1, y_1), (x_2, y_2), ..., (x_n, y_n)) D=((x1,y1),(x2,y2),...,(xn,yn)),其中 x i = ( x i 1 , x i 2 , . . . , x i d ) x_i = (x_{i1}, x_{i2}, ... , x_{id}) xi=(xi1,xi2,...,xid) y i y_i yi 表示该样本的分类。“熵” 表示这个数据集的混乱程度,直观理解就是这个数据集中的数据属于不同分类的程度。这 n 个数据属于 n 个分类肯定比这 n 个数据属于 2 个分类的混乱程度高。

ok,说的简单,那我们怎么精确地度量一个数据集的混乱程度呢?信息熵的数学公式如下:
E n t ( D ) = − ∑ k = 1 ∣ Y ∣ p k log ⁡ 2 p k Ent(D)=-\sum_{k=1}^{|Y|}p_k \log_2p_k Ent(D)=k=1Ypklog2pk其中, ∣ Y ∣ |Y| Y 表示标记空间(或输出空间),简单理解就是不同的分类结果,引用西瓜书上的例子,“对一堆西瓜分类” 的标记空间就是 “好瓜、坏瓜”。 p k p_k pk 表示样本被分到第 k 类的概率,也就是第 k 类样本在数据集 D 中的占比。大多数情况下, p k < 1 p_k<1 pk<1,所以 log ⁡ 2 p k \log_2 p_k log2pk 是个负数,so 我们需要在式子最前面加一个负号把结果变成正数。

不难发现, E n t ( D ) Ent(D) Ent(D) 的值越小,说明这组样本的 “混乱程度” 越低,即更多的样本都是同一类,数据集的 “纯度” 更高
准确来说,当 p 1 = p 2 = . . . = p ∣ Y ∣ = 1 ∣ Y ∣ p_1 = p_2 = ... = p_{|Y|} = \frac{1}{|Y|} p1=p2=...=pY=Y1 的时候,即每个类别的样本在数据集中占比相同时, E n t ( D ) Ent(D) Ent(D) 有最大值 log ⁡ 2 ∣ Y ∣ \log_2|Y| log2Y,对应数据集纯度最低。而当 p k ( k = 1 , 2 , . . . , ∣ Y ∣ ) p_k (k = 1, 2, ..., |Y|) pk(k=1,2,...,Y) 中有一个为 1,其它为 0,即数据集中全是某一类样本的时候, E n t ( D ) Ent(D) Ent(D) 有最小值 0,对应数据集的纯度最高
至于以上两种情况的证明,不在此展开,简单来说就是凸优化问题,让它的拉格朗日函数的一阶偏导等于 0 就 ok。

举个例子,用最开始的数据集算一下信息熵:共 17 个数据,正例(好瓜)8 个,反例 9 个,则信息熵为:
E n t ( D ) = − ∑ k = 1 ∣ Y ∣ p k log ⁡ 2 p k = − ( 8 17 log ⁡ 2 8 17 + 9 17 log ⁡ 2 9 17 ) = 0.998 Ent(D)=-\sum_{k=1}^{|Y|}p_k \log_2p_k = -(\frac{8}{17} \log_2\frac{8}{17}+\frac{9}{17} \log_2\frac{9}{17})=0.998 Ent(D)=k=1Ypklog2pk=(178log2178+179log2179)=0.998

好~现在我们知道信息熵是什么了,根据前面说的决策树的工作流程,我们现在得找一个最优划分属性。即,用这个属性划分原数据集之后,分支数据集的纯度要尽可能高,也就是分支数据集的信息熵要尽可能小。

这事好办,原始数据集的信息熵是一个定值,我们想让划分后(每一个)分支数据集的信息熵(都)尽可能小,不妨转换个思路,让 “原始信息熵减去分支信息熵的和” 的结果最大。给这个结果一个名字——信息增益。简言之,信息增益越大,这次划分对数据集的 “纯度提升” 就越大。
换言之,最优划分属性,就是信息增益最大的属性。

先把信息增益的数学表达式放在这里,后面会用一个例子来过一遍完整的计算。
G a i n ( D , a ) = E n t ( D ) − ∑ v = 1 V ∣ D v ∣ ∣ D ∣ E n t ( D v ) Gain(D,a) =Ent(D)-\sum^{V}_{v=1}\frac{|D^v|}{|D|}Ent(D^v) Gain(D,a)=Ent(D)v=1VDDvEnt(Dv)其实很好理解,a 是我们选择的划分属性,V 是这个划分属性一共有几种可能的情况,减号前面的式子就是原始数据集的信息熵,后面就是把划分后的每个分支数据集的信息熵加起来,两个相减,就是信息增益。
这里说一下为什么有 ∣ D v ∣ ∣ D ∣ \frac{|D^v|}{|D|} DDv 这一项。可以把它简单理解为权重,毕竟样本数越多的分支数据集对信息增益的影响(理应)越大,如果不加这一项,那不管分支数据集有 1 个数据还是有 100 个数据,对信息增益的影响程度都一样,这可就不合适了。

前面说过,所谓最优划分属性就是让信息增益最大的属性,用最开始的那个西瓜数据集,我们可以选择的特征有 { 色泽、根蒂、敲声、纹理、脐部、触感 } \{色泽、根蒂、敲声、纹理、脐部、触感\} {色泽、根蒂、敲声、纹理、脐部、触感},现在来算一下这些属性的信息增益,以第一项 “色泽” 为例

“色泽” 属性有三个可能的取值,划分成三个分支数据集就是: D 1 ( 色泽 = 青绿 ) , D 2 ( 色泽 = 乌黑 ) , D 3 ( 色泽 = 浅白 ) D^1(色泽=青绿), \ D^2(色泽=乌黑), \ D^3(色泽=浅白) D1(色泽=青绿), D2(色泽=乌黑), D3(色泽=浅白).
其中 D 1 D^1 D1 包含 6 个样例,属于正例(好瓜)的有 3 个,属于反例(坏瓜)的也有 3 个,信息熵为 E n t ( D ) = − ∑ k = 1 ∣ Y ∣ p k log ⁡ 2 p k = − ( 3 6 log ⁡ 2 3 6 + 3 6 log ⁡ 2 3 6 ) = 1 Ent(D)=-\sum_{k=1}^{|Y|}p_k \log_2p_k = -(\frac{3}{6} \log_2\frac{3}{6}+\frac{3}{6} \log_2\frac{3}{6})=1 Ent(D)=k=1Ypklog2pk=(63log263+63log263)=1
同理, D 2 D^2 D2 D 3 D^3 D3 的信息熵分别为 0.918 和 0.722。
再用信息增益的公式:
( D , 色泽 ) = E n t ( D ) − ∑ v = 1 V ∣ D v ∣ ∣ D ∣ E n t ( D v ) = E n t ( D ) − ∑ v = 1 3 ∣ D v ∣ ∣ D ∣ E n t ( D v ) = 0.998 − ( 6 17 × 1.000 + 6 17 × 0.918 + 5 17 × 0.722 ) = 0.109 \begin{align*} & (D,色泽) =Ent(D)-\sum^{V}_{v=1}\frac{|D^v|}{|D|}Ent(D^v) \\ & =Ent(D)-\sum^{3}_{v=1}\frac{|D^v|}{|D|}Ent(D^v) \\ & =0.998-(\frac{6}{17}×1.000+\frac{6}{17}×0.918+\frac{5}{17}×0.722) \\ &= 0.109 \end{align*} (D,色泽)=Ent(D)v=1VDDvEnt(Dv)=Ent(D)v=13DDvEnt(Dv)=0.998(176×1.000+176×0.918+175×0.722)=0.109计算出,使用属性 ”色泽“ 进行划分,信息增益是 0.109。

类似地,对所有属性进行计算后,发现属性 “纹理” 的信息增益最大,于是我们用它作为划分属性。
ok!这样第一轮划分就完成了,按照这个套路,继续对每个分支数据集进行划分即可~
注意,对于划分好的三个分支数据集,进一步划分它们的时候,每个分支数据集之间是彼此独立的,也就是说,可以用不同的划分属性去划分它们三个。

这样一步步划分的结果如下图(from 🍉书):

ID3

emmm 没错,你应该也感觉到了,这玩意明显过拟合了,不过现在先不管这个,后面会讲怎么解决。

代码会在下一篇文章里集中给出,这一篇先把原理讲完~~

C4.5 决策树

嗯,其实有了 ID3 决策树的各种铺垫,C4.5 和 CART 理解起来会超级简单,因为基本思想是一样的,只不过参考指标的计算方式变了。

怎么说,C4.5 是对 ID3 的改进。其中两点是 C4.5 支持剪枝、支持连续值和缺失值,不过这不是这部分的重点。
先举个例子,我如果在上面的划分属性中加一个 “编号”(共 17 个可取值),那这事可就好办了,直接用编号进行划分,划分之后每个分支数据集里就 1 个数据,信息增益高达 0.998,也就是说划分之后信息熵之和直接变成 0 了。这貌似很强,可是这样的决策树没有任何泛化能力。
这是个极端的例子,但是它反映了 ID 3 算法的不足之处——可取值数量多了,每一个取值下的数据就少了,纯度自然就提高了,那划分后的信息熵之和必然就减小了,信息增益肯定会提高

也就是说,ID3 算法在选择最优划分属性的时候,会倾向于选择 “可取值数量多” 的属性。这会导致什么?yesyes,如果一个属性的可取值数量过多(比如上面举例的 “编号”),很容易就导致过拟合。。。so 我们得避免这种情况。

一个简单的思路是,既然信息增益会在属性可取值数量多的时候偏大,那就让信息增益除以另一个值,并且让这个值也在属性可取值多的时候偏大即可。类似于归一化。

这个 “除以的值” 的数学表达式如下:
I V ( a ) = ∑ v = 1 V ∣ D v ∣ ∣ D ∣ log ⁡ 2 ∣ D v ∣ ∣ D ∣ IV(a) = \sum^V_{v=1}\frac{|D^v|}{|D|}\log_2\frac{|D^v|}{|D|} IV(a)=v=1VDDvlog2DDv其中,a 即划分属性,这个值被称作属性 a 的固有值
你可能会感觉,诶这个式子的形式怎么如此熟悉…好像,就是信息熵那个式子的形式?
yesyes,恭喜你,感觉的很对,这个式子其实就是在计算信息熵呀!它计算的是某个划分属性自身的信息熵。代换一下,V 是这个属性的可取值数量,类似于信息熵中的标记空间; ∣ D v ∣ ∣ D ∣ \frac{|D^v|}{|D|} DDv 是样本在 a 属性上的值等于该属性某个可取值的概率,类似于信息熵中的 p k p_k pk。所以其实,这个公式可以理解为属性本身的信息熵,即不确定性。

如果一个属性的可取值越多,这个属性自身的 “混乱度”(不确定性)就越高,它的固有值(信息熵)也会相应的大,所以用固有值作为分母,还挺不错!
这么一来,C4.5 算法选择最优划分属性的公式如下,我们把它称作增益率

G a i n _ r a d i o ( D , a ) = G a i n ( D , a ) I V ( a ) = E n t ( D ) − ∑ v = 1 V ∣ D v ∣ ∣ D ∣ E n t ( D v ) ∑ v = 1 V ∣ D v ∣ ∣ D ∣ log ⁡ 2 ∣ D v ∣ ∣ D ∣ \begin{align*} & Gain\_radio(D,a) =\frac{Gain(D,a)}{IV(a)} \\ &=\frac{Ent(D)-\sum^{V}_{v=1}\frac{|D^v|}{|D|}Ent(D^v)}{\sum^V_{v=1}\frac{|D^v|}{|D|}\log_2\frac{|D^v|}{|D|}} \end{align*} Gain_radio(D,a)=IV(a)Gain(D,a)=v=1VDDvlog2DDvEnt(D)v=1VDDvEnt(Dv)

emmm,不过 C4.5 其实也有 bug。因为从数学角度来看,信息增益和增益率都不是线性变化的(有 log 的参与),所以不论是信息增益还是增益率,其二阶导数必定不为 0(或一阶导必定不为常数),这说明它们的变化率(一阶导)不是均匀变化的,即因变量会在自变量值较大的时候变化较快或在自变量值较小的时候变化较快,这就决定了它们必然会偏向样本较多的属性样本较少的属性(看二阶导是正还是负了)。

C4.5 和 ID3 相反,它会偏向可取值数量较少的属性。所以 C4.5 算法并不是直接选择增益率最大的属性作为划分属性,而是用了一个折中的方法先在所有属性中选出信息增益较大的一半,再从这一半属性中选择增益率最高的属性。 这是一种相对平衡的方法。

一样,代码会在下一篇给出~

CART 决策树

CART,英文全称 classification and regression tree,是三种决策树中性能最强的。从名字就能看出,它既可以用于分类,也可以用于回归。sklearn 中默认的决策树算法就是 CART。

CART 决策树使用基尼指数作为选择属性的指标。这个指标比前两个好理解一些。
直观来看,我在一堆样本中随机抽取两个,抽取 10 次,如果这 10 次中有 8 次我抽到的两个样本都是同类,那我可以大胆推测,这个数据集还蛮 “整齐” 的,纯度挺高的。但是如果我这 10 次每次抽到的两个样本都不同类,那我肯定觉得,这数据集也太混乱了。

没错,基尼指数的基本逻辑就是上面那段,它衡量的是:从一个数据集中随机抽取两个样本,它们的类别标记不一致的概率。 基尼指数越小,说明数据集的纯度越高。

式子很简单,“两个样本类别不一致的概率” 等于 1 减去 “两个样本类别一致的概率”:
G i n i ( D ) = 1 − ∑ k = 1 ∣ Y ∣ p k 2 Gini(D) = 1-\sum^{|Y|}_{k=1}p_k^2 Gini(D)=1k=1Ypk2这就是原始数据集 D 的基尼指数。

再来计算每个属性的基尼指数,形式和之前信息熵那里保持统一:
G i n i _ i n d e x ( D , a ) = ∑ v = 1 V ∣ D v ∣ ∣ D ∣ G i n i ( D v ) Gini\_index(D,a) = \sum^{V}_{v=1}\frac{|D^v|}{|D|}Gini(D^v) Gini_index(D,a)=v=1VDDvGini(Dv)我们选择基尼指数最小的属性作为最优划分属性。

但是嘛…这种方法说来简单,在实际中却没办法应用,因为 CART 是一棵二叉树,它不像 ID3 那样可以同时生成多个分支。
不过关于 CART 的详细做法,我打算放到下一篇(二分类算法推广到多分类的一些方法)中再说,这里先说这么多~

OK!!以上就是三种决策树算法的数学原理~!其实并不难。

放一个各项对比图:

对比

接下来我们开始解决过拟合问题…

剪枝操作

well,任何一个机器学习算法都不可避免地会遇到过拟合问题,决策树也一样。
对于决策树,过拟合的主要原因是它的分支过多,就比如我有 n 个样本,我如果用 “编号” 进行分类,那每个分支就一个样本,这样肯定最后的信息熵最低,看似是 “最优” 的划分方式,可是这个决策树完全不具有泛化能力
所以,为了减少过拟合,我们需要对决策树进行 “剪枝”——如果用某一个条件进行划分不能使决策树的性能提升(甚至反而下降),那么就不必用这个条件进行划分了,这个 “树枝” 就可以被剪掉了,这就是剪枝操作的基本思想

注意,“性能是否提升” 是需要验证集进行验证的,所以我们把最开始的数据集分成两部分,一部分作为训练集,另一部分作为验证集。(emm 的确这个数据集很小,但是作为示例够用了)

训练集:

编号色泽根蒂敲声纹理脐部触感好瓜
1青绿蜷缩浊响清晰凹陷硬滑
2乌黑蜷缩沉闷清晰凹陷硬滑
3乌黑蜷缩浊响清晰凹陷硬滑
6青绿稍蜷浊响清晰稍凹软粘
7乌黑稍蜷浊响稍糊稍凹软粘
10青绿硬挺清脆清晰平坦软粘
14浅白稍蜷沉闷稍糊凹陷硬滑
15乌黑稍蜷浊响清晰稍凹软粘
16浅白蜷缩浊响模糊平坦硬滑
17青绿蜷缩沉闷稍糊稍凹硬滑

验证集:

编号色泽根蒂敲声纹理脐部触感好瓜
4青绿蜷缩沉闷清晰凹陷硬滑
8乌黑稍蜷浊响清晰稍凹硬滑
9乌黑稍蜷沉闷稍糊稍凹硬滑
11浅白硬挺清脆模糊平坦硬滑
12浅白蜷缩浊响模糊平坦软粘
13青绿稍蜷浊响稍糊凹陷硬滑

先来看一下如果不进行剪枝,基于训练集最终生成的决策树是什么样的:

未剪枝决策树

常用的剪枝操作有两种——预剪枝和后剪枝,其实现过程和优劣势略有不同。
我们用上面的训练集来训练决策树,选择信息增益准则。

预剪枝

顾名思义,预剪枝就是在生成一棵完整的决策树之前就把没必要的树枝剪掉,也就是一些树枝根本就不会被生成

根据信息增益准则,(如果要划分的话)对于训练集而言最优划分属性是 “脐部”。
但是,是否有必要进行这个划分呢?请记住决策树的剪枝准则(在剪枝部分最开始也有说过):如果用该属性进行划分能够提高决策树在验证集上的准确率,就划分,否则就不划分(即 “剪枝”)。

在基本流程中我们提到,如果在当前节点处不进行划分,那么当前节点将被标记为叶子节点,类别为在当前节点的所有样本中出现最多的类别
也就是说,如果在根节点这里不用 “脐部” 属性进行划分,那直接把根节点标记为叶子节点,类别为在训练集中出现次数最多的类别,也就是 “好瓜”。换言之,这棵决策树会把验证集中所有数据都分类为好瓜。
well,不进行划分的情况下,验证集 7 个样本全部被判定为好瓜,但实际上好瓜只有 3 个,准确率为 42.9%。

再来看看进行划分的情况。我们先只用 “脐部” 属性划分一次,然后不再进行第二次划分,把节点类别标记为被分到节点那一类的数据中出现最多的类别

划分一次

okkk,大概就是这样,划分后在验证集上的准确率达到了 71.4%,大于不划分的情况(42.9%),于是,我们选择用 “脐部” 进行划分。

第一次划分完成,然后呢?还要继续划分吗?
没错,重复上述套路就 ok 了,④ 节点已经没有必要继续划分了(类别一致),对于 ②③ 节点,通过计算发现,划分后决策树在验证集上的准确率都下降了,于是不再划分,最终的决策树如上图所示(这种只有一层的决策树也被称为 “决策树桩”)。

对比一下预剪枝决策树和未剪枝决策树:

对比1

可以看出,预剪枝决策树的很多分支都没有展开。这在一方面减少了过拟合风险,降低了决策树训练的各种开销;但是从另一方面看,这同时增加了欠拟合的风险(嗯至少我觉得预剪枝决策树明显是欠拟合的),因为有些划分可能并不能直接提高决策树的准确率(甚至会导致准确率下降),但在其基础上的划分却能让决策树的准确率提升。但是预剪枝相当于直接否定了这种可能,造成欠拟合的风险。

后剪枝

很明显,后剪枝和预剪枝相对,它会在一棵完整的决策树生成完毕后,自底向上地计算哪些树枝是没必要的,再把它们去掉。

简单来说,后剪枝的过程就是:从一个叶子节点出发,看看如果把这个叶子节点的父节点作为叶子节点(相当于剪掉叶子节点这一层的分支),决策树的准确率是否提高,如果提高了,就剪掉这一层分支,否则就不剪。
特别地,如果是否剪枝对决策树的准确率没有影响,那可剪可不剪。

因为流程已经在预剪枝那里讲过一遍了,这里不用再展开说,放一张最终决策树的图即可。

后剪枝

不难发现,后剪枝比预剪枝保留了更多分支,因此它的欠拟合风险很小泛化性能往往优于预剪枝和未剪枝决策树。但同时,后剪枝需要先训练一棵完整的决策树,再自底向上对每一个分支进行考察,这导致后剪枝的各种开销在属性数量较多且数据量较大时都远大于预剪枝和未剪枝。

连续值与缺失值处理

well,在现实情况中,我们很难收集到非常完整的(指没有属性缺失的)数据集,也很难保证一个数据集中所有的属性都是连续的 or 都是离散的。如果遇到这两种情况,原始的决策树算法就不那么好用了,我们需要做一些特殊处理

连续值

显然,面对连续值,我们肯定不可能把每一个值单独分为一类。这就需要用到连续属性离散化技术了,在决策树算法中,最常用的是二分法,简单来说就是选出一个临界值,大于这个临界值的连续属性被分为一类,小于这个临界值的被分为另一类。

比如现在我们有一个数据集 D 和一个连续属性 a,a 在 D 上有 n 个不同的取值,把这些取值从小到大排序,即 { a 1 , a 2 , . . . , a n } \{a^1, a^2, ..., a^n\} {a1,a2,...,an},那么肯定存在一个临界值 t ( a 1 < t < a n ) t \ ( a^1 < t < a^n) t (a1<t<an) 能够通过属性 a 把数据集 D 划分为两部分,即 “在属性 a 上的取值大于 t 的部分” 和 “在属性 a 上的取值不大于 t 的部分”,记为 D t + D^+_t Dt+ D t − D^-_t Dt

怎么找这个临界值 t 呢?不难发现,对于相邻的属性取值 a i a^i ai a i + 1 a^{i+1} ai+1 来说,这个 t 取区间 [ a i , a i + 1 ) [a^i, a^{i+1}) [ai,ai+1) 里任意一个值的划分效果都是一样的,so 我们不妨就取中间值作为一个可能的临界值。
即,二分法的核心就是:对于每两个相邻的属性取值,都取中间值作为一个可能的临界值,这些中间值组成一个 “可能临界值” 的集合,再通过一些标准选出最合适的临界值。
由这些中间值组成的集合可表示为:
T a = { a i + a i + 1 2 , 1 ≤ i ≤ n − 1 } T_a = \{\frac{a^i+a^{i+1}}{2},1≤i≤n-1\} Ta={2ai+ai+1,1in1}那么,临界值怎么选呢?这就和选取最优划分属性一样了。因为选临界值的目的也是分类,那就用三种评价标准中的一个,比如信息增益,选出 “可能临界值” 集合中信息增益最大的那个值,作为最终的临界(划分)值 t。

不过,和离散值不同的是,连续值可以反复作为最优划分属性,只不过每次选择的临界值可能不一样。换言之,比如一棵决策树已经用 “属性 <= 7.25” 划分过一次了,但也可以在此基础上再用 “属性 >= 2.18” 继续划分。

连续值的处理比较简单,这里就不再举例子了。

缺失值

well,缺失值是很常见的,通常指样本在某个或某几个属性上的值有空缺
如果有缺失值的样本很少,总样本量又比较大,那直接丢掉这些有缺失值的样本也可以,但是通常情况下事情不会这么简单,所以在遇到缺失值的时候,我们需要一些应对方案。

我们面临的问题主要有两个:
(1)如何在某些属性有缺失值的情况下选择最优划分属性
(2)选好最优划分属性后,如果某样本在这个属性上的值缺失,怎么划分这个样本?

先来解决第一个问题。很显然,我们只能通过在该属性上没有缺失值的样本来判断这个属性是否能作为最优划分属性(依然采用信息增益作为标准)。

还是一样,给定数据集 D D D 和属性 a a a,作以下规定:

  • D D D 中的数据共有 ∣ Y ∣ |Y| Y 个分类
  • D ~ \tilde{D} D~ 表示数据集 D D D 中在属性 a a a 上没有缺失值的样本子集
  • 属性 a a a V V V 个可取值 { a 1 , a 2 , . . . , a v } \{a^1, a^2, ... , a^v\} {a1,a2,...,av}
  • D v ~ \tilde{D^v} Dv~ 表示 D ~ \tilde{D} D~ 中在属性 a a a 上取值为 a v a^v av 的样本子集
  • D k ~ \tilde{D_k} Dk~ 表示 D ~ \tilde{D} D~ 中属于第 k , ( k = 1 , 2 , . . . , ∣ Y ∣ ) k, (k=1, 2, ..., |Y|) k,(k=1,2,...,Y) 类的样本子集
  • D D D 中的每个样本的初始权重 w x = 1 w_x=1 wx=1

ok,有了这些,我们来计算一些式子
Ⅰ. 对于属性 a a a,在属性 a a a 上无缺失值的样本占总样本的比例:
ρ = ∑ x ∈ D ~ w x ∑ x ∈ D w x ρ = \frac{\sum_{x\in\tilde{D} \ w_x}}{\sum_{x\in D \ w_x}} ρ=xD wxxD~ wx

Ⅱ. 在属性 a a a 上无缺失值的样本中,属于第 k k k 类样本所占比例:
p k = ∑ x ∈ D k ~ w x ∑ x ∈ D ~ w x , k = 1 , 2 , . . . , ∣ Y ∣ p_k = \frac{\sum_{x\in\tilde{D_k} w_x}}{\sum_{x\in\tilde{D} \ w_x}}, k=1, 2, ..., |Y| pk=xD~ wxxDk~wx,k=1,2,...,Y

Ⅲ. 在属性 a a a 上无缺失值的样本中,在属性 a a a 上取值为 a v a^v av 的样本所占比例:
r v ~ = ∑ x ∈ D v ~ w x ∑ x ∈ D ~ w x \tilde{r_v} = \frac{\sum_{x\in\tilde{D^v} \ w_x}}{\sum_{x\in \tilde{D} \ w_x}} rv~=xD~ wxxDv~ wx

计算这些是为了把信息增益的计算式推广到有缺失值的场景。
再回顾一下信息增益的原始表达式:
G a i n ( D , a ) = E n t ( D ) − ∑ v = 1 V ∣ D v ∣ ∣ D ∣ E n t ( D v ) Gain(D,a) =Ent(D)-\sum^{V}_{v=1}\frac{|D^v|}{|D|}Ent(D^v) Gain(D,a)=Ent(D)v=1VDDvEnt(Dv)

把新计算出的数值代换进去,新的信息增益算式为:
G a i n ( D , a ) = ρ × G a i n ( D ~ , a ) = ρ × ( E n t ( D ~ ) − ∑ v = 1 V r v ~ E n t ( D v ~ ) ) Gain(D, a) = ρ × Gain(\tilde{D}, a) \\ = ρ × (Ent(\tilde{D})-\sum^{V}_{v=1}\tilde{r_v}Ent(\tilde{D^v})) Gain(D,a)=ρ×Gain(D~,a)=ρ×(Ent(D~)v=1Vrv~Ent(Dv~))其中: E n t ( D ~ ) = − ∑ k = 1 ∣ Y ∣ p k log ⁡ 2 p k Ent(\tilde{D}) = -\sum_{k=1}^{|Y|}p_k\log_2p_k Ent(D~)=k=1Ypklog2pk

其实就相当于把 D ~ \tilde D D~ 当成了新的数据集,所有的计算方式都和原算式一样。至于为什么要乘 ρ ρ ρ,可以这么理解: ρ ρ ρ 类似置信度或权重,因为对于一个属性,肯定是缺失的值越少,参考价值越高, × ρ ×ρ ×ρ 相当于同时兼顾了纯度提升和可信度(参考价值)

ok 终于把公式讲完了(对这是这一篇最后一个公式)。

emmmm,我们好像还有个问题(2)是吧,问题(2)比(1)好解决——之前不是说,给每一个样本在最初都赋予了 1 的权重嘛,这个权重这时候就有用了:我们不知道这个有缺失值的样本到底怎么分,那就同时把它分到所有分支中,它在新分支中的权重就等于这个分支的先验概率(也就是被分到这个分支的样本在总样本中的占比)。当然,其它有明确分类的样本的权重不变,还是 1。

C4.5 算法对缺失值的处理方式就如上两个问题的答案所说。

举个例子,我们现在有这样一个数据集:

编号色泽根蒂敲声纹理脐部触感好瓜
1蜷缩浊响清晰凹陷硬滑
2乌黑蜷缩沉闷清晰凹陷
3乌黑蜷缩清晰凹陷硬滑
4青绿蜷缩沉闷清晰凹陷硬滑
5蜷缩浊响清晰凹陷硬滑
6青绿稍蜷浊响清晰软粘
7乌黑稍蜷浊响稍糊稍凹软粘
8乌黑稍蜷浊响稍凹硬滑
9乌黑稍蜷沉闷稍糊稍凹硬滑
10青绿硬挺清脆平坦软粘
11浅白硬挺清脆模糊平坦
12浅白蜷缩模糊平坦软粘
13稍蜷浊响稍糊凹陷硬滑
14浅白稍蜷沉闷稍糊凹陷硬滑
15乌黑稍蜷浊响清晰软粘
16浅白蜷缩浊响模糊平坦硬滑
17青绿沉闷稍糊稍凹硬滑

以属性 “色泽” 为例,17 个样本中共有 14 个样本在该属性上没有缺失值,则这 14 个样本的信息熵为: − ( 6 14 log ⁡ 2 6 14 + 8 14 log ⁡ 2 8 14 ) = 0.985 -(\frac{6}{14} \log_2\frac{6}{14}+\frac{8}{14} \log_2\frac{8}{14})=0.985 (146log2146+148log2148)=0.985
同样,我们也可以计算出三个分支数据集的信息熵分别为 1.000、0.918、0。

ok,样本子集 D ~ \tilde{D} D~ 上属性 “色泽” 的信息增益就是:
0.998 − ( 4 14 × 1.000 + 6 14 × 0.918 + 4 14 × 0.000 ) = 0.306 0.998-(\frac{4}{14}×1.000+\frac{6}{14}×0.918+\frac{4}{14}×0.000) = 0.306 0.998(144×1.000+146×0.918+144×0.000)=0.306

那么样本集 D D D 上的信息增益就是 14 17 × 0.306 = 0.252 \frac{14}{17}×0.306 = 0.252 1714×0.306=0.252.

类似的,我们计算出属性 “纹理” 的信息增益最大,为 0.424,于是我们选择它作为最优划分属性
重复上述过程,直到决策树构建完成。

最终结果如下:

划分结果

ok!!!以上就是决策树算法的原理,学完这些大概用了几节自习课吧,写这篇又写了好几个小时,代码之后发~!


好嘞,这篇就到这里!感谢~!

这篇文章详解决策树算法,写了好几个小时,希望对你有所帮助!⭐
欢迎三连!!一起加油!🎇
——Geeker_LStar

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/504878.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电子电器架构 —— DoIP协议相关的介绍

电子电器架构 —— DoIP协议相关的介绍 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值,你不能站在他人的角度来反对自己。人生在世,最怕…

Excel 按奇数偶数列处理数据

目录 一. 需求背景1.1 获取偶数列的数据1.2 奇偶列数据互换 二. 解决方式2.1 为列添加奇偶辅助列2.2 通过公式将奇偶列互换 一. 需求背景 1.1 获取偶数列的数据 ⏹ 最近在整理歌单&#xff0c;发现部分歌曲没有歌词&#xff0c;于是打算自己制作一份。 从网上找到了歌词&…

【Spring IoC】实验四:特殊值处理

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

Topaz Gigapixel AI:让每一张照片都焕发新生mac/win版

Topaz Gigapixel AI 是一款革命性的图像增强软件&#xff0c;它利用先进的人工智能技术&#xff0c;能够显著提升图像的分辨率和质量。无论是摄影爱好者还是专业摄影师&#xff0c;这款软件都能帮助他们将模糊的、低分辨率的照片转化为清晰、细腻的高分辨率图像。 Topaz Gigap…

《Spring Security 简易速速上手小册》第9章 测试与维护 (2024 最新版)

文章目录 9.1 编写安全测试9.1.1 基础知识9.1.2 重点案例&#xff1a;保护 REST API9.1.3 拓展案例 1&#xff1a;自定义登录逻辑测试9.1.4 拓展案例 2&#xff1a;CSRF 保护测试 9.2 Spring Security 升级和维护9.2.1 基础知识9.2.2 重点案例&#xff1a;适配新的密码存储格式…

监控与日志

一、监控 1、监控类型 从监控类型上划分&#xff0c;在 K8s 中可以分成四个不同的类型&#xff1a; ① 资源监控&#xff1a;这种监控主要关注于基础资源的使用情况&#xff0c;例如 CPU、内存、网络等。通常使用数值或百分比等单位来统计&#xff0c;可以通过 Zabbix、Tele…

vue3项目中如何一个vue组件中的一个div里面的图片铺满整个屏幕样式如何设置

在Vue 3项目中&#xff0c;要使一个div内的图片铺满整个屏幕&#xff0c;你需要确保几个关键点&#xff1a;div元素和图片元素的样式设置正确&#xff0c;以及确保它们能够覆盖整个视口&#xff08;viewport&#xff09;。以下是一个简单的步骤和代码示例&#xff0c;帮助你实现…

水电表远程集中抄表管理系统

水电表远程集中抄表管理系统是当前水电行业智能化发展的关键技术之一&#xff0c;为水电企业和用户提供了便捷、高效的抄表管理解决方案。该系统结合了远程监控、自动抄表、数据分析等多种功能&#xff0c;实现了水电抄表的智能化和精准化&#xff0c;为用户节省了大量人力物力…

效率真高!众安保险数据分析岗(实习)面试通过了,分享一下面试经验!

最近&#xff0c;我们社群组织了一场技术&面试讨论会&#xff0c;邀请了一些互联网大厂同学、参加社招和校招面试的同学&#xff0c;针对新手如何入门数据分析、机器学习算法、该如何备战、面试常考点分享等热门话题进行了深入的讨论。 基于社群的讨论&#xff0c;今天我整…

Maven高级(黑马学习笔记)

Maven 是一款构建和管理 Java 项目的工具。 分模块设计与开发 介绍 所谓分模块设计&#xff0c;顾名思义指的就是我们在设计一个 Java 项目的时候&#xff0c;将一个 Java 项目拆分成多个模块进行开发。 1). 未分模块设计的问题 如果项目不分模块&#xff0c;也就意味着所有…

selenium爬虫

方法选择和安装包 在动态网页并且登陆过程中不需要进行过于复杂的密码验证的时候使用selenium会非常的方便 安装准备过程也相对简单&#xff1a; 下载对应版本的chromedriver并且通过如下代码找到路径下载到python所在的目录&#xff1a; import sysprint(sys.executable) …

xsslabs第四关

测试 "onclick"alert(1) 这与第三关的代码是一样的&#xff0c;但是每一关考的点是不一样的所以我们看一下源代码 <!DOCTYPE html><!--STATUS OK--><html> <head> <meta http-equiv"content-type" content"text/html;ch…