机器学习求索之路(3)— 决策树
@(Machine Learning)
文章目录
1. 信息论基础
- 熵
- 熵度量了事物的不确定性,越不确定的事物,它的熵就越大。具体的,随机变量X的熵的表达式如下:
H ( X ) = − ∑ i = 1 n p i l o g p i H(X) = -\sum\limits_{i=1}^{n}p_i logp_i H(X)=−i=1∑npilogpi
其中 n n n代表 X X X的 n n n种不同的离散取值。而 p i p_i pi代表了 X X X取值为 i i i的概率, l o g log log为以2或者 e e e为底的对数。 - 从一个变量
X
X
X的熵,很容易推广到多个个变量的联合熵,这里给出两个变量
X
X
X和
Y
Y
Y的联合熵表达式:
H ( X , Y ) = − ∑ i = 1 n p ( x i , y i ) l o g p ( x i , y i ) H(X,Y) = -\sum\limits_{i=1}^{n}p(x_i,y_i)logp(x_i,y_i) H(X,Y)=−i=1∑np(xi,yi)logp(xi,yi) - 有了联合熵,又可以得到条件熵的表达式
H
(
X
∣
Y
)
H(X|Y)
H(X∣Y),条件熵类似于条件概率,它度量了我们的
X
X
X在知道
Y
Y
Y以后剩下的不确定性。表达式如下:
H ( X ∣ Y ) = − ∑ i = 1 n p ( x i , y i ) l o g p ( x i ∣ y i ) = ∑ j = 1 n p ( y j ) H ( X ∣ y j ) H(X|Y) = -\sum\limits_{i=1}^{n}p(x_i,y_i)logp(x_i|y_i) = \sum\limits_{j=1}^{n}p(y_j)H(X|y_j) H(X∣Y)=−i=1∑np(xi,yi)logp(xi∣yi)=j=1∑np(yj)H(X∣yj)
- 熵度量了事物的不确定性,越不确定的事物,它的熵就越大。具体的,随机变量X的熵的表达式如下:
- 信息增益
上述提到 H ( X ) H(X) H(X)度量了 X X X的不确定性,条件熵 H ( X ∣ Y ) H(X|Y) H(X∣Y)度量了我们在知道 Y Y Y以后 X X X剩下的不确定性,那么 H ( X ) − H ( X ∣ Y ) H(X)-H(X|Y) H(X)−H(X∣Y)则为度量了 X X X在知道 Y Y Y以后不确定性减少程度,这个度量我们在信息论中称为互信息,记为 I ( X , Y ) = H ( X ) − H ( X ∣ Y ) I(X,Y)=H(X)-H(X|Y) I(X,Y)=H(X)−H(X∣Y)。
在决策树ID3算法中叫做信息增益。ID3算法就是用信息增益来判断当前节点应该用什么特征来构建决策树。信息增益大,则越适合用来分类。 - 基尼不纯度
将来自集合的某种结果随机应用于某一数据项的预期误差率。
I G ( f ) = ∑ i = 1 m f i ( 1 − f i ) = ∑ i = 1 m f i − ∑ i = 1 m f i 2 = 1 − ∑ i = 1 m f i 2 I_G(f)=\sum_{i=1}^mf_i(1-f_i)=\sum_{i=1}^mf_i-\sum_{i=1}^mf_i^2=1-\sum_{i=1}^mf_i^2 IG(f)=i=1∑mfi(1−fi)=i=1∑mfi−i=1∑mfi2=1−i=1∑mfi2- 显然基尼不纯度越小,纯度越高,集合的有序程度越高,分类的效果越好;
- 基尼不纯度为 0 时,表示集合类别一致;
- 基尼不纯度最高(纯度最低)时,
f
1
=
f
2
=
…
=
f
m
=
1
m
f_1=f_2=\ldots =f_m=\frac1m
f1=f2=…=fm=m1
I G ( f ) = 1 − ( 1 m ) 2 × m = 1 − 1 m I_G(f)=1-(\frac1m)^2\times m=1-\frac1m IG(f)=1−(m1)2×m=1−m1
2. ID3
ID3算法就是用信息增益大小来判断当前节点应该用什么特征来构建决策树,用计算出的信息增益最大的特征来建立决策树的当前节点。由上节可知信息增益的公式为:
I
(
X
,
Y
)
=
H
(
X
)
−
H
(
X
∣
Y
)
I(X,Y)=H(X)-H(X|Y)
I(X,Y)=H(X)−H(X∣Y)
2.1. 算法过程
1)初始化信息增益的阈值
ϵ
\epsilon
ϵ
2)判断样本是否为同一类输出
D
i
D_i
Di,如果是则返回单节点树T。标记类别为
D
i
D_i
Di
3) 判断特征是否为空,如果是则返回单节点树T,标记类别为样本中输出类别D实例数最多的类别。
4)计算A中的各个特征(一共n个)对输出D的信息增益,选择信息增益最大的特征
A
g
A_g
Ag
5) 如果
A
g
A_g
Ag的信息增益小于阈值
ϵ
\epsilon
ϵ,则返回单节点树T,标记类别为样本中输出类别D实例数最多的类别。
6)否则,按特征
A
g
A_g
Ag的不同取值
A
g
i
A_{gi}
Agi将对应的样本输出D分成不同的类别
D
i
D_i
Di。每个类别产生一个子节点。对应特征值为
A
g
i
A_{gi}
Agi。返回增加了节点的数T。
7)对于所有的子节点,令
D
=
D
i
,
A
=
A
−
{
A
g
}
D=D_i, A= A-\{A_g\}
D=Di,A=A−{Ag}递归调用2-6步,得到子树
T
i
T_i
Ti并返回。
2.2. 停止分裂的条件
决策树不可能不限制地生长,总有停止分裂的时候,最极端的情况是当节点分裂到只剩下一个数据点时自动结束分裂,但这种情况下树过于复杂,而且预测的经度不高。一般情况下为了降低决策树复杂度和提高预测的经度,会适当提前终止节点的分裂。
以下是决策树节点停止分裂的一般性条件:
- 最小节点数
当节点的数据量小于一个指定的数量时,不继续分裂。两个原因:一是数据量较少时,再做分裂容易强化噪声数据的作用;二是降低树生长的复杂性。提前结束分裂一定程度上有利于降低过拟合的影响。 - 熵或者基尼值小于阀值。
由上述可知,熵和基尼值的大小表示数据的复杂程度,当熵或者基尼值过小时,表示数据的纯度比较大,如果熵或者基尼值小于一定程度数,节点停止分裂。 - 决策树的深度达到指定的条件
节点的深度可以理解为节点与决策树跟节点的距离,如根节点的子节点的深度为1,因为这些节点与跟节点的距离为1,子节点的深度要比父节点的深度大1。决策树的深度是所有叶子节点的最大深度,当深度到达指定的上限大小时,停止分裂。 - 所有特征已经使用完毕,不能继续进行分裂。
被动式停止分裂的条件,当已经没有可分的属性时,直接将当前节点设置为叶子节点
2.3. ID3算法的不足
ID3算法虽然提出了新思路,但是还是有很多值得改进的地方。
- ID3无法处理连续特征,比如长度,密度都是连续值。
- ID3采用信息增益大的特征优先建立决策树的节点。但在相同条件下,取值比较多的特征比取值少的特征信息增益大。
- ID3算法对于缺失值的情况没有做考虑
- 没有考虑过拟合的问题
3. C4.5
C4.5算法是用于生成决策树的一种经典算法,是ID3算法的一种延伸和优化。C4.5算法对ID3算法主要做了一下几点改进:
(1)通过信息增益率选择分裂属性,克服了ID3算法中通过信息增益倾向于选择拥有多个属性值的属性作为分裂属性的不足;
(2)能够处理离散型和连续型的属性类型,即将连续型的属性进行离散化处理;
(3)构造决策树之后进行剪枝操作;
(4)能够处理具有缺失属性值的训练数据。
对于第二个问题,信息增益作为标准容易偏向于取值较多的特征的问题。引入一个信息增益比的变量
I
R
(
X
,
Y
)
I_R(X,Y)
IR(X,Y),它是信息增益和特征熵的比值。表达式如下:
I
R
(
D
,
A
)
=
I
(
A
,
D
)
H
A
(
D
)
I_R(D,A) = \frac{I(A,D)}{H_A(D)}
IR(D,A)=HA(D)I(A,D)
其中D为样本特征输出的集合,A为样本特征,对于特征熵
H
A
(
D
)
H_A(D)
HA(D),表达式如下:
H
A
(
D
)
=
−
∑
i
=
1
n
∣
D
i
∣
∣
D
∣
l
o
g
2
∣
D
i
∣
∣
D
∣
H_A(D) = -\sum\limits_{i=1}^{n}\frac{|D_i|}{|D|}log_2\frac{|D_i|}{|D|}
HA(D)=−i=1∑n∣D∣∣Di∣log2∣D∣∣Di∣
其中n为特征A的类别数,
D
i
D_i
Di为特征A的第i个取值对应的样本个数。D为样本个数。
特征数越多的特征对应的特征熵越大,它作为分母,可以校正信息增益容易偏向于取值较多的特征的问题。
对于过拟合问题C4.5引入了正则化系数进行初步的剪枝。除了上面的几点,C4.5和ID3的思路区别不大。
C4.5不足之处:
(1) 由于决策树算法非常容易过拟合,因此对于生成的决策树必须要进行剪枝。剪枝的思路主要是两种,一种是预剪枝,即在生成决策树的时候就决定是否剪枝。另一个是后剪枝,即先生成决策树,再通过交叉验证来剪枝。
(2) C4.5生成的是多叉树,即一个父节点可以有多个节点。采用二叉树,可以提高效率。
(3) C4.5只能用于分类。
(4) C4.5由于使用了熵模型,里面有大量的耗时的对数运算和排序运算。
4. CART树
CART分类树算法使用基尼系数来代替信息增益比,基尼系数代表了模型的不纯度,基尼系数越小,则不纯度越低,特征越好。这和信息增益(比)是相反的。
4.1 CART分类树——待预测结果为离散型数据
在分类问题中,假设有
K
K
K类,样本点属于第
k
k
k类的概率为
p
k
p_k
pk,则概率分布的基尼指数定义为:
G
i
n
i
(
p
)
=
∑
k
=
1
K
p
k
(
1
−
p
k
)
=
(
p
1
+
p
2
+
.
.
.
+
p
K
)
−
∑
k
=
1
K
p
k
2
=
1
−
∑
k
=
1
K
p
k
2
Gini( p) = \sum_{k=1}^Kp_k(1-p_k)=(p_1+p_2+...+p_K)-\sum_{k=1}^Kp_k^2=1-\sum_{k=1}^Kp_k^2
Gini(p)=k=1∑Kpk(1−pk)=(p1+p2+...+pK)−k=1∑Kpk2=1−k=1∑Kpk2
对于分类问题:设
C
k
C_k
Ck为D中属于第
k
k
k类的样本子集,则基尼指数为:
G
i
n
i
(
D
)
=
1
−
∑
k
=
1
K
(
∣
C
k
∣
∣
D
∣
)
2
Gini(D)=1-\sum_{k=1}^K(\frac{|C_k|}{|D|})^2
Gini(D)=1−k=1∑K(∣D∣∣Ck∣)2
设条件A将样本D切分为
D
1
D_1
D1和
D
2
D_2
D2两个数据子集,则在条件A下的样本D的基尼指数为:
G
i
n
i
(
D
,
A
)
=
∣
D
1
∣
∣
D
∣
G
i
n
i
(
D
1
)
+
∣
D
2
∣
∣
D
∣
G
i
n
i
(
D
2
)
Gini(D,A) = \frac{|D_1|}{|D|}Gini(D_1) + \frac{|D_2|}{|D|}Gini(D_2)
Gini(D,A)=∣D∣∣D1∣Gini(D1)+∣D∣∣D2∣Gini(D2)
基尼指数也表示样本的不确定性,基尼指数值越大,样本集合的不确定性越大。
算法实现步骤:
1)计算现有样本D的基尼指数,之后利用样本中每一个特征A,及A的每一个可能取值
a
a
a,根据
A
>
=
a
A>=a
A>=a与
A
<
a
A<a
A<a将样本分为两部分,并计算
G
i
n
i
(
D
,
A
)
Gini(D,A)
Gini(D,A)值
2)找出对应基尼指数最小
G
i
n
i
(
D
,
A
)
Gini(D,A)
Gini(D,A)的最优切分特征及取值,并判断是否切分停止条件,否,则输出最优切分点
3)递归调用1)2)
4)生成CART决策树
4.2. CART回归树——待预测结果为连续型数据
回归树以误差平方和为准则选择最优二分切点,该生成算法在训练数据集上所在的输入空间中,递归的将每个区域划分为两个子区域并决定每个子区域的输出值,在这里分为两种情况,一是输出值为子区域输出值的均值该种情况下为回归树,二是输出值为子区域输入与输出的线性回归,输出值为回归系数,该种情况下为模型树。
算法实现步骤:
1)选择最优切分特征J与切分点s,按照如下原则:
m
i
n
j
,
s
[
m
i
n
c
1
∑
(
y
i
−
c
1
)
+
m
i
n
c
2
∑
(
y
i
−
c
2
)
]
min_{j,s}[min_{c_1}\sum(y_i-c_1)+min_{c_2}\sum(y_i-c_2)]
minj,s[minc1∑(yi−c1)+minc2∑(yi−c2)]
c
1
,
c
2
c1,c2
c1,c2分别为左右子区域输出的均值(模型树时是输出变量的回归值),可通过遍历每个变量的每个可能取值来切分数据集找出最优切分点。
2)用切分点划分区域并决定相应的输出值
3)递归调用1)2)直到满足停止条件
4)利用字典,递归调用创建二叉树,生成决策树
4.3. 树剪枝
CART回归树和CART分类树的剪枝策略除了在度量损失的时候一个使用均方差,一个使用基尼系数。
由于决策时算法很容易对训练集过拟合,而导致泛化能力差,为了解决这个问题,我们需要对CART树进行剪枝,即类似于线性回归的正则化,来增加决策树的泛化能力。CART采用的办法是后剪枝法,即先生成决策树,然后产生所有可能的剪枝后的CART树,然后使用交叉验证来检验各种剪枝的效果,选择泛化能力最好的剪枝策略。
也就是说,CART树的剪枝算法可以概括为两步,第一步是从原始决策树生成各种剪枝效果的决策树,第二部是用交叉验证来检验剪枝后的预测能力,选择泛化预测能力最好的剪枝后的数作为最终的CART树。
首先剪枝的损失函数度量,在剪枝的过程中,对于任意的一刻子树T, 其损失函数为:
C
α
(
T
t
)
=
C
(
T
t
)
+
α
∣
T
t
∣
C_{\alpha}(T_t) = C(T_t) + \alpha |T_t|
Cα(Tt)=C(Tt)+α∣Tt∣
其中,
α
\alpha
α为正则化参数,这和线性回归的正则化一样。
C
(
T
t
)
C(T_t)
C(Tt)为训练数据的预测误差,分类树是用基尼系数度量,回归树是均方差度量。
∣
T
t
∣
|T_t|
∣Tt∣是子树T的叶子节点的数量。
当
α
=
0
\alpha = 0
α=0时,即没有正则化,原始的生成的CART树即为最优子树。当
α
=
∞
\alpha = \infty
α=∞时,即正则化强度达到最大,此时由原始的生成的CART树的根节点组成的单节点树为最优子树。当然,这是两种极端情况。一般来说,
α
\alpha
α越大,则剪枝剪的越厉害,生成的最优子树相比原生决策树就越偏小。对于固定的
α
\alpha
α,一定存在使损失函数
C
α
(
T
)
C_{\alpha}(T)
Cα(T)最小的唯一子树。
剪枝的思路如下,对于位于节点t的任意一颗子树
T
t
T_t
Tt,如果没有剪枝,它的损失是
C
α
(
T
t
)
=
C
(
T
t
)
+
α
∣
T
t
∣
C_{\alpha}(T_t) = C(T_t) + \alpha |T_t|
Cα(Tt)=C(Tt)+α∣Tt∣
如果将其剪掉,仅仅保留根节点,则损失是
C
α
(
T
)
=
C
(
T
)
+
α
C_{\alpha}(T) = C(T) + \alpha
Cα(T)=C(T)+α
当
α
=
0
\alpha = 0
α=0或者$\alpha
很
小
时
,
很小时,
很小时,C_{\alpha}(T_t) <C_{\alpha}(T)$ , 当
α
\alpha
α增大到一定的程度时
C
α
(
T
t
)
=
C
α
(
T
)
C_{\alpha}(T_t) = C_{\alpha}(T)
Cα(Tt)=Cα(T)。当
α
\alpha
α继续增大时不等式反向,也就是说,如果满足下式:
α
=
C
(
T
)
−
C
(
T
t
)
∣
T
t
∣
−
1
\alpha = \frac{C(T)-C(T_t)}{|T_t|-1}
α=∣Tt∣−1C(T)−C(Tt)
T
t
T_t
Tt和
T
T
T有相同的损失函数,但是
T
T
T节点更少,因此可以对子树
T
t
T_t
Tt进行剪枝,也就是将它的子节点全部剪掉,变为一个叶子节点
T
T
T。
最后CART树的交叉验证策略。上面讲到可以计算出每个子树是否剪枝的阈值 α \alpha α,如果把所有的节点是否剪枝的值 α \alpha α都计算出来,然后分别针对不同的 α \alpha α所对应的剪枝后的最优子树做交叉验证。这样就可以选择一个最好的 α \alpha α,有了这个 α \alpha α,就可以用对应的最优子树作为最终结果。
CART树的剪枝算法:
输入:CART树建立算法得到的原始决策树
T
T
T。
输出:最优决策子树
T
α
T_\alpha
Tα。
算法过程如下:
1)初始化
α
m
i
n
=
∞
\alpha_{min}= \infty
αmin=∞, 最优子树集合
ω
=
{
T
}
\omega=\{T\}
ω={T}。
2)从叶子节点开始自下而上计算各内部节点t的训练误差损失函数
C
α
(
T
t
)
C_{\alpha}(T_t)
Cα(Tt)(回归树为均方差,分类树为基尼系数), 叶子节点数
∣
T
t
∣
|T_t|
∣Tt∣,以及正则化阈值
α
=
m
i
n
{
C
(
T
)
−
C
(
T
t
)
∣
T
t
∣
−
1
,
α
m
i
n
}
\alpha= min\{\frac{C(T)-C(T_t)}{|T_t|-1}, \alpha_{min}\}
α=min{∣Tt∣−1C(T)−C(Tt),αmin}, 更新
α
m
i
n
=
α
\alpha_{min}= \alpha
αmin=α
3) 得到所有节点的
α
\alpha
α值的集合M。
4)从M中选择最大的值
α
k
\alpha_k
αk,自上而下的访问子树t的内部节点,如果
C
(
T
)
−
C
(
T
t
)
∣
T
t
∣
−
1
≤
α
k
\frac{C(T)-C(T_t)}{|T_t|-1} \leq \alpha_k
∣Tt∣−1C(T)−C(Tt)≤αk时,进行剪枝。并决定叶节点t的值。如果是分类树,则是概率最高的类别,如果是回归树,则是所有样本输出的均值。这样得到
α
k
\alpha_k
αk对应的最优子树
T
k
T_k
Tk
5)最优子树集合
ω
=
ω
∪
T
k
\omega=\omega \cup T_k
ω=ω∪Tk,
M
=
M
−
{
α
k
}
M= M -\{\alpha_k\}
M=M−{αk}。
6) 如果M不为空,则回到步骤4。否则就已经得到了所有的可选最优子树集合
ω
\omega
ω.
7) 采用交叉验证在
ω
\omega
ω选择最优子树
T
α
T_\alpha
Tα
5. Python调用及参数
from sklearn.datasets import load_iris
from sklearn import tree
iris = load_iris()
clf = tree.DecisionTreeClassifier()
clf = clf.fit(iris.data, iris.target)
clf.predict(test_data)
参数解释
- 特征选择标准criterion:
- 分类树-可以使用"gini"或者"entropy",前者代表基尼系数,后者代表信息增益。一般说使用默认的基尼系数"gini"就可以了,即CART算法。
- 回归树可以使用"mse"或者"mae",前者是均方差,后者是和均值之差的绝对值之和。推荐使用默认的"mse"。
- 特征划分点选择标准splitter:可以使用"best"或者"random"。前者在特征的所有划分点中找出最优的划分点。后者是随机的在部分划分点中找局部最优的划分点。默认的"best"适合样本量不大的时候,而如果样本数据量非常大,此时决策树构建推荐"random"
- 划分时考虑的最大特征数max_features:可以使用很多种类型的值,默认是"None",意味着划分时考虑所有的特征数;如果是"log2"意味着划分时最多考虑log2N个特征;如果是"sqrt"或者"auto"意味着划分时最多考虑N−−√个特征。如果是整数,代表考虑的特征绝对数。如果是浮点数,代表考虑特征百分比,即考虑(百分比xN)取整后的特征数。其中N为样本总特征数。如果样本特征数不多,比如小于50,我们用默认的"None"就可以了,如果特征数非常多,我们可以灵活使用刚才描述的其他取值来控制划分时考虑的最大特征数,以控制决策树的生成时间。
- 决策树最大深max_depth:决策树的最大深度,默认可以不输入。一般来说,数据少或者特征少的时候可以不管这个值。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。常用的可以取值10-100之间。
- 内部节点再划分所需最小样本数min_samples_split:这个值限制了子树继续划分的条件,如果某节点的样本数少于min_samples_split,则不会继续再尝试选择最优特征来进行划分
- 叶子节点最少样本数min_samples_leaf: 这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。 默认是1,可以输入最少的样本数的整数,或者最少样本数占样本总数的百分比。
- 最大叶子节点数max_leaf_nodes:通过限制最大叶子节点数,可以防止过拟合,默认是"None”,即不限制最大的叶子节点数。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。
以上只是给出了常用参数,完整参数需要查看Scikit-learn源码
补充
决策树可视化可以方便我们直观的观察模型,以及发现模型中的问题。可在scikit-learn中找到决策树的可视化方法。scikit-learn中决策树的可视化一般需要安装graphviz。详细以后补充