CART算法
分类与回归树(CART)是应用广泛的算法,同样由特征选择、树的生成及剪枝组成,可以用于解决分类和回归问题。
ID3算法、C4.5算法分别使用了信息增益、信息增益比来选择特征,他们都使用了包含大量的对数运算的熵模型来计算样本纯度。而CART算法使用基尼系数来代替信息增益(比),基尼系数代表了模型的不纯度,基尼系数越小,则不纯度越低,特征越好。这和信息增益(比)是相反的。
CART决策树的生成过程是递归构建二叉树的过程。对于分类树,使用基尼指数最小化准则;对回归树,使用平方误差最小化准则。
CART回归树生成
构建回归树有两个问题:
(1) 如何得到预测结果?
(2) 如何对输入空间进行划分?
一颗回归树是输入空间的一个划分,以及在划分单元的输出值。假设输入空间已经划分为M个:
R
1
,
R
2
,
.
.
.
,
R
M
R_1, R_2, ..., R_M
R1,R2,...,RM,并且在每个单元
R
m
R_m
Rm有一个固定的输出值
c
m
c_m
cm,于是回归树模型可表示为:
f
(
x
)
=
∑
m
=
1
M
c
m
I
(
x
∈
R
m
)
f(x) = \sum_{m=1}^{M} c_m I(x \in R_m)
f(x)=m=1∑McmI(x∈Rm)
可以用平方误差
∑
x
i
∈
R
m
(
y
i
−
f
(
x
i
)
)
2
\sum_{x_i \in R_m} (y_i - f(x_i))^2
∑xi∈Rm(yi−f(xi))2来表示回归树的预测误差,用平方误差最小的准则求解每个单元的最优输出值。
对于第一个问题,单元
R
m
R_m
Rm上的
c
m
c_m
cm的最优值
c
^
m
\hat c_m
c^m是
R
m
R_m
Rm上所有输入实例
x
i
x_i
xi对应的输出
y
i
y_i
yi的均值,即:
c
^
m
=
a
v
e
(
y
i
∣
x
i
∈
R
m
)
\hat{c}_m = ave(y_i \ | \ x_i \in R_m)
c^m=ave(yi ∣ xi∈Rm)
那么如何对输入空间进行划分?可以采用启发式的方法,选择样本x的第j个特征
x
(
j
)
x^{(j)}
x(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)} \leqslant s\}\\ \ R_2(j, s) = \{x \ | \ x^{(j)} > s\}
R1(j,s)={x ∣ x(j)⩽s} R2(j,s)={x ∣ x(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_{j, s} \ [ \min_{c_1} \sum_{x_i \in R_1(j,s)} (y_i - c_1)^2 + \min_{c_2} \sum_{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]
其中,
c
1
c_1
c1为R1数据集的样本输出均值,
c
2
c_2
c2为R2数据集的样本输出均值:
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
)
)
\hat{c}_1 = ave( y_i \ | \ x_i \in R_1(j, s)), \ \hat{c}_2 = ave( y_i \ | \ x_i \in R_2(j, s))
c^1=ave(yi ∣ xi∈R1(j,s)), c^2=ave(yi ∣ xi∈R2(j,s))
遍历所有输入变量,找到最优的切分变量 j,构成一个对(j,s)。依次将输入空间划分为两个区域。对每个区域重复上述划分过程,直到满足停止条件位置,这样的回归树通常称为最小二乘回归树,算法叙述如下:
输入:训练数据集 D D D
输出:回归树 f ( x ) f(x) f(x)
步骤:
-
遍历变量 j j j,对固定的切分变 量 j j j 扫描切分点 s s 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}\left[\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\right] j,smin⎣⎡c1minxi∈R1(j,s)∑(yi−c1)2+c2minxi∈R2(j,s)∑(yi−c2)2⎦⎤ -
用选定的 ( j , s ) (j,s) (j,s), 划分区域并决定相应的输出值
R 1 ( j , s ) = { x ∣ x ( j ) ≤ s } , R 2 ( j , s ) = { x ∣ x ( j ) > s } c ^ m = 1 N ∑ x i ∈ R m ( j , s ) y j , x ∈ R m , m = 1 , 2 R_1(j,s)=\{x|x^{(j)}\leq s\}, R_2(j,s)=\{x|x^{(j)}> s\} \\ \hat{c}_m= \frac{1}{N}\sum\limits_{x_i\in R_m(j,s)} y_j, x\in R_m, m=1,2 R1(j,s)={x∣x(j)≤s},R2(j,s)={x∣x(j)>s}c^m=N1xi∈Rm(j,s)∑yj,x∈Rm,m=1,2 -
对两个子区域调用(1)(2)步骤, 直至满足停止条件
-
将输入空间划分为 M M M个区域 R 1 , R 2 , … , R M R_1, R_2,\dots,R_M R1,R2,…,RM,生成决策树:
f ( x ) = ∑ m = 1 M c ^ m I ( x ∈ R m ) f(x)=\sum_{m=1}^M\hat{c}_mI(x\in R_m) f(x)=m=1∑Mc^mI(x∈Rm)
CART分类树的生成
分类树使用基尼指数选择最优特征,同时决定该特征的最优二值切分点。
假设有K个类,样本点属于k类的概率为
p
k
p_k
pk,则概率分布的基尼指数定义为:
G
i
n
i
(
p
)
=
∑
k
=
1
K
p
k
(
1
−
p
k
)
=
1
−
∑
k
=
1
K
p
k
2
Gini(p) = \sum_{k=1}^{K}p_k (1 - p_k) = 1 - \sum_{k=1}^{K} {p_k}^2
Gini(p)=k=1∑Kpk(1−pk)=1−k=1∑Kpk2
对于二分类问题:
G
i
n
i
(
p
)
=
2
p
(
1
−
p
)
Gini(p) = 2p(1-p)
Gini(p)=2p(1−p)
对于给定样本集合D,其基尼指数为:
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
如果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)
Gini值越大,样本集合的不确定性也越大(与熵类似),因此每次选择Gini小的特征来划分。
连续值处理:
CART分类树对连续值的处理思路和C4.5是相同的,都是将连续的特征离散化。
具体来说,假设有m个样本,都包含连续特征A,特征A的取值从小到大排序后用: a 1 , a 2 , . . . , a m {a_1,a_2,...,a_m} a1,a2,...,am表示,则CART算法取相邻两样本值的平均数,一共取得m-1个划分点,其中第i个划分点 T i T_i Ti表示为: T i = a i + a i + 1 2 T_i = \frac{a_i+a_{i+1}}{2} Ti=2ai+ai+1。对于这m-1个点,分别计算以该点作为二元分类点时的基尼系数。选择基尼系数最小的点作为该连续特征的二元离散分类点。比如取到的基尼系数最小的点为 a t a_t at,则小于 a t a_{t} at的值为类别1,大于 a t a_{t} at的值为类别2,这样我们就做到了连续特征的离散化。要注意的是,与ID3或者C4.5处理离散属性不同的是,如果当前节点为连续属性,则该属性后面还可以参与子节点的产生选择过程。
离散值处理:
如果某个特征A被选取建立决策树节点,如果它有A1,A2,A3三种类别,我们会在决策树上一下建立一个三叉的节点。这样导致决策树是多叉树。但是CART分类树使用的方法不同,他采用的是不停的二分,还是这个例子,CART分类树会考虑把A分成{A1}和{A2,A3},{A2}和{A1,A3} {A3}和{A1,A2}三种情况,找到基尼系数最小的组合,比如{A2}和{A1,A3},然后建立二叉树节点,一个节点是A2对应的样本,另一个节点是{A1,A3}对应的节点。同时,由于这次没有把特征A的取值完全分开,后面我们还有机会在子节点继续选择到特征A来划分A1和A3。这和ID3或者C4.5不同,在ID3或者C4.5的一棵子树中,离散特征只会参与一次节点的建立。
结合上面的知识,总结得到算法流程如下:
输入:训练数据集D,基尼系数的阈值,样本个数阈值。
输出:决策树T。
根据训练数据集,从根结点开始,递归地对每个结点进行以下操作,构建二叉决策树:
-
设结点的训练数据集为D,计算现有特征对该数据集的基尼指数。此时,对每一个特征A,对其可能取的每个值a,根据样本点对A=a的测试为“是"或“否”,将D分割成 D 1 D_1 D1和 D 2 D_2 D2两部分,计算 A = a A=a A=a时的基尼指数。
-
在所有可能的特征A以及它们所有可能的切分点a中,选择基尼指数最小的特征及其对应的切分点作为最优特征与最优切分点。依最优特征与最优切分点,从现结点生成两个子结点,将训练数据集依特征分配到两个子结点中去。
-
对两个子结点递归地调用(1),,(2),直至满足停止条件。
-
生成CART决策树。
算法停止计算的条件是结点中的样本个数小于预定阈值,或样本集的基尼指数小于预定阈值(样本基本属于同-类),或者没有更多特征。
对于生成的决策树做预测的时候,假如测试集里的样本A落到了某个叶子节点,而节点里有多个训练样本,则对于A的类别预测采用的是这个叶子节点里概率最大的类别。
举个同样的例子:
分别用
A
1
,
A
2
,
A
3
,
A
4
A_1,A_2,A_3,A_4
A1,A2,A3,A4表示年龄、有工作、有房子、贷款情况4个特征,则有:
G
i
n
i
(
D
,
A
1
=
1
)
=
5
15
(
2
×
2
5
×
(
1
−
2
5
)
)
+
10
15
(
2
×
7
10
×
(
1
−
7
10
)
)
=
0.44
G
i
n
i
(
D
,
A
1
=
2
)
=
0.48
G
i
n
i
(
D
,
A
1
=
3
)
=
0.44
\begin{aligned} & Gini(D,A_1=1)=\frac{5}{15}(2 \times \frac{2}{5} \times (1-\frac{2}{5})) + \frac{10}{15}(2 \times \frac{7}{10} \times (1-\frac{7}{10})) = 0.44 \\ & Gini(D,A_1=2)=0.48\\ & Gini(D,A_1=3)=0.44 \end{aligned}
Gini(D,A1=1)=155(2×52×(1−52))+1510(2×107×(1−107))=0.44Gini(D,A1=2)=0.48Gini(D,A1=3)=0.44
由于
G
i
n
i
(
D
,
A
1
=
1
)
Gini(D,A_1=1)
Gini(D,A1=1)和
G
i
n
i
(
D
,
A
1
=
3
)
Gini(D,A_1=3)
Gini(D,A1=3)最小且相等,所以
A
1
,
A
3
A_1, A_3
A1,A3都可以作为最优切分点。同理可以得到
A
2
,
A
3
A_2,A_3
A2,A3的基尼指数:
G
i
n
i
(
D
,
A
2
=
1
)
=
0.32
G
i
n
i
(
D
,
A
3
=
1
)
=
0.27
Gini(D,A_2=1) = 0.32 \\ Gini(D,A_3=1) = 0.27
Gini(D,A2=1)=0.32Gini(D,A3=1)=0.27
由于
A
2
,
A
3
A_2,A_3
A2,A3只有一个切分点,所以基尼指数最小的即为对应特征的最优切分点。
A
4
A_4
A4的基尼指数:
G
i
n
i
(
D
,
A
4
=
1
)
=
0.36
G
i
n
i
(
D
,
A
4
=
2
)
=
0.47
G
i
n
i
(
D
,
A
4
=
3
)
=
0.32
Gini(D,A_4=1) = 0.36 \\ Gini(D,A_4=2) = 0.47\\ Gini(D,A_4=3) = 0.32
Gini(D,A4=1)=0.36Gini(D,A4=2)=0.47Gini(D,A4=3)=0.32
G
i
n
i
(
D
,
A
4
=
3
)
Gini(D,A_4=3)
Gini(D,A4=3)最小,所以
A
4
=
3
A_4=3
A4=3为
A
4
A_4
A4的最优切分点。
A 1 , A 2 , A 3 , A 4 A_1,A_2,A_3,A_4 A1,A2,A3,A4的特征中, G i n i ( D , A 3 = 1 ) = 0.27 Gini(D,A_3=1)=0.27 Gini(D,A3=1)=0.27最小,所以选择 A 3 A_3 A3为最优特征, A 3 = 1 A_3=1 A3=1为最优切分点,于是生成了两个子节点。左子节点是叶节点,右子节点则需要继续在 A 1 , A 2 , A 4 A_1,A_2,A_4 A1,A2,A4中选择最优切分点,如此往复,知道所以节点都是叶节点。
CART 剪枝
CART回归树和CART分类树的剪枝策略除了在度量损失的时候一个使用均方差,一个使用基尼系数,算法基本完全一样,这里我们一起来讲。
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 1 , . . . , T n T_0,T_1,...,T_n T0,T1,...,Tn}。 T 0 T_0 T0好理解,就是未经剪枝的决策树, T 1 T_1 T1怎么来的?
T
1
T_1
T1是
T
0
T_0
T0的子树,意味着子树
T
1
T_1
T1的损失函数至少要≤剪枝前
T
0
T_0
T0的损失函数(剪枝前后损失函数不变,但剪枝后复杂度降低,亦可以剪枝)。CART树T剪枝时,子树T的损失函数如下:
C
α
(
T
)
=
C
(
T
)
+
α
∣
T
∣
C_{\alpha}(T) = C(T) + \alpha |T|
Cα(T)=C(T)+α∣T∣
其中,
C
(
T
)
C(T)
C(T)为训练数据的预测误差,对回归而言可以是平方误差和,对分类而言可以是
s
u
m
(
每
个
叶
子
节
点
的
g
i
n
i
值
×
叶
子
节
点
样
本
数
目
)
sum(每个叶子节点的gini 值\times叶子节点样本数目)
sum(每个叶子节点的gini值×叶子节点样本数目)。
当α=0时,损失函数等于预测误差,相当于不进行剪枝,对应的最优子树即决策树本身;α越大,则惩罚越大,会得到更加简单的树,即剪枝幅度更大;
由于树的叶子个数是离散值,所以给定α后,必定存在某个子树 T α T_\alpha Tα使得损失函数 C α ( T ) C_{\alpha}(T) Cα(T)取得最小值。于是只要确定序列{ α 0 , α 1 , . . . , α n α_0,α_1,...,α_n α0,α1,...,αn}就能确定对应的最佳子树序列{ T 0 , T 1 , . . . , T n T_0,T_1,...,T_n T0,T1,...,Tn}。因此,目标为找到合适的α序列的构造。
我们将α序构造为递增的序列,则子树序列T是满树到根节点树的递减树序列。首先令 α 0 = 0 α_0=0 α0=0,决策树本身为 T 0 T_0 T0,在 T 0 T_0 T0上进行第一次剪枝(构造 α 1 α_1 α1),由于剪枝后的损失函数要≤剪枝前,因此,如果想在内部节点t处剪枝(即只保留节点t,左右子树删除),只需要将问题聚焦于节点t以及t节点对应的子树 T t T_t Tt上。
若在节点t处需要剪枝,则剪枝后的t变为了叶节点,对应的损失函数为:
C
α
(
t
)
=
C
(
t
)
+
α
×
1
(1)
C_\alpha(t) = C(t) + \alpha \times 1 \tag 1
Cα(t)=C(t)+α×1(1)
若不进行剪枝,则t及其子树
T
t
T_t
Tt的损失函数为:
C
α
(
T
t
)
=
C
(
T
t
)
+
α
∣
T
t
∣
(2)
C_\alpha(T_t) = C(T_t) + \alpha | T_t | \tag 2
Cα(Tt)=C(Tt)+α∣Tt∣(2)
由于剪枝是为了降低损失函数或者简化树模型,于是有:
C
α
(
T
t
)
≤
C
α
(
t
)
C_\alpha(T_t) \le C_\alpha(t)
Cα(Tt)≤Cα(t)
将式子(1)、(2)代入得到:
C
(
t
)
+
α
≤
C
(
T
t
)
+
α
∣
T
t
∣
(2)
C(t) + \alpha \le C(T_t) + \alpha | T_t | \tag 2
C(t)+α≤C(Tt)+α∣Tt∣(2)
解得:
α
≥
C
(
t
)
−
C
(
T
t
)
∣
T
t
∣
−
1
\alpha \ge \frac{C(t) - C(T_t)}{|T_t| - 1}
α≥∣Tt∣−1C(t)−C(Tt)
即当
α
∈
[
0
,
C
(
t
)
−
C
(
T
t
)
∣
T
t
∣
−
1
)
\alpha \in [0, \frac{C(t) - C(T_t)}{|T_t| - 1})
α∈[0,∣Tt∣−1C(t)−C(Tt))时,不满足剪枝条件,若要满足剪枝条件,至少有
α
m
i
n
=
C
(
t
)
−
C
(
T
t
)
∣
T
t
∣
−
1
\alpha_{min} = \frac{C(t) - C(T_t)}{|T_t| - 1}
αmin=∣Tt∣−1C(t)−C(Tt),此时虽然损失函数没有减少,但是可以简化决策树,达到了剪枝的条件。我们记:
g
(
t
)
=
α
m
i
n
=
C
(
t
)
−
C
(
T
t
)
∣
T
t
∣
−
1
g(t) =\alpha_{min} = \frac{C(t) - C(T_t)}{|T_t| - 1}
g(t)=αmin=∣Tt∣−1C(t)−C(Tt)
对于一颗要剪枝的树,自下而上地对内部每个内部节点 t 计算
g
(
t
)
g(t)
g(t),然后减去
g
(
t
)
g(t)
g(t)取值最小的
T
t
T_t
Tt,将得到的子树作为
T
1
T_1
T1。为什么取最小的
g
(
t
)
g(t)
g(t),是因为要保证
α
\alpha
α序列是递增的,每次取最小的
α
m
i
n
\alpha_{min}
αmin可以保证不遗漏任何可以剪枝的情况。每次得到
α
m
i
n
\alpha_{min}
αmin的同时,
T
t
T_t
Tt也随之得到了,于是可以同时得到序列{
α
0
,
α
1
,
.
.
.
,
α
n
α_0,α_1,...,α_n
α0,α1,...,αn}和{
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}之后,再将每棵树进行交叉验证,交叉验证结果最好的那颗子树便是最终的剪枝结果。
CART剪枝算法流程如下:
输入: CART算法生成的决策树 T 0 T_0 T0
输出: 最优决策树 T α T_α Tα
(1) 设 k = 0 , T = T 0 k=0, T=T_0 k=0,T=T0
(2) 设 α = + ∞ α= +∞ α=+∞。.
(3) 自下而上地对各内部结点 t 计算
C
(
T
t
)
,
∣
T
t
∣
C(T_t), |T_t|
C(Tt),∣Tt∣以及
g
(
t
)
=
C
(
t
)
−
C
(
T
t
)
∣
T
t
∣
−
1
α
=
m
i
n
(
α
,
g
(
t
)
)
g(t) = \frac{C(t) - C(T_t)}{|T_t| - 1} \\ α = min(α, g(t))
g(t)=∣Tt∣−1C(t)−C(Tt)α=min(α,g(t))
这里, T t T_t Tt表示以t为根结点的子树, C ( T t ) C(T_t) C(Tt)是对训练数据的预测误差, ∣ T t ∣ |T_t| ∣Tt∣ 是 T t T_t Tt的叶结点个数。
(4) 对 g ( t ) = α g(t)=\alpha g(t)=α的内部结点t进行剪枝,并对叶结点t以多数表决法决定其类,得到树T。
(5) 设 k = k + 1 , α k = α , T k = T k=k+1, \alpha_k=\alpha, T_k= T k=k+1,αk=α,Tk=T
(6) 如果 T k T_k Tk不是由根结点及两个叶结点构成的树,则回到步骤(2); 否则令 T k = T n T_k= T_n Tk=Tn。
(7) 采用交叉验证法在子树序列{ T 0 , T 1 , . . . , T n T_0,T_1,...,T_n T0,T1,...,Tn}中选取最优子树 T α T_{\alpha} Tα
参考文章:
《统计学习方法 第二版》