文章目录
0. 前言
其实决策树的重点在于树的构建过程,一旦树完成了构建,剩下的就是类似于if else
精彩多选一的问题。
1.真正的决策树
在决策树中,一棵决策树包含一个根节点,若干个内部节点和若干个叶节点。假设数据集共有 n n n条数据: D = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x n , y n ) } D=\{(\boldsymbol{x_1}, y_1), (\boldsymbol{x_2}, y_2),..., (\boldsymbol{x_n}, y_n)\} D={(x1,y1),(x2,y2),...,(xn,yn)},其中 x i \boldsymbol{x_i} xi代表第 i i i条数据,是一个 d d d维的向量,每一个列向量相当于一个特征,一条数据中的所有特征记为 A = { a 1 , a 2 , . . . , a d } A=\{a_1, a_2, ..., a_d\} A={a1,a2,...,ad}。
那么,决策树的算法流程如下:
在《西瓜书》中提到,有三种情况会导致算法返回:
- 当前结点包含的样本全属于同一类别,无需划分。
- 当前属性集为空,或所有样本在所有属性上的取值相同,无法划分:把当前结点标记为叶节点,并将其类别设定为该结点所含样本最多的类别。
- 属性集为空的情况:假设有六个特征,六个特征全部用完发现,数据集中还是存在不同类别数据的情况。
- 当前特征值全都相同,在类别中有不同取值。
- 当前结点包含的样本集合为空,不能划分:将类别设定为父节点所含样本最多的类别。
出现这个情况的原因是:在生成决策树的过程中,数据按照特征不断的划分,很有可能在使用这个特征某一个值之前,已经可以判断包含该特征值的类别了。所以会出现空的情况。
2.划分选择
那么,在决策树中,怎么选择特征进行划分?以西瓜数据集为例。
2.1 ID3算法
2.1.1 信息熵
用于度量样本集合的纯度,代表一个系统中蕴含信息量的多少,熵越小,信息量越少,纯度越高,不确定性就越小。单位为:比特或者纳特。
假定当前样本集合
D
D
D中第
k
k
k类样本所占比例为
p
k
,
k
=
1
,
2
,
.
.
.
,
∣
Y
∣
p_k,k=1,2,...,|Y|
pk,k=1,2,...,∣Y∣,则
D
D
D的信息熵,计算公式为(在《统计学习方法》中,也用
H
(
D
)
H(D)
H(D)表示
E
n
t
(
D
)
Ent(D)
Ent(D)):
信息熵极值公式推导1
-
当样本 D D D中 ∣ y ∣ |y| ∣y∣类样本均匀分布时,信息熵最大,
E n t ( D ) = − ∑ k = 1 ∣ Y ∣ 1 ∣ y ∣ l o g 2 1 ∣ y ∣ = l o g 2 ∣ y ∣ Ent(D)=-\sum_{k=1}^{|Y|} \frac{1}{|y|}log_2\frac{1}{|y|}=log_2|y| Ent(D)=−k=1∑∣Y∣∣y∣1log2∣y∣1=log2∣y∣
-
当样本 D D D中的 ∣ y ∣ |y| ∣y∣只有一个值的时候,信息熵最小
E n t ( D ) = − ∑ k = 1 ∣ Y ∣ 1 ∣ y ∣ l o g 2 1 ∣ y ∣ = − 1 l o g 2 1 − 0 l o g 2 0 − . . . − 0 l o g 2 0 = 0 Ent(D)=-\sum_{k=1}^{|Y|} \frac{1}{|y|}log_2\frac{1}{|y|}=-1log_21-0log_20-...-0log_20 = 0 Ent(D)=−k=1∑∣Y∣∣y∣1log2∣y∣1=−1log21−0log20−...−0log20=0
E n t ( D ) = − ∑ k = 1 ∣ Y ∣ p k l o g 2 p k (2.1) Ent(D)=-\sum_{k=1}^{|Y|}p_klog_2p_k \tag{2.1} Ent(D)=−k=1∑∣Y∣pklog2pk(2.1)
西瓜数据集中,“好瓜”标签下只有“是”与“否”,因此 ∣ Y ∣ = 2 |Y|=2 ∣Y∣=2,是好瓜的有8个,不是好瓜的有9个,所以信息熵为
2.1.2 条件熵
两个随机变量
X
X
X、
Y
Y
Y可以形成联合熵
H
(
X
,
Y
)
H(X,Y)
H(X,Y),条件熵为:表示
(
X
,
Y
)
(X,Y)
(X,Y)发生所包含的熵,去掉
X
X
X单独发生的熵<=>在
X
X
X条件发生的条件下,
Y
Y
Y发生所产生的熵。
理解:
H
(
Y
∣
X
)
=
H
(
X
,
Y
)
−
H
(
X
)
=
−
∑
X
,
Y
p
(
X
,
Y
)
l
o
g
2
p
(
X
,
Y
)
−
−
∑
X
p
(
X
)
l
o
g
2
p
(
X
)
=
−
∑
X
,
Y
p
(
X
,
Y
)
l
o
g
2
p
(
X
,
Y
)
+
∑
X
(
∑
Y
p
(
X
,
Y
)
)
l
o
g
2
p
(
X
)
=
−
∑
X
,
Y
p
(
X
,
Y
)
l
o
g
2
p
(
X
,
Y
)
p
(
X
)
=
−
∑
X
,
Y
p
(
X
,
Y
)
l
o
g
2
p
(
Y
∣
X
)
(2.2)
\begin{aligned} H(Y|X) &= H(X,Y)-H(X)\\ &= -\sum_{X,Y}p(X,Y)log_2p(X,Y)--\sum_{X}p(X)log_2p(X)\\ &= -\sum_{X,Y}p(X,Y)log_2p(X,Y)+\sum_{X}(\sum_{Y}p(X,Y))log_2p(X)\\ &= -\sum_{X,Y}p(X,Y)log_2 \frac{p(X,Y)}{p(X)}\\ &= -\sum_{X,Y}p(X,Y)log_2 p(Y|X)\tag {2.2} \end{aligned}
H(Y∣X)=H(X,Y)−H(X)=−X,Y∑p(X,Y)log2p(X,Y)−−X∑p(X)log2p(X)=−X,Y∑p(X,Y)log2p(X,Y)+X∑(Y∑p(X,Y))log2p(X)=−X,Y∑p(X,Y)log2p(X)p(X,Y)=−X,Y∑p(X,Y)log2p(Y∣X)(2.2)
则,在色泽条件下|Y|的条件增益为: 6 17 ∗ 1 + 6 17 ∗ 0.918 + 5 17 ∗ 0.722 = 0.889 \frac{6}{17}*1+\frac{6}{17}*0.918+\frac{5}{17}*0.722=0.889 176∗1+176∗0.918+175∗0.722=0.889
2.1.3 信息增益
大白话:要想知道随机变量 Y Y Y的信息增益,就要“用 Y Y Y本身的信息熵” 减掉 “在已知 X X X情况下,随机变量 Y Y Y的信息熵”
含义:得知特征
X
X
X的信息而使得类
Y
Y
Y的信息不确定性减少的程度。
g
(
Y
,
X
)
=
H
(
Y
)
−
H
(
Y
∣
X
)
(2.3)
g(Y, X)=H(Y)-H(Y|X) \tag{2.3}
g(Y,X)=H(Y)−H(Y∣X)(2.3)
ID3算法就是选择信息增益最大的特征作为划分节点。
2.2 C4.5算法
2.2.1 信息增益率
因为信息增益可能会更偏向于数目较多的属性,因此,用一个数放缩了一下,具体公式如下:
G
a
i
n
_
r
a
t
i
o
(
D
,
a
)
=
G
r
a
i
n
(
D
,
a
)
I
V
(
a
)
(2.4)
Gain\_ratio(D, a)=\frac{Grain(D, a)}{IV(a)} \tag{2.4}
Gain_ratio(D,a)=IV(a)Grain(D,a)(2.4)
其中
I
V
(
a
)
=
−
∑
v
=
1
p
(
X
,
Y
)
l
o
g
2
p
(
X
,
Y
)
(2.5)
IV(a)=-\sum_{v=1}p(X,Y)log_2 p(X,Y)\tag{2.5}
IV(a)=−v=1∑p(X,Y)log2p(X,Y)(2.5)
一般来说,某特征可能的取值越多,说明IV(a)越大。 增益率对特征值较少的特征有一定偏好,因此 C4.5 算法选择特征的方法是先从候选特征中选出信息增益高于平均水平的特征,再从这些特征中选择增益率最高的。
C4.5算法就是选择信息增益率最大的特征作为划分节点。
2.3 CART算法
2.3.1基尼值
反映了数据集中随机抽取两个样本,其类别标记不一致的概率,因此,基尼值越小,数据集的纯度越高。
G
i
n
i
(
D
)
=
∑
k
=
1
∣
Y
∣
∑
k
≠
k
′
p
k
p
k
′
=
∑
k
=
1
∣
Y
∣
p
k
(
1
−
p
k
)
=
∑
k
=
1
∣
Y
∣
p
k
−
∑
k
=
1
∣
Y
∣
p
k
2
=
1
−
∑
k
=
1
∣
Y
∣
p
k
2
(2.6)
\begin{aligned} Gini(D) &= \sum_{k=1}^{|Y|}\sum_{k \neq k'}p_kp_{k'} \\ &=\sum_{k=1}^{|Y|}p_k(1-p_{k}) \\ &=\sum_{k=1}^{|Y|}p_k- \sum_{k=1}^{|Y|}p_k^2 \\ &=1-\sum_{k=1}^{|Y|}p_k^2 \tag{2.6} \end{aligned}
Gini(D)=k=1∑∣Y∣k=k′∑pkpk′=k=1∑∣Y∣pk(1−pk)=k=1∑∣Y∣pk−k=1∑∣Y∣pk2=1−k=1∑∣Y∣pk2(2.6)
2.3.2基尼系数
2.4 连续值的处理方式
- 若特征值是连续变量怎么处理?
3. 剪枝
通过剪枝,可以有效防止决策树模型过拟合的问题。主要有一下两种剪枝方法:
- 预剪枝
- 后剪枝
3.1 预剪枝
在决策树生成过程中,对每个节点先进行估计,若当前及诶单的划分不能使决策树的泛化性能提升,则停止划分。
采取的方法通常有:
- 数据划分法
采用多次交叉验证将数据分为训练集和测试集,树在训练集上生长,直到在测试集上的分类错误率达到最小时停止生长。 - 阈值法
预先设定一个阈值,当划分标准小于信息增益时停止生长,一般来说,阈值难以指定。 - 统计显著性分析
对已有节点获得的所有信息增益统计其分布,若继续生长得到的信息增益与该分布相比不显著,则停止树的生长,通常情况下,用卡方检验考察显著性。
3.2 后剪枝
对一个完整的决策树,从底向上对非叶子节点进行分析,若将该子树替换为叶子结点能够提升决策树的泛化能力,则将该子树替换为叶子节点。
采取的方法通常有:
- 数据划分法
采用多次交叉验证将数据分为训练集和测试集,树在训练集上生长,直到在测试集上的分类错误率达到最小时停止生长。 - 最小长度描述准则
首先对决策树进行编码,通过剪枝得到编码最短的决策树。
4. 代码
4.1 在所有数据集上未剪枝的决策树运行结果
西瓜书中有一处分类错误:
4.2 在训练集上未剪枝的运行结果
本文的运行结果与西瓜书不一致,原因在于在信息增益相同的情况下:(“脐部凹陷”处,gain(色泽)=gain(根蒂)),选取的划分特征不同。本文在“脐部凹陷”处选择的划分特征为根蒂,西瓜书选择的是“色泽”。
4.3 在训练集上使用“预剪枝”运行结果
5.小结
构建决策树过程中出现了以下问题:
- 在特征值划分部分
- python列表深复制和浅复制的问题。
- 《西瓜书》中在算法描述部分提到的“从A中去掉
a
∗
a_*
a∗”是指在子树中去掉,并不是整棵树中不再用,所以在最终树的“触感”特征出现了两次
- 之前第三种导致算法返回的情况一直没有遇到。原因是,在特征选择时用到的是
feature_values = list(dataset[classify_feature].unique())
而非
feature_values = self.unique_value[classify_feature]
导致无法获取到第三种返回的特征值。
6. 参考
《西瓜书》
《统计学习方法》
机器学习实战决策树plotTree函数完全解析
7. 脚注
已知集合D的信息熵为:
E n t ( D ) = − ∑ k = 1 ∣ y ∣ p k l o g 2 p k Ent(D)=-\sum_{k=1}^{|y|}p_klog_2p_k Ent(D)=−k=1∑∣y∣pklog2pk
可以理解为在 0 ≤ p k ≤ 1 0 \leq p_k \leq 1 0≤pk≤1和 ∑ k = 1 ∣ y ∣ \sum_{k=1}^{|y|} ∑k=1∣y∣的条件下 − ∑ k = 1 ∣ y ∣ p k l o g 2 p k -\sum_{k=1}^{|y|}p_klog_2p_k −∑k=1∣y∣pklog2pk的最大值/最小值的问题。由拉格朗日算子可设
L ( p 1 , p 2 , . . . , p n , λ ) = − ∑ k = 1 ∣ y ∣ p k l o g 2 p k + λ ( ∑ k = 1 ∣ y ∣ p k l o g 2 p k − 1 ) L(p_1,p_2,...,p_n,\lambda) = -\sum_{k=1}^{|y|}p_klog_2p_k + \lambda(\sum_{k=1}^{|y|}p_klog_2p_k-1) L(p1,p2,...,pn,λ)=−k=1∑∣y∣pklog2pk+λ(k=1∑∣y∣pklog2pk−1)
对 p 1 , . . . , p n , λ p_1,...,p_n,\lambda p1,...,pn,λ求导,可得
KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ \frac{\partial…
那么,对 p 2 . . . p n p_2...p_n p2...pn求导则有
KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ \lambda = log_…
又因 ∑ k = 1 ∣ y ∣ = 1 \sum_{k=1}^{|y|}=1 ∑k=1∣y∣=1,所以有 p 1 = p 2 = . . . = p n = 1 n p_1=p_2=...=p_n= \frac{1}{n} p1=p2=...=pn=n1 ↩︎