决策树的基本流程
决策树的结构
一颗决策树一般包括一个根结点,若干个内部结点和若干个叶结点。叶结点对应一个决策结果,其他结点则对应一个属性测试。对于每一个结点包含的样本,将会分到子结点中;根节点包括了样本的全集,从根到每一个叶的过程,也即是一个决策过程。
决策树伪代码
输入:训练集
D
=
{
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
.
.
.
.
.
.
(
x
m
,
y
m
)
}
D=\{(x_1,y_1),(x_2,y_2)......(x_m,y_m)\}
D={(x1,y1),(x2,y2)......(xm,ym)};属性集
A
=
{
a
1
,
a
2
,
.
.
.
,
a
d
}
A = \{a_1,a_2,...,a_d\}
A={a1,a2,...,ad}
过程:函数
T
r
e
e
G
e
n
e
r
a
t
e
(
D
,
A
)
TreeGenerate(D,A)
TreeGenerate(D,A)
1.生成结点node
2.if
D
D
D中样本全部归属于同一类别
C
C
C then
3.将node标记为
C
C
C类叶结点;return
4.end if
5.if
A
=
∅
A=\emptyset
A=∅ OR
D
D
D中样本在
A
A
A上取值相同 then
6.将node标记为叶子结点,其类别标记为
D
D
D中样本数最多的类;return
7.end if
8.从
A
A
A中选择最优划分属性
a
∗
a_*
a∗;
9.for
a
∗
a_*
a∗中每一个值
a
∗
v
a_*^v
a∗v do
10.为node生成一个分支,令
D
v
D_v
Dv表示
D
D
D在
a
∗
a_*
a∗上取值为
a
∗
v
a_*^v
a∗v的样本子集;
11.if
D
v
D_v
Dv为空 ** then**
12.将分支结点标记为叶子结点,其类别标记为
D
v
D_v
Dv中样本最多的类别;return
13.else
14.以
T
r
e
e
G
e
n
e
r
a
t
e
(
D
v
,
A
/
{
a
∗
}
)
TreeGenerate(D_v,A/ \{a_*\})
TreeGenerate(Dv,A/{a∗})作为分支结点
15.end if
16.end for
通过伪代码我们不难看出,决策树的生成是一个递归的过程。三种情况下会导致递归返回:
1.当前节点包含样本为同一类别,无需分类
2.当前节点包含样本的属性集为空或者所有样本的所有属性都相同,无法进行分类
3.当前节点包含的样本集合为空集
需要注意的是,第二种情况下,我们将样本集中样本最多的类别标记为叶子结点的类别,而在第三种情况下,我们将父节点所含样本数量最多的类别标记为叶节点类别。前者是在利用当前结点的后验分布,后者则是吧父结点的样本作为当前节点得到先验分布。
决策树的核心:划分选择
通过伪代码,不难发现算法的核心是第八步,也即是如何选择最优的划分属性。一般而言,我们希望随着决策树的生长,树的分支结点所包含的样本的类别尽量一致,也即是纯度(purity)越来越高。
信息增益
信息熵(information entropy)是一种常用来度量样本集合纯度的一种指标,假定当前样本集合
D
D
D中第
k
k
k类样本所占比例为
p
k
p_k
pk,则
D
D
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∑Ypklog2pk
信息熵越小,样本集合的纯度越高。
对于离散属性
a
a
a有V种取值,若使用a进行划分,则将会产生V个分支结点,对于每个结点所包含的样本
D
v
D_v
Dv,可以计算其信息熵,同时根据结点包含样本量数量给予每个结点相应权重
∣
D
v
∣
∣
D
∣
\frac{|D_v|}{|D|}
∣D∣∣Dv∣,于是可以计算出使用进行分类所带来的信息增益(information gain)
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=1}^{V}{\frac{|D_v|}{|D|}Ent(D_v)}
Gain(D,a)=Ent(D)−v=1∑V∣D∣∣Dv∣Ent(Dv)
则求解最优划分属性的过程也即是寻找使
G
a
i
n
(
D
,
a
)
Gain(D,a)
Gain(D,a)最大的属性
a
a
a。
增益率
信息增益存在一个问题,对于可取值数目较多的属性具有偏好,为了减少这种偏好带来的不利影响,C4.5决策树算法没有使用信息增益而是使用了增益率(gain ratio),定义其为
G
a
i
n
_
r
a
t
i
o
(
D
,
a
)
=
G
a
i
n
(
D
,
a
)
I
V
(
a
)
Gain\_ratio(D,a) = \frac{Gain(D,a)}{IV(a)}
Gain_ratio(D,a)=IV(a)Gain(D,a)
其中
I
V
(
a
)
=
−
∑
v
=
1
V
∣
D
v
∣
∣
D
∣
l
o
g
2
∣
D
v
∣
∣
D
∣
IV(a)=-\sum_{v=1}^{V}\frac{|D_v|}{|D|}log_2\frac{|D_v|}{|D|}
IV(a)=−v=1∑V∣D∣∣Dv∣log2∣D∣∣Dv∣
被称为属性
a
a
a的固有值(intrinsic value)。其种类越多,固有值越大。
同时也需要注意,增益率对于取值种类较少的属性由偏好,故而实际使用的时候,使用了一种启发式:先从候选划分中找出信息增益高于平均水平的属性,再从这些属性中找出增益率最高的。
基尼指数
CART(classification and regression tree)决策树使用了基尼指数(gini index)选择划分属性,定义基尼值为
G
i
n
i
(
D
)
=
∑
k
=
1
∣
y
∣
∑
k
′
≠
k
p
k
p
k
′
=
1
−
∑
k
=
1
∣
y
∣
p
k
2
\begin{aligned} Gini(D)&=\sum_{k=1}^{|y|}\sum_{k'\neq k}p_kp_{k'}\\ &=1-\sum_{k=1}^{|y|}p_k^2 \end{aligned}
Gini(D)=k=1∑∣y∣k′=k∑pkpk′=1−k=1∑∣y∣pk2
直观来说,基尼值反映了从数据集中抽取两个样本,其类别标记不一致的概率。
则属性a的基尼系数定义为
G
i
n
i
_
i
n
d
e
x
(
D
,
a
)
=
∑
v
=
1
V
∣
D
v
∣
∣
D
∣
G
i
n
i
(
D
)
Gini\_index(D,a)=\sum{v=1}^{V}\frac{|D_v|}{|D|}Gini(D)
Gini_index(D,a)=∑v=1V∣D∣∣Dv∣Gini(D)
信息增益、增益率和基尼系数,分别对应三种大名鼎鼎的算法,也即是ID3算法、C4.5算法和CART算法。实际运用中,使用不同的选择划分属性的方法的效果差异不大。
决策树防止过拟合:剪枝处理
为了防止决策树生长过程中学习得“太好”了,导致泛化能力下降,可以通过减少一些分支来降低过拟合风险。
预剪枝
预剪枝,指在树生成过程中,对每个结点在划分前进行估计,若节点的划分不能带来决策树泛化性能提升,则停止划分并标记当前结点为叶子结点。可以用留出法、交叉验证法、自助法等评估方法对泛化能力进行评估。
预剪枝会使得决策树的很多分支都无法展开,降低了过拟合风险,同时也减少了训练时间开销和测试时间开销。但另一方面,有些分支的当前划分可能不能带来泛化性能的显著提升,但是该划分的后续划分却有可能带来泛化性能的提升;预剪枝作为一种贪心算法,禁止这些分支展开,存在产生欠拟合的风险。
后剪枝
后剪枝,指先生成一颗完整的树,再自下而上对非叶子结点进行考察,若将节点替换为叶子节点可以带来树泛化性能提升则将其标记为叶子节点。
相比于预剪枝,后剪枝通常会保留更多分支,欠拟合风险较小,泛化性能一般优于预剪枝,但是由于需要进行从下而上对每一个非叶子结点进行考察,其训练时间开销比较大。
连续值和缺失值的处理
连续值处理
以上的讨论都是基于离散属性来生成决策树,但是现实学习任务中,常会遇到连续属性。此时需要将连续属性转化为离散属性。
在C4.5算法中,使用了二分法(bi-partition)对连续属性进行处理。对于连续属性
a
a
a,将其取值从小到大排列为
{
a
1
,
a
2
,
.
.
.
,
a
n
}
\{a^1,a^2,...,a^n\}
{a1,a2,...,an},取一点,将集合划分为大于该点和小于该点的两个部分,则划分点集合为
T
a
=
{
a
i
+
a
i
+
1
2
∣
1
≤
i
≤
n
−
1
}
T_a = \{\frac{a^i+a^{i+1}}{2}|1\leq i\leq{n-1}\}
Ta={2ai+ai+1∣1≤i≤n−1}
则可以像考察离散属性值一样来选取最优的划分点
G
a
i
n
(
D
,
a
)
=
m
a
x
G
a
i
n
(
D
,
a
,
t
)
=
m
a
x
E
n
t
(
D
)
−
∑
λ
∈
{
−
,
+
}
∣
D
t
λ
∣
∣
D
∣
E
n
t
(
D
t
λ
)
\begin{aligned} Gain(D,a)&=max\ Gain(D,a,t)\\ &=max\ Ent(D) - \sum_{\lambda \in\{-,+\}}{\frac{|D_t^{\lambda}|}{|D|}Ent(D_t^{\lambda})} \end{aligned}
Gain(D,a)=max Gain(D,a,t)=max Ent(D)−λ∈{−,+}∑∣D∣∣Dtλ∣Ent(Dtλ)