决策树
特点
决策树是一种基本的分类与回归方法,是一种树形结构,由内部结点和叶节点组成,其中:
- 内部结点表示一个特征和属性;
- 叶节点表示最终的分类了;
一个实例如下,其中椭圆为内部结点,方框为叶节点:
决策树与概率分布
决策树表示在给定特征条件下类的条件概率分布,这一条件概率分布定义在对特征空间的划分上。从模型的类型上讲,决策树属于判别模型,即最终求解的是 P ( Y ∣ X ) P(Y|X) P(Y∣X)。
决策树的学习
决策树的整个学习过程可以分为:
- 特征选择:局部的学习特征与类别的关系
- 决策树生成:根据选择的特征对数据集进行分类,递归的构建,直到划分之后的特征基本只有一类或者没有合适的特征进行分类
- 决策树剪枝:因为决策树对于特征的过细分类,导致决策树很容易过拟合,解决该问题的方法就是剪枝,将模型变得稍微简单一些,该部分的本质是通过操作使得损失函数(通常是正则化的极大似然函数)最小化。
先验知识
熵
熵表示信息的混乱程度(不确定性),通常用H(D)表示,其中X={(x1,y1), (x2,y2)…(xn,yn)}表示数据集,如果不加特殊的说明,H(D)表示对标签y的概率分布P(y)计算熵。
熵的公式如下:
H
(
X
)
=
−
∑
i
=
1
n
p
i
log
p
i
H(X)=-\sum_{i=1}^{n} p_{i} \log p_{i}
H(X)=−i=1∑npilogpi
其中如果log的底为2,则单位为比特,若log的底为e,则单位为纳特。
其中
−
log
p
i
-\log p_{i}
−logpi表示信息量(这里可以看做频率的倒数的对数值,P越大值越小),所以熵又可以看做是信息量的期望值。
举个例子来说:假设天气预报告诉你,明天90%的可能性会下雨,那么该事件的确定性其实很大,基本上你明天一定会带上雨伞,同理如果天气预报说下雨的可能性只有10%,那么你明天基本上就不会带伞;但是如果天气预报告诉你,明天50%的可能性会下雨,那么此时我们是最纠结的时候,因为这时候事件的确定性是很小的,我们最不确定明天是否会下雨。
以上就是一个二值的例子,如果用熵的公式表示这个时间的不确定性的话,可以得到下图:
可见当p=0.5的时候,事件的混乱度(不确定性)是最大的。
条件熵
将上述公式中换做:
H
(
Y
∣
X
)
=
∑
i
=
1
n
p
i
H
(
Y
∣
X
=
x
i
)
H(Y | X)=\sum_{i=1}^{n} p_{i} H\left(Y | X=x_{i}\right)
H(Y∣X)=i=1∑npiH(Y∣X=xi)
就可以表示在已知其中一个条件
X
=
x
i
X=x_i
X=xi时,事件的不确定性。由公式可以看出,条件熵是条件概率的熵的期望。
例如明天的天气情况X与后天是否有雨Y,我们根据历来的一些数据知道了 P ( Y ∣ X = 所 有 今 天 的 天 气 状 况 ) P(Y|X={所有今天的天气状况}) P(Y∣X=所有今天的天气状况) 的概率分布,那么我们就可以得到条件概率的熵,之后对明天的天气情况的概率分布 P ( X ) P(X) P(X)求期望就得到了条件熵。
基尼系数
基尼系数与熵类似,也是衡量一个事件确定程度的数值,具体的公式如下:
Gini
(
p
)
=
∑
k
=
1
K
p
k
(
1
−
p
k
)
=
1
−
∑
k
=
1
K
p
k
2
\operatorname{Gini}(p)=\sum_{k=1}^{K} p_{k}\left(1-p_{k}\right)=1-\sum_{k=1}^{K} p_{k}^{2}
Gini(p)=k=1∑Kpk(1−pk)=1−k=1∑Kpk2
与熵类似,基尼系数对于条件概率表示的事件也能评价其确定性,公式如下:
Gini
(
D
,
A
)
=
∣
D
1
∣
∣
D
∣
Gini
(
D
1
)
+
∣
D
2
∣
∣
D
∣
Gini
(
D
2
)
\operatorname{Gini}(D, A)=\frac{\left|D_{1}\right|}{|D|} \operatorname{Gini}\left(D_{1}\right)+\frac{\left|D_{2}\right|}{|D|} \operatorname{Gini}\left(D_{2}\right)
Gini(D,A)=∣D∣∣D1∣Gini(D1)+∣D∣∣D2∣Gini(D2)
总结
熵和基尼系数其实都是对于数据集确定性的一种度量方式,这里不进行过多介绍。
特征选择
决策树的特征分类与人类的行为是一致的,都是选择一个特征,以该特征为基准进行数据集的划分。简单的来讲,在选择特征的时候,一定是向着划分之后的子集 { S i ∣ S i ∈ S i = 1 , 2 , . . . , n } \{S_i | S_i \in S \quad i=1,2,...,n\} {Si∣Si∈Si=1,2,...,n}的确定度较高(即子集中的类别尽量都是一样的)的方向走,在程序实现时,往往会定义一个指标,让程序按照最大化或者最小化该指标的方向进行,这里我们把指标选择为信息增益。
信息增益(ID3采用)
信息增益的公式如下:
G
(
D
∣
A
)
=
H
(
D
)
−
H
(
D
∣
A
)
G(D|A)=H(D)-H(D|A)
G(D∣A)=H(D)−H(D∣A)
可以较为明显的看出来,信息增益是说:对于数据集D,其整体不确定性随着知道特征A之后会下降多少。其中 H ( D ) H(D) H(D)表示以label的熵, H ( D ∣ A ) H(D|A) H(D∣A)表示以特征A划分数据集后,所有子集不确定度的期望值。
信息增益比(C4.5采用)
信息增益比的公式如下:其中
H
A
(
D
)
H_A(D)
HA(D)是A特征在数据集D中的不确定度。
G
(
D
∣
A
)
=
H
(
D
)
−
H
(
D
∣
A
)
H
A
(
D
)
G(D|A)=\frac{H(D)-H(D|A)}{H_A(D)}
G(D∣A)=HA(D)H(D)−H(D∣A)
对比于信息增益,信息增益比是信息增益对于自身不确定性的比值。
信息增益比主要解决的是信息增益会偏向取值较多的特征的问题,因为取值较多的特征,往往(不是一定)会把数据集划分的比较细,造成信息增益较大的局面,相比于这样的特征而言,我们往往更希望能够选择取值不多,但是也能使得数据集确定度增加的特征。
还是由今天的天气情况预测明天是否下雨:假如特征向量中有温度这个特征,其取值较多,对于数据集的划分很大,很容易就使得信息增益较大,从而被认为是最好的划分特征;但是我们清楚,今天有雨其实对于明天下雨是更有参考意义的,通过除以选择特征的不确定度(温度变量的熵一般情况下应该更大,而今天有雨与否的会小),使得度量值能够更公平的反应特征对于数据集确定度贡献的特性。
生成决策树
有了上面的描述,生成决策树的思路其实就比较清晰了,一般我们使用递归的方法进行决策树的构建,描述如下:
输入变量:数据集D,特征名称A,阈值 ϵ \epsilon ϵ.
算法过程:
- a. 如果D中的所有类别都是一类,则生成叶节点,类为其中唯一的类;
- b. 如果A为空(没有更多的特征可以分割),则生成叶节点,类为其中最多的类别;
- c. 否则,对A中的每一个特征计算度量值(信息增益ID3或者信息增益比C4.5),选择其中使得度量值最大的特征 A g A_g Ag;
- d. 判断 A g A_g Ag是否小于阈值 ϵ \epsilon ϵ,如果是,则返回叶节点,类为其中最多的类;
- e. 使用 A g A_g Ag的所有取值对数据集进行划分,得到子集 D i D_i Di,该节点的类为所有数据中数量最多的类;
- f. 对于第i个子集 D i D_i Di,特征名称为 A − A g A-A_g A−Ag,传入a中,递归的生成决策树。
决策树的剪枝
决策树的剪枝是防止决策树过拟合的方法,由于决策树在生成的时候仅仅考虑了分类的准确度,模型在这个过程中会变得比较大,造成过拟合,防止过拟合的方法就是通过剪枝操作使得模型的规模减低,同时保证整体的熵不会降低很多。
1. 决策树的预剪枝
预剪枝方法是说在生成决策树的时候,通过一些参数使得节点划分的不用那么细,从而保证决策树的规模没有那么大,但是缺点就是对于参数的依赖比较敏感,鲁棒性不强。
2. 决策树的后剪枝
后剪枝的方法是在生成决策树之后,将“冗余的”的叶节点修剪掉,“冗余”是相对的,因为此时算法使用的数据集从训练集变为测试集,因此这里的冗余是对于测试集和特定的代价函数而言的,下面介绍代价函数。
代价函数
剪枝操作通过极小化代价函数的方式进行,其中代价函数可以如下所示(应有很多种方法定义,这里使用《统计学习方法》中的定义):
C
α
(
T
)
=
∑
t
=
1
∣
T
∣
N
t
H
t
(
T
)
+
α
∣
T
∣
C_{\alpha}(T)=\sum_{t=1}^{|T|}N_tH_t(T)+\alpha|T|
Cα(T)=t=1∑∣T∣NtHt(T)+α∣T∣
其中
α
\alpha
α为平衡系数,
∣
T
∣
|T|
∣T∣表示数量,该数量是以某一节点为根的树中包含的叶节点的数量,
N
t
N_t
Nt为树中第t个叶节点中包含的样本数量,
H
t
(
T
)
H_t(T)
Ht(T)是第t个叶节点的熵(或者其他的度量值)。
对于 α \alpha α,有如下几种情形:
- a. α = 0 \alpha=0 α=0,此时不对树做修剪是最好的,因为一旦修剪,父节点变为叶节点,其中样本数量 N t N_t Nt变大,同时叶节点的熵也变大,整体变大;
- b. α = inf \alpha=\inf α=inf, 此时算法更关注模型的规模,因此把整个树修剪掉是最好的,因为此时树的深度就为1了。
剪枝算法
- a. 计算决策树中每一个节点的(包括内部节点和叶节点)熵;
- b. 从叶节点向上回溯到其父节点,比较将该子树剪枝后的整体的代价函数 C a l p h a ( T B ) C_{alpha}(T_B) Calpha(TB)与剪枝之前的代价函数 C α ( T A ) C_{\alpha}(T_A) Cα(TA)的大小,如果代价函数变小或者相等,则使用剪枝之后的模型;如果变大了,则模型不变,找别的叶节点进行剪枝操作。