决策树
本文内容主体是基于李航老师的《统计学习方法》第二版中决策树的内容,有兴趣的同学可以自行参考书籍资料。其中个人觉得不是很直观的部分进行了适当的解释,解释仅属于个人理解,若觉得解释更加难以理解的同学可以自行忽略。代码部分有时间再补充。若文中有编辑错误,烦请指正,谢谢。
符号说明:
假设给定训练集样本 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)},N是样本数量。
其中, x i = ( x i ( 1 ) , x i ( 2 ) , . . . , x i ( n ) ) T x_i=(x_i^{(1)},x_i^{(2)},...,x_i^{(n)})^T xi=(xi(1),xi(2),...,xi(n))T,n是样本的特征数量; y i ∈ { 1 , 2 , . . . , K } y_i\in\{1,2,...,K\} yi∈{1,2,...,K}为对于样本的类标签,K为类别个数。
∣ D ∣ |D| ∣D∣表示样本总数量,根据某样本特征A可以将D划分为n个子集, D 1 , D 2 , . . . , D n D_1,D_2,...,D_n D1,D2,...,Dn, ∣ D i ∣ |D_i| ∣Di∣为对应子集的样本数量。
∣ C k ∣ |C_k| ∣Ck∣表示属于类 C k C_k Ck的样本个数,即 ∑ k = 1 K ∣ C k ∣ = ∣ D ∣ \sum_{k=1}^K |C_k|=|D| ∑k=1K∣Ck∣=∣D∣
D i k D_{ik} Dik表示子集 D i D_i Di中属于类 C k C_k Ck的样本的集合,其数量为 ∣ D i k ∣ |D_{ik}| ∣Dik∣。
1. 决策树简介
1.1 决策树的定义
众所周知,定义是一种概念的高度概括,尽管其包含的信息量很多很精华,但总是枯燥又无趣的。所以,在介绍定义前,先来看个引例,方便后续理解。
引例:
以教育为例,假设每个人都是一个样本(对应数据集),孔夫子说过,教育需要因材施教,所以我们的目标是尽可能地将每个人归到最适合自己的专业领域(对应数据标签),即专业是我们此处的最终目标(对应分类目标)。每个人都具有自己的特点,要怎么根据不同人的特点将每个人最终归到合适的专业呢?为此,每个人需要进行各方面的测试(对应数据特征),通过一次次的测试结果(对应决策树的有向边),到达自己最适合的专业领域。那么这个人才分流的过程(见下图),其实就是决策树算法的过程。
定义:分类决策树模型是一种描述对实例进行分类的树形结构。决策树由结点(node)和有向边(directed edge)组成。结点有两种类型:内部结点(internal node)和叶结点(leaf node)。内部结点表示实例的某个特征或属性,叶结点表示一个类。
如引例中所示,内部节点对应的就是每个人的特征,比如艺术感,使用艺术感这个特征,可以将人群大致分为艺术类和非艺术类。经过大量特征的选择后,每个人最终都会到达叶结点,也就是具体的每个专业领域(如工科、商科等)。所以说每个叶结点表示一个类,就是当前问题的最终分类。
所以,决策树可以看作一个if-then的集合,所有样本在每个内部结点都会进行一次if-then的判断。通过多次if-then的判断后,最终样本会到达某个叶结点,也就是最终的结论。
当然,事实上,决策树中每个样本的分类并不一定符合客观实时,只是决策树算法对于样本的一种划分。所以也说,决策树表示给定特征条件下类的条件概率分布。假设X是表示特征的随机变量(即引例中每个人的特点测试结果),Y是表示类的随机变量(即引例中的各种领域)。那么,决策树的叶结点只是表示一个概率
P
(
Y
∣
X
)
P(Y|X)
P(Y∣X),即在X构成的条件下属于Y类的概率。比如对于某个人来说,X=“艺术感好、音乐感好”,那么经过决策树算法后,其实会得到四个值,
P
(
Y
=
音
乐
∣
X
)
P(Y=音乐|X)
P(Y=音乐∣X)、
P
(
Y
=
美
术
∣
X
)
P(Y=美术|X)
P(Y=美术∣X)、
P
(
Y
=
工
科
∣
X
)
P(Y=工科|X)
P(Y=工科∣X)和
P
(
Y
=
商
科
∣
X
)
P(Y=商科|X)
P(Y=商科∣X)。也就是说,这个人去任何领域其实都是可能的,但是决策树算法最终算出来的
P
(
Y
=
音
乐
∣
X
)
P(Y=音乐|X)
P(Y=音乐∣X)是最大的,代表这个人在上述条件下,最有可能去音乐领域。
1.2 决策树算法的过程
1).特征选择:算法会根据某种原则,每次迭代选择对当前结点上的训练样本划分最好的特征。如果算法的特征数量很多,可以在决策树学习开始前,对特征进行选择,只留下对训练数据有足够分类能力的特征;
2).决策树的生成:反复进行特征选择,一步步将样本划分开来,直到所有训练数据子集被基本正确划分,或者没有合适特征为止。最后每个样本都被分类到某个叶结点上,这就生成了一棵决策树。
3).决策树的剪枝:理论上,决策树可以完美地将训练样本划分为准确的类,但是当使用的特征过多,叶结点也会随之增长,即最终分类出来的类别也很多。这对已知数据可能能很好的拟合,但是对于未知数据的泛化效果是很差的。就好比,将一个人分为音乐家后,还要强行划分为左手音乐家还是右手音乐家,这种划分过于细致,会让训练模型产生过拟合现象。所以,有时候决策树生成后,需要对决策树进行剪枝,剪去过于琐碎的分叉,从而得到更好的泛化效果。
决策树学习的策略:因为决策树可以看作给定特征条件下类的条件概率分布,所以决策树算法的损失函数通常是正则化的极大似然函数。决策树学习的策略是使损失函数最小。因为从所有可能的决策树中选取最优决策树是NP问题,所以现实中决策树的算法通常采用启发式方法,近似求解最优问题。所以得到的决策树通常是次优的,不是全局最优解。
2. 特征选择
从第一章中可知,算法需要根据某种原则来选择特征,保证每次选择分类效果最好的特征作为内部节点。所以这章就会介绍特征选择的原则。
2.1 知识储备
1).熵
定义:在信息论与概率统计中,熵是表示随机变量不确定性的度量。
什么叫不确定性呢?直观来解释,假设事件A一共可能出现
A
i
A_i
Ai种情况,
i
=
1
,
2
,
.
.
.
,
n
i=1,2,...,n
i=1,2,...,n。出现
A
i
A_i
Ai情况的概率是
P
(
A
=
A
i
)
=
p
i
P(A=A_i)=p_i
P(A=Ai)=pi。那么,如果
∀
k
,
P
(
A
=
A
k
)
→
1
\forall k,P(A=A_k)→1
∀k,P(A=Ak)→1,那么很明显,这个事件A的确定性就很大,因为事件A很可能发生
A
k
A_k
Ak的情况。相反地,如果每个
p
i
p_i
pi数值都差不多,那么就很难分辨清楚到底可能发生什么情况,所以就说随机变量A的不确定性很大,也就是熵很大。
数学表达:
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
注意
- 上式虽然通常写成 H ( X ) H(X) H(X),但其实只是为了表示是随机变量X的熵,并不代表熵的取值本身与随机变量X的取值有关系。按函数的角度来说,其实应该写成 H ( p i ) H(p_i) H(pi)。
- log的底数通常取2或e,这时熵对应的单位称为比特(bit)或纳特(nat)。
- 为什么要取 log p i \log p_i logpi,其实是一种数学构造,首先 p i ∈ [ 0 , 1 ] p_i\in[0,1] pi∈[0,1], ∴ log p i ∈ ( − ∞ , 0 ] ∴\log p_i\in(-∞,0] ∴logpi∈(−∞,0],并且规定 0 log 0 = 0 0\log 0=0 0log0=0。那么上式取负号后就有 − log p i ∈ [ 0 , + ∞ ) -\log p_i\in[0,+∞) −logpi∈[0,+∞)。根据定义中的分析可知,如果任意的 p i p_i pi越大,那熵值应该越低;但并不是 p i p_i pi越小,熵值越高,而是所有 p i p_i pi数值越平均,其熵值应该越大。所以最终构造出对 − log p i -\log p_i −logpi的期望 E ( − log p i ) E(-\log p_i) E(−logpi),作为熵的表达式。
2).条件熵
定义:条件熵表示在已知随机变量X的条件下,随机变量Y的不确定性。
在下文的信心增益的定义中,可以知道为什么需要使用条件熵的概念。下式理解起来其实也很直观,根据定义,是要度量随机变量X已知的情况下,事件Y的不确定性。而随机变量X发生各种情况的可能性为
p
i
p_i
pi,每种情况下对应的随机变量Y的熵值为
H
(
Y
∣
X
=
x
i
)
H(Y|X=x_i)
H(Y∣X=xi),所以对
H
(
Y
∣
X
)
H(Y|X)
H(Y∣X)取期望即可得到下式。
数学表达:
H
(
Y
∣
X
)
=
∑
i
=
1
n
p
i
H
(
Y
∣
X
=
x
i
)
,
其
中
p
i
=
P
(
X
=
x
i
)
,
i
=
1
,
2
,
.
.
.
,
n
H(Y|X)=\sum_{i=1}^n p_iH(Y|X=x_i),其中p_i=P(X=x_i),i=1,2,...,n
H(Y∣X)=i=1∑npiH(Y∣X=xi),其中pi=P(X=xi),i=1,2,...,n
3).经验熵和经验条件熵
当熵和条件熵中的概率由数据估计(特别是极大似然估计)得到时,所对应的熵和条件熵就叫做经验熵和经验条件熵。其实实际应用中,使用计算得出的都是经验熵和经验条件熵,因为真实的事件概率都是无法计算出来的,只能用大量的样本进行估计,所以都是经验值。
2.2 信息增益(information gain)
定义:表示得知特征X的信息而使得类Y的信息的不确定性减少的程度。
上述定义非常直观,就是已知X,会使得Y的信息不确定度减少的数值,就是信息增益。也就是
H
(
Y
)
−
H
(
Y
∣
X
)
H(Y)-H(Y|X)
H(Y)−H(Y∣X)。一般地,
H
(
Y
)
−
H
(
Y
∣
X
)
H(Y)-H(Y|X)
H(Y)−H(Y∣X)也称作互信息。那么,转换为机器学习中的说法就是:特征A对训练数据集D的信息增益
g
(
D
,
A
)
g(D,A)
g(D,A),定义为集合D的经验熵
H
(
D
)
H(D)
H(D)与给定特征A的条件下,D的经验条件熵
H
(
D
∣
A
)
H(D|A)
H(D∣A)之差,即:
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的不确定性减少最大的特征。也就是选择一个对当前数据集信息增益最大的特征进行划分即可。
计算信息增益的算法
符号说明请参见上文。
- 计算数据集D的经验熵H(D)
H ( D ) = − ∑ k = 1 K ∣ C k ∣ ∣ D ∣ log 2 ∣ C k ∣ ∣ D ∣ H(D)=-\sum_{k=1}^K \frac{|C_k|}{|D|}\log_2 \frac{|C_k|}{|D|} H(D)=−k=1∑K∣D∣∣Ck∣log2∣D∣∣Ck∣
数据集D的经验熵可以这么理解,把D当作是一个随机变量(事件),因为我们最终要对数据集D进行分类,所以,数据集D内的每个样本最终都会属于某个分类(而对于训练集来说,每个样本的分类都是已知的),所以样本的最终分类就是随机变量D发生的情况。对于类别k来说,其发生的概率就是 p k = ∣ C k ∣ ∣ D ∣ p_k=\frac{|C_k|}{|D|} pk=∣D∣∣Ck∣。所以再根据熵的计算公式,即可以得到上式。 - 计算特征A对数据集D的经验条件熵
H
(
D
∣
A
)
H(D|A)
H(D∣A)
H ( D ∣ A ) = ∑ i = 1 n ∣ D i ∣ ∣ D ∣ H ( D i ) = − ∑ i = 1 n ∣ D i ∣ ∣ D ∣ ∑ k = 1 K ∣ D i k ∣ ∣ D i ∣ log 2 ∣ D i k ∣ ∣ D i ∣ H(D|A)=\sum_{i=1}^n \frac{|D_i|}{|D|}H(D_i)=-\sum_{i=1}^n \frac{|D_i|}{|D|}\sum_{k=1}^K \frac{|D_{ik}|}{|D_i|}\log_2\frac{|D_{ik}|}{|D_i|} H(D∣A)=i=1∑n∣D∣∣Di∣H(Di)=−i=1∑n∣D∣∣Di∣k=1∑K∣Di∣∣Dik∣log2∣Di∣∣Dik∣
上式中的 D i k D_{ik} Dik比较不好理解。举个例子,假设当前样本需要计算样本年龄特征的经验条件熵,即特征A是年龄。那么,需要对特征进行划分,比如以10岁以下为一组;10~20岁为一组;20-30为一组;30以上为一组共四组。这样,数据集就可以根据特征A划分为 D 1 , D 2 , D 3 , D 4 D_1,D_2,D_3,D_4 D1,D2,D3,D4四组。再假设当前任务的最终目标是将人群进行分类,分为A,B,C,D四类。那么 D i k D_{ik} Dik就表示按特征划分为第 D i D_i Di组,最终归类为第k类的样本集合。对于不同的特征, D i D_i Di的划分总是不相同的;但是对于同一个问题,最终的目标的K个类别总是相同的。
H ( D i ) H(D_i) H(Di)就是根据特征划分后,某个子集集合 D i D_i Di对于K个类别的熵值。 - 计算信息增益(终于可以计算了)
g ( D , A ) = H ( D ) − H ( D ∣ A ) g(D,A)=H(D)-H(D|A) g(D,A)=H(D)−H(D∣A)
2.3 信息增益比
以信息增益作为划分训练数据集特征的原则,通常结果偏向于选择取值较多的特征。因为某个特征将数据集划分的子集数量越多,相对来说每个
∣
D
i
∣
|D_i|
∣Di∣的数值就越小。那么一方面,
∣
D
i
∣
/
∣
D
∣
|D_i|/|D|
∣Di∣/∣D∣的数值就越小;另一方面,因为
D
i
D_i
Di子集的数量少,而分类类别总数K对于每个子集是恒定的,那么
H
(
D
i
)
H(D_i)
H(Di)的确定性很可能就越大,熵值就越小(可以理解为子集数量少,最终类别平均分布在几个子集的概率就低)。所以
H
(
D
∣
A
)
H(D|A)
H(D∣A)就越小,即该特征对应的信息增益就可能更大。
使用信息增益比可以对该情况进行矫正,是另一种选取特征的原则。
定义:特征A对训练数据集D的信息增益比
g
R
(
D
,
A
)
g_R(D,A)
gR(D,A)定义为其信息增益
g
(
D
,
A
)
g(D,A)
g(D,A)于训练数据集D关于特征A的值的熵
H
A
(
D
)
H_A(D)
HA(D)之比。
数学表达:
g
R
(
D
,
A
)
=
g
(
D
,
A
)
H
A
(
D
)
,
其
中
H
A
(
D
)
=
−
∑
i
=
1
n
∣
D
i
∣
∣
D
∣
log
2
∣
D
i
∣
∣
D
∣
g_R(D,A)=\frac{g(D,A)}{H_A(D)},其中H_A(D)=-\sum_{i=1}^n\frac{|D_i|}{|D|}\log_2\frac{|D_i|}{|D|}
gR(D,A)=HA(D)g(D,A),其中HA(D)=−i=1∑n∣D∣∣Di∣log2∣D∣∣Di∣
(定义总是让人捉摸不透)其实,
H
A
(
D
)
H_A(D)
HA(D)就是说,数据集D根据特征A划分为多个子集
{
D
i
}
\{D_i\}
{Di},然后数据集D针对划分子集这个事件的熵。其实看数学表达比较容易理解。
3. 决策树的生成
3.1 ID3算法
ID3算法具体步骤很简单:从根节点开始,对结点计算所有可能的特征的信息增益,选择信息增益最大的特征作为结点的特征,由该特征的不同取值建立子节点;再对子节点递归地调用以上方法,构建决策树;直到所有特征的信息增益均很小或没有特征可以选择为止。最后得到一棵决策树。ID3算法相当于用极大似然法进行概率模型的选择。
ID3算法实施:
- 输入:训练数据集D,特征集A,设置信息增益阈值 ϵ \epsilon ϵ
- 输出:决策树T。
- 1).若D中所有实例属于同一类 C k C_k Ck,则T为单结点树,并将类 C k C_k Ck作为该结点的类标记,返回T;
- 2).若 A = ∅ A=\empty A=∅,则T为单结点树,并将D中实例个数最大的类 C k C_k Ck作为该结点的类标记,返回T;
- 3).否则,计算A中各个特征对D的信息增益 g ( D , A i ) g(D,A_i) g(D,Ai),选择信息增益最大的特征 A g A_g Ag;
- 4).如果 A g A_g Ag的信息增益小于阈值 ϵ \epsilon ϵ,则置T为单节点树,并将D中实例数最大的类 C k C_k Ck作为该结点的类标记,返回T;
- 5).否则,对 A g A_g Ag的每一可能值 a i a_i ai,依 A g = a i A_g=a_i Ag=ai将D分割为若干非空子集 D i D_i Di,将 D i D_i Di中实例数最大的类作为标记,构建子结点。由结点及其子结点构成树T,返回T;
- 6).对第i个子结点,以 D i D_i Di为训练集,以 A − { A g } A-\{A_g\} A−{Ag}为特征集,递归地调用第1-5步,得到子树 T i T_i Ti,返回 T i T_i Ti。
算法部分没有什么好解释的了,看起来很复杂,其实也挺复杂的。但是一步一步理解了操作下来还是可以的。需要具备一定的代码基础,包括数据结构等等。还是强烈建议自己写一遍算法,然后再上网搜一下sklearn决策树相关源码,对比理解一下,对算法的理解会有很大提升。毕竟机器学习不只是研究理论,实际的编码能力还是要有的。博主的代码有时间会公布在github上,公布后会在本文中贴出。
3.2 C4.5算法
C4.5算法和ID3算法几乎一样,进行了适当的改进,就是选择特征的标准从信息增益换成了信息增益比。
C4.5算法实施:
- 输入:训练数据集D,特征集A,设置信息增益阈值 ϵ \epsilon ϵ
- 输出:决策树T。
- 1).若D中所有实例属于同一类 C k C_k Ck,则T为单结点树,并将类 C k C_k Ck作为该结点的类标记,返回T;
- 2).若 A = ∅ A=\empty A=∅,则T为单结点树,并将D中实例个数最大的类 C k C_k Ck作为该结点的类标记,返回T;
- 3).否则,计算A中各个特征对D的信息增益比 g R ( D , A i ) g_R(D,A_i) gR(D,Ai),选择信息增益比最大的特征 A g A_g Ag;
- 4).如果 A g A_g Ag的信息增益比小于阈值 ϵ \epsilon ϵ,则置T为单节点树,并将D中实例数最大的类 C k C_k Ck作为该结点的类标记,返回T;
- 5).否则,对 A g A_g Ag的每一可能值 a i a_i ai,依 A g = a i A_g=a_i Ag=ai将D分割为若干非空子集 D i D_i Di,将 D i D_i Di中实例数最大的类作为标记,构建子结点。由结点及其子结点构成树T,返回T;
- 6).对第i个子结点,以 D i D_i Di为训练集,以 A − { A g } A-\{A_g\} A−{Ag}为特征集,递归地调用第1-5步,得到子树 T i T_i Ti,返回 T i T_i Ti。
算法部分没有什么好解释的了,看起来很复杂,其实也挺复杂的。但是一步一步理解了操作下来还是可以的。需要具备一定的代码基础,包括数据结构等等。还是强烈建议自己写一遍算法,然后再上网搜一下sklearn决策树相关源码,对比理解一下,对算法的理解会有很大提升。毕竟机器学习不只是研究理论,实际的编码能力还是要有的。博主的代码有时间会公布在github上,公布后会在本文中贴出。
3.3 CART算法(分类和回归树,classification and regression tree)
分类和回归树,顾名思义是可以用于分类也可以用于回归的决策树模型。注意,前面两种算法得到的树都是任意结构的树,而CART算法得到的树是二叉树。内部结点特征的取值为“是”和“否”,并规定左结点为“是”分支,右结点为“否"分支。
I.针对回归问题的CART
针对回归问题的CART,使用的最小化准则为平方误差。
假设X与Y分别为输入和输出变量,并且Y是连续变量,给定训练数据集
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)}
假设经过CART算法后,生成了如上图的二叉决策树。共4个结点。输入空间被划分为4个单元
R
1
,
R
2
,
.
.
.
,
R
4
R_1,R_2,...,R_4
R1,R2,...,R4。可以看到,每个空间包含的样本集合都已经在图中圈出来了。每个单元
R
m
R_m
Rm(即叶结点)都有一个固定的输出值
c
m
c_m
cm,
c
m
c_m
cm最好的取值方式就是属于
R
m
R_m
Rm单元内所有样本对应的输出值的均值,即
c
m
=
a
v
e
(
y
i
∣
x
i
∈
R
m
)
c_m=ave(y_i|x_i\in R_m)
cm=ave(yi∣xi∈Rm)
那么,该怎样对输入空间进行划分呢?(即如何选择样本特征作为二叉树的内部结点呢?)这里采用启发式的方法:选择第j个特征的样本集合
{
x
(
j
)
}
\{x^{(j)}\}
{x(j)},假定s是划分该特征的阈值。这个特征就叫做切分变量(splitting variable,个人觉得叫切分特征好理解一些),这个阈值就叫做切分点(splitting point),并定义对应划分的两个区域:
R
1
(
j
,
s
)
=
{
x
∣
x
(
j
)
≤
s
}
和
R
2
(
j
,
s
)
=
{
x
∣
x
(
j
)
>
s
}
R_1(j,s)=\{x|x^{(j)}\le s\} 和 R_2(j,s)=\{x|x^{(j)}>s\}
R1(j,s)={x∣x(j)≤s}和R2(j,s)={x∣x(j)>s}
然后在当前数据集D(或子集
D
i
D_i
Di)的所有特征中,寻找最优切分变量j和最优切分点s,求解:
min
j
,
s
[
min
c
1
∑
x
i
∈
R
1
(
j
,
s
)
(
y
i
−
c
1
)
2
+
min
c
2
∑
x
i
∈
R
2
(
j
,
s
)
(
y
i
−
c
2
)
2
]
\min\limits_{j,s}[\min\limits_{c_1}\sum\limits_{x_i\in R_1(j,s)}(y_i-c_1)^2+\min\limits_{c_2}\sum\limits_{x_i\in R_2(j,s)}(y_i-c_2)^2]
j,smin[c1minxi∈R1(j,s)∑(yi−c1)2+c2minxi∈R2(j,s)∑(yi−c2)2]
对固定的j,都可以找到各自的最优切分点s。切分后左右子结点代表的输出值就是:
c
1
=
a
v
e
(
y
i
∣
x
i
∈
R
1
(
j
,
s
)
)
,
c
2
=
a
v
e
(
y
i
∣
x
i
∈
R
2
(
j
,
s
)
)
c_1=ave(y_i|x_i\in R_1(j,s)),c_2=ave(y_i|x_i\in R_2(j,s))
c1=ave(yi∣xi∈R1(j,s)),c2=ave(yi∣xi∈R2(j,s))
遍历所有的特征 j,每个特征都构成一个数据对
(
j
,
s
)
(j,s)
(j,s)。从中找到最优的切分特征,根据该特征将当前数据集划分为两个区域。接着,对为满足结束条件的子区域继续执行上述过程,直到满足停止条件为止。这样,我们就得到了最终所有叶结点的划分空间
R
1
,
R
2
,
.
.
.
,
R
M
R_1,R_2,...,R_M
R1,R2,...,RM(注意,此处的
R
i
R_i
Ri均是叶结点代表的样本空间),以及每个空间代表的输出值
c
m
c_m
cm。用这棵决策树,就可以预测回归问题,决策树的输出为:
f
(
x
)
=
∑
m
=
1
M
c
m
I
(
x
∈
R
m
)
f(x)=\sum_{m=1}^M c_mI(x\in R_m)
f(x)=m=1∑McmI(x∈Rm)
下面是CART回归型决策树的算法实施:
- 输入:训练数据集D,设置停止条件
- 输出:回归树的输出f(x)
- 1).遍历当前结点数据集的所有特征,对固定特征j扫描所有切分点s,选择最优切分变量与切分点
(
j
,
s
)
(j,s)
(j,s):
min j , s [ min c 1 ∑ x i ∈ R 1 ( j , s ) ( y i − c 1 ) 2 + min c 2 ∑ x i ∈ R 2 ( j , s ) ( y i − c 2 ) 2 ] \min\limits_{j,s}[\min\limits_{c_1}\sum\limits_{x_i\in R_1(j,s)}(y_i-c_1)^2+\min\limits_{c_2}\sum\limits_{x_i\in R_2(j,s)}(y_i-c_2)^2] j,smin[c1minxi∈R1(j,s)∑(yi−c1)2+c2minxi∈R2(j,s)∑(yi−c2)2] - 2).用选好的
(
j
,
s
)
(j,s)
(j,s)划分当前数据集,并求出子结点代表的输出值:
R 1 ( j , s ) = { x ∣ x ( j ) ≤ s } 和 R 2 ( j , s ) = { x ∣ x ( j ) > s } R_1(j,s)=\{x|x^{(j)}\le s\} 和 R_2(j,s)=\{x|x^{(j)}>s\} R1(j,s)={x∣x(j)≤s}和R2(j,s)={x∣x(j)>s}
c 1 、 2 = a v e ( y i ∣ x i ∈ R 1 、 2 ( j , s ) ) = 1 N 1 、 2 ∑ x i ∈ R 1 、 2 ( j , s ) y i c_{1、2}=ave(y_i|x_i\in R_{1、2}(j,s))=\frac{1}{N_{1、2}}\sum\limits_{x_i\in R_{1、2}(j,s)}y_i c1、2=ave(yi∣xi∈R1、2(j,s))=N1、21xi∈R1、2(j,s)∑yi - 3).重复步骤1、2,直到满足停止条件;
- 4).最终得到决策树,将输入空间划分为M个区域
R
1
,
R
2
,
.
.
.
,
R
M
R_1,R_2,...,R_M
R1,R2,...,RM,计算待预测样本的输出值:
f ( x ) = ∑ m = 1 M c m I ( x ∈ R m ) f(x)=\sum_{m=1}^M c_mI(x\in R_m) f(x)=m=1∑McmI(x∈Rm)
II.针对分类问题的CART
分类问题的CART使用的特征选择原则为基尼指数,同时决定最优特征的最优二值切分点。
基尼指数的数学表达:
G
i
n
i
(
p
)
=
∑
k
=
1
K
p
k
(
1
−
p
k
)
=
1
−
∑
k
=
1
K
p
k
2
,
对
二
分
类
问
题
=
2
p
(
1
−
p
)
Gini(p)=\sum_{k=1}^Kp_k(1-p_k)=1-\sum_{k=1}^Kp_k^2,对二分类问题=2p(1-p)
Gini(p)=k=1∑Kpk(1−pk)=1−k=1∑Kpk2,对二分类问题=2p(1−p)
由于CART将每个特征的划分都假定为二分类问题,即某个特征是否取某一数值。所以,在给定样本集合D的情况下,根据特征A是否取某一可能值a,可以将样本划分为两个子集
D
1
,
D
2
D_1,D_2
D1,D2
D
1
=
{
(
x
,
y
)
∈
D
∣
A
(
x
)
=
a
}
,
D
2
=
D
−
D
1
D_1=\{(x,y)\in D|A(x)=a\},D_2=D-D_1
D1={(x,y)∈D∣A(x)=a},D2=D−D1
此时,在特征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)
基尼指数
G
i
n
i
(
D
)
,
G
i
n
i
(
D
,
A
)
Gini(D),Gini(D,A)
Gini(D),Gini(D,A)也表示了数据的不确定性,其含义和上文中的熵与条件熵几乎是一样的。
CART算法实施:
- 输入:训练数据集D,设置停止计算的条件
- 输出:CART决策树
- 根据训练数据集,从根节点开始,递归地对每个结点进行以下操作,构建二叉决策树:
- 1).设结点的训练数据集为D,计算现有特征对该数据集的基尼指数。此时,对每个特征A,对其可能取的每个值a,根据样本点对A=a的测试为“是”或“否”,将D分割成 D 1 , D 2 D_1,D_2 D1,D2两部分,利用公式计算A=a时的基尼指数;
- 2).在所有可能的特征A以及他们所有可能的切分点a中,选择基尼指数最小的特征及其对应的切分点作为最优特征与最优切分点。根据最优特征与最优切分点,从现结点生成两个子结点,将训练集分配到两个子结点中去。
- 3).重复上述步骤1、2,直到满足停止条件,即可生成CART决策树。
算法停止计算的条件是结点中的样本个数小于预定阈值,或者样本集的基尼指数小于阈值(意味着当前结点内的样本基本属于一类),或者没有更多特征。
4. 决策树的剪枝
决策树算法的特点决定了决策树可以对样本训练集进行几乎完美的拟合,但是通常这样会导致过拟合问题。决策树出现过拟合问题是很常见的,所以通常都需要对决策树进行剪枝。
4.1 ID3/C4.5的剪枝
简单的剪枝方法是,通过极小化决策树整体的损失函数来实现。
假设树T的叶结点个数为
∣
T
∣
|T|
∣T∣个,t是树T的叶结点,该叶结点有
N
t
N_t
Nt个样本点,其中k类的样本点有
N
t
k
N_tk
Ntk个,
k
=
1
,
2
,
.
.
.
,
K
k=1,2,...,K
k=1,2,...,K,
H
t
(
T
)
H_t(T)
Ht(T)为叶结点t上的经验熵,
α
≥
0
\alpha\ge 0
α≥0是正则项超参数。决策树学习的损失函数可以定义为:
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∣
其
中
经
验
熵
:
H
t
(
T
)
=
−
∑
k
N
t
k
N
t
log
N
t
k
N
t
,
记
C
(
T
)
=
∑
t
=
1
∣
T
∣
N
t
H
t
(
T
)
=
−
∑
t
=
1
∣
T
∣
∑
k
=
1
K
N
t
k
log
N
t
k
N
t
其中经验熵:H_t(T)=-\sum\limits_k \frac{N_{tk}}{N_t} \log \frac{N_{tk}}{N_t},记C(T)=\sum_{t=1}^{|T|}N_tH_t(T)=-\sum_{t=1}^{|T|}\sum_{k=1}^KN_{tk}\log \frac{N_{tk}}{N_t}
其中经验熵:Ht(T)=−k∑NtNtklogNtNtk,记C(T)=t=1∑∣T∣NtHt(T)=−t=1∑∣T∣k=1∑KNtklogNtNtk
∴
C
α
(
T
)
=
C
(
T
)
+
α
∣
T
∣
∴C_{\alpha}(T)=C(T)+\alpha|T|
∴Cα(T)=C(T)+α∣T∣
其实就是所有叶结点的熵的总和,加上一个正则项。
α
\alpha
α越大,倾向于选择结构简单的树;反之,则选择结构复杂的树。
剪枝算法流程:
- 输入:生成算法产生的整个树T,参数 α \alpha α;
- 输出:修剪后的子树 T α T_{\alpha} Tα;
- 1).计算每个结点的经验熵;
- 2).递归地从树的叶结点向上回缩(就是从叶结点向上遍历)。设一组叶结点回缩到其父节点之前与之后的整体树分别为 T B T_B TB与 T A T_A TA,其对应的损失函数分别是 C α ( T B ) C_{\alpha}(T_B) Cα(TB)与 C α ( T A ) C_{\alpha}(T_A) Cα(TA),如果: C α ( T A ) ≤ C α ( T B ) C_{\alpha}(T_A)\le C_{\alpha}(T_B) Cα(TA)≤Cα(TB),则进行剪枝,即将父节点变为新的叶结点,其子结点全部删去。
- 3).重复执行步骤2,直到不能继续为止,即可得到损失函数最小的子树 T α T_{\alpha} Tα。
4.2 CART的剪枝
CART算法的剪枝是首先从算法生成的决策树 T 0 T_0 T0底端开始不断剪枝,直到 T 0 T_0 T0的根节点为止,形成一个子树序列 { T 0 , T 1 , . . . , T n } \{T_0,T_1,...,T_n\} {T0,T1,...,Tn},其中,从 T 0 T_0 T0开始往后,每棵树与后续的子树都是包含关系,及下标小的树包含下标大的树。然后,通过交叉验证法在独立的验证数据集上,对子树序列进行测试,根据验证集的损失函数选择其中的最优子树。
- 剪枝,形成子树序列
Breiman等人证明了:可以用递归的方式对树进行剪枝。将 α \alpha α从小增大, 0 = α 0 < α 1 < . . . < α n < + ∞ 0=\alpha_0<\alpha_1<...<\alpha_n<+∞ 0=α0<α1<...<αn<+∞,产生一系列区间 [ α i , α i + 1 ) , i = 0 , 1 , . . . , n [\alpha_i,\alpha_{i+1}),i=0,1,...,n [αi,αi+1),i=0,1,...,n;剪枝得到的子树序列对应着区间 α ∈ [ α i , α i + 1 ) , i = 0 , 1 , . . . , n \alpha\in[\alpha_i,\alpha_{i+1}),i=0,1,...,n α∈[αi,αi+1),i=0,1,...,n的最优子树序列 { T 0 , T 1 , . . . , T n } \{T_0,T_1,...,T_n\} {T0,T1,...,Tn},序列中的子树是嵌套的。
因为之后是要对生成的子树序列内的所有子树都进行交叉验证,从中选择最优的子树作为结果的,所以希望子树序列能够尽可能多地包含各种剪枝情况。那么什么时候一个内部结点需要进行剪枝呢?考察原二叉树 T 0 T_0 T0的一个内部结点t:
以t为单结点的树的损失函数是:
C α ( t ) = C ( t ) + α C_{\alpha}(t)=C(t)+\alpha Cα(t)=C(t)+α
以t为根节点的树 T t T_t Tt的损失函数为(注意,此处 T t T_t Tt不是最终子树序列中的 T i T_i Ti,要注意区分, T i T_i Ti的根结点都是 T 0 T_0 T0的根节点。)
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 t ) ≥ C α ( t ) C_{\alpha}(T_t)\ge C_{\alpha}(t) Cα(Tt)≥Cα(t)的情况,那么说明内部结点t继续划分为子树后,其数据集整体的损失函数至少没变化或反而增大了,也就是划分了还不如不分,那么这时候,就可以将t结点下端的子树剪掉。
取 C α ( T t ) ≥ C α ( t ) ⇒ α ≥ C ( t ) − C ( T t ) ∣ T t ∣ − 1 ⇒ 记 g ( t ) = C ( t ) − C ( T t ) ∣ T t ∣ − 1 取C_{\alpha}(T_t) \ge C_{\alpha}(t) \Rightarrow \alpha \ge \frac{C(t)-C(T_t)}{|T_t|-1}\Rightarrow 记g(t)=\frac{C(t)-C(T_t)}{|T_t|-1} 取Cα(Tt)≥Cα(t)⇒α≥∣Tt∣−1C(t)−C(Tt)⇒记g(t)=∣Tt∣−1C(t)−C(Tt)
说明,当正则项系数 α \alpha α的数值大于 g ( t ) g(t) g(t)时,t结点的子树只会增加整体的损失值,而不会下降,这时应该减去。
观察一下 g ( t ) g(t) g(t)的实际含义,分子是t结点剪枝后的熵值与剪枝前t结点为根的子树的熵值之差,也就是剪枝前后的熵差。通常情况下,数据集在t结点后继续划分,不加入正则项时,有 C ( t ) − C ( T t ) > 0 C(t)-C(T_t)>0 C(t)−C(Tt)>0。分母是t结点下端子树的结点总数(不包含t结点)。所以 g ( t ) g(t) g(t)可以理解成当正则项系数 α \alpha α的数值大于 g ( t ) g(t) g(t)时,剪枝后整体损失函数的减少程度。为了尽量使子树序列包含最多的剪枝情况,所以不能一下就选剪枝后整体损失函数下降很大的 g ( t ) g(t) g(t),因此要选择当前的最小 g ( t ) g(t) g(t)所对应的结点,作为进行剪枝操作的结点。如此剪枝下去,直到剪到根节点,这个过程中, α \alpha α也在不断的迭代、增大。所得到的子树序列就是最完整的子树序列 { T 0 , T 1 , . . . , T n } \{T_0,T_1,...,T_n\} {T0,T1,...,Tn} - 在子树序列
{
T
0
,
T
1
,
.
.
.
,
T
n
}
\{T_0,T_1,...,T_n\}
{T0,T1,...,Tn}中通过交叉验证选取最优子树
T
α
T_{\alpha}
Tα
具体来说,就是利用验证集,计算每棵子树的平方误差(回归)或基尼指数(分类),选择损失最小的子树,就是最优的决策树 T α T_{\alpha} Tα。
CART剪枝算法实施:
- 输入:CART算法生成的决策树 T 0 T_0 T0
- 输出:最优决策树 T α T_{\alpha} Tα
- 1).设 k = 0 , T = T 0 , α = + ∞ k=0,T=T_0,\alpha=+∞ k=0,T=T0,α=+∞;
- 2).自下而上地对所有内部结点t计算 C ( T t ) , ∣ T t ∣ C(T_t),|T_t| C(Tt),∣Tt∣以及 g ( t ) g(t) g(t),并迭代 α = m i n ( α , g ( t ) ) \alpha=min(\alpha,g(t)) α=min(α,g(t)),找到最小的 g ( t ) g(t) g(t)。再次强调,这里的 T t T_t Tt是以t为根节点的子树,和用于交叉验证的子树序列的 T i , i = 0 , 1 , . . . , n T_i,i=0,1,...,n Ti,i=0,1,...,n是不同的。
- 3).对 t = arg t min g ( t ) t=\arg\limits_t\min g(t) t=targming(t),即最小 g ( t ) g(t) g(t)对应的内部结点t,进行剪枝。并对剪枝后的叶结点t以多数表决法决定其类,得到树T;
- 4).设 k = k + 1 , α k = α , T k = T k=k+1,\alpha_k=\alpha,T_k=T k=k+1,αk=α,Tk=T(这里的 T k T_k Tk就是子树序列之一)
- 5).如果 T k T_k Tk不是由根节点及两个叶结点构成的树,则回到步骤2继续循环;否则,令 T n = T k T_n=T_k Tn=Tk
- 6).采用交叉验证法在子树序列 { T 0 , T 1 , . . . , T n } \{T_0,T_1,...,T_n\} {T0,T1,...,Tn}中选取最优子树 T α T_{\alpha} Tα。
5. 随机森林
随机森林算法步骤:
1).从原样本集中进行重采样(有重复的)选出n个样本;
2).从所有属性中随机选择s个属性,从s个属性中选择最佳分割属性作为节点建立CART决策树;
3).重复以上两步m次,即建立了m棵CART决策树;
4).这m个CART形成随机森林,通过投票表决结果,决定预测数据属于哪一类。
一般来说,SVM和Logistic回归也可以作随机森林的分类器,但是最好不要这么做,因为它们是强分类器,最后的分类效果可能并不大好。投票表决还有别的方式,可以参考“推荐系统”知识。