决策树算法原理及实现
引入:去不去相亲?
我们现实生活中经常见到自己或者其他人做许多决策:今天是否去打球?明天要不要逃课?家人介绍的相亲对象要不要去见?
我们以最后一个为例:
比如说小好妈妈对小好说:“我同事家一男孩儿还不错,你周末去见见。”
小好问:“他多大了?超过30我不见”
妈妈:“没有,和你同岁”
小好:“长得帅不帅?低于一般水平我不见”
妈妈:“长得可帅了,像古天乐呢!”
小好:“O(∩_∩)O哈哈~那他收入怎样?”
(PS.emmm…像古天乐肯定就去啦,但是,为了例子的完整性,还是要象征性的再问一个问题~)
妈妈:“一般般”
小好:“是公务员吗?”
妈妈:“是的”
小好:“那我去见~”
上述对话可用决策树表示为:
这就是决策树比较简单的表现形式,用树的形式更直观的展现决策流程。
可能有人会问:这我干嘛要做成树的形式,我不用树也可以清楚的知道结果。但是这是针对很小样本的情况,如果样本量很大,或者小好的要求很零散、很多,这时不用决策树很难一目了然的得到一般规律和结果。
这就是决策树算法存在的意义,那么决策树算法到底是什么?让我们来推开决策树的大门!
决策树(Decision Tree)
定义
决策树(Decision Tree),又称为判定树,是数据挖掘技术中的一种重要的分类方法,它是一种以树结构(包括二叉树和多叉树)形式来表达的预测分析模型。
决策树方法是一种比较通用的分类函数逼近法,它是一种常用于预测模型的算法,通过将大量数据有目的分类,找到一些有潜在价值的信息
。
具体用到的知识我们下一步说,先来看看决策树的构造。
决策树的构造
就像上图是否去相亲的决策树,其中绿色节点表示判断条件,橙色节点表示决策结果,箭头表示在一个判断条件在不同情况下的决策路径,图中红色箭头表示了上面例子中女孩的决策过程。
由上可知,决策树需要有内部节点:判别条件(年龄、长相、收入、是否是公务员);叶节点:决策结果(是否去相亲);分支:不同判别条件下的决策路径;而根节点就是树最顶层的节点,可以理解为最先的分裂属性,也是所有内部节点的父节点。
Note.什么是父子节点?
由上述图形,年龄节点是长相节点的父节点,也是根节点,子节点由父节点根据某分类规则得来。
决
策
树
的
树
结
构
{
根
节
点
内
部
节
点
叶
节
点
决策树的树结构\begin{cases}根节点\\内部节点\\叶节点\end{cases}
决策树的树结构⎩⎪⎨⎪⎧根节点内部节点叶节点
决策树算法原理
在介绍决策树算法原理之前,需要了解一点:决策树的构建准则是使信息量以最快的速度降低到0。
那么,什么是信息量?如何衡量信息量?
在信息论中,认为信源输出的消息是随机的。即在未收到消息之前,是不能肯定信源到底发送什么样的消息。而通信的目的也就是要使接收者在接收到消息后,尽可能多的解除接收者对信源所存在的疑义(不定度),因此这个被解除的不定度实际上就是在通信中所要传送的信息量。”
简而言之,信息量是用来描述信息的不确定程度。比如说,'太阳东升西落’这件事是必然事件,对于这种大家都已知的必然事件带来的信息量就为0,因为没有消除大家的任何疑虑,也就是说这个信息不存在任何不确定性程度的变动(因为他就是确定的,必然发生的)。
再比如:专业射击选手小王(成绩平均在9.0)和射击新手小明(成绩平均在5.0)分别进行射击,对于观众来说,小王射击这个事件的不确定性较小(通常在9.0附近),而小明射击的不确定性较大(可能时好时坏),所以可以认为小明射击事件的信息量更大。
那么信息量是用什么来衡量的呢?就像我们刚才举的例子,“信息的不确定程度的变化”,我们使用信息的不确定程度的降低来衡量信息量的大小。
由于上述的例子中,必然事件(概率为1)的信息量最小,为零。不确定性越大的事件(小明射击)的信息量较大。因此,信息量和概率有着必然的联系。
信息量的公式为:
h
(
x
)
=
−
l
o
g
2
p
(
x
)
h(x)=-log_2p(x)
h(x)=−log2p(x)
信息熵的公式为:
H
(
X
)
=
−
∑
i
N
p
i
(
x
i
)
l
o
g
(
p
i
(
x
i
)
)
H(X)=-\sum_i^N p_i(x_i)log(p_i(x_i))
H(X)=−∑iNpi(xi)log(pi(xi))
信息熵:信息对可能产生的信息量的期望——信息量的所有可能取值,即所有可能发生事件所带来的信息量的期望。
注:信息熵用来衡量事件不确定性。其值越大,不确定性越高。
回到这句话:决策树的构建准则是使信息量以最快的速度降低到0
可见,决策树的构建过程是一种优化思想:确定性增益最大化!(将‘不确定性’看做‘不纯度’,‘确定性’看做‘纯度’)即决策树构建要使纯度增益最大化。
综上可得,决策树的算法原理
:根据不纯度函数,使每一次选择分裂属性带来的数据不纯度下降最大(纯度增益最大化)。
那么,决策树算法的重点就到了不纯度函数
和分裂属性的选择
上。
决策树算法
根据决策树的发展史,经典算法的演变和发展分别为:ID3——>C4.5——>CART,本文主要介绍这三个算法。
对于不同方法的分裂属性的选择方法先总结至下表:
算法 | 分裂属性度量 |
---|---|
ID3 | 信息增益 |
C4.5 | 信息增益率 |
CART | 基尼系数 |
下面,我们根据一个例子,分别详细讲解ID3,C4.5,CART算法的分类过程。
例:根据日志密度,好友密度、是否使用真实头像、来判断账户是否真实,如下是10条数据(无实意)
日志密度 | 好友密度 | 是否使用真实头像 | 账户是否真实 |
---|---|---|---|
s | l | yes | yes |
m | l | no | yes |
l | m | yes | yes |
m | m | yes | yes |
l | m | yes | yes |
l | m | no | yes |
s | s | no | no |
m | s | no | no |
m | s | no | yes |
s | s | yes | no |
下面通过计算来深入了解每一个算法。
(1)ID3算法
1、原理介绍:若选择一个属性,使数据分类效果最好,其产生的信息增益最大。(因此,ID3算法以信息增益最大化来选择分裂属性)
对信息增益的理解——信息增益:若原数据信息熵为
I
0
I_0
I0,根据属性A划分后得到信息熵
I
1
I_1
I1,
I
2
I_2
I2;信息增益为:
I
0
−
(
I
1
+
I
2
)
I_0-(I_1+I_2)
I0−(I1+I2)
首先,介绍ID3算法的计算公式:
总信息熵:
H
(
D
)
=
−
∑
i
=
1
c
p
(
x
i
)
l
o
g
p
(
x
i
)
H(D)=-\sum^c_{i=1}p(x_i)logp(x_i)
H(D)=−i=1∑cp(xi)logp(xi)某属性分裂后的信息熵:
H
(
D
∣
分
裂
属
性
A
)
=
∑
j
=
1
m
∣
D
j
∣
∣
D
∣
∗
∑
i
=
1
c
p
(
x
i
)
l
o
g
p
(
x
i
)
H(D|分裂属性A)=\sum_{j=1}^m \frac{|D_j|}{|D|}*\sum^c_{i=1}p(x_i)logp(x_i)
H(D∣分裂属性A)=j=1∑m∣D∣∣Dj∣∗i=1∑cp(xi)logp(xi)信息增益:
g
a
i
n
(
分
裂
属
性
A
)
=
H
(
D
)
−
H
(
D
∣
分
裂
属
性
A
)
gain(分裂属性A)=H(D)-H(D|分裂属性A)
gain(分裂属性A)=H(D)−H(D∣分裂属性A)
2、案例计算,
信息熵的计算——
账户是否真实:
{
y
e
s
:
7
n
o
:
3
\begin{cases}yes:7\\no:3\end{cases}
{yes:7no:3
目标变量的信息熵:
H
(
D
)
=
−
7
10
l
o
g
2
7
10
−
3
10
l
o
g
2
3
10
=
0.8813
H(D)=-\frac{7}{10}log_2\frac{7}{10}-\frac{3}{10}log_2\frac{3}{10}=0.8813
H(D)=−107log2107−103log2103=0.8813
①日志密度:
H
(
D
∣
日
志
密
度
)
=
3
10
[
−
1
3
l
o
g
2
1
3
−
2
3
l
o
g
2
2
3
]
+
4
10
[
−
1
4
l
o
g
2
1
4
−
3
4
l
o
g
2
3
4
]
+
3
10
[
−
3
3
l
o
g
2
3
3
−
0
]
=
0.6
H(D|日志密度)=\frac{3}{10} [-\frac{1}{3}log_2 \frac{1}{3}-\frac{2}{3}log_2\frac{2}{3}]+\frac{4}{10} [-\frac{1}{4}log_2 \frac{1}{4}-\frac{3}{4}log_2\frac{3}{4}]+\frac{3}{10} [-\frac{3}{3}log_2 \frac{3}{3}-0]=0.6
H(D∣日志密度)=103[−31log231−32log232]+104[−41log241−43log243]+103[−33log233−0]=0.6
g
a
i
n
(
日
志
密
度
)
=
H
(
D
)
−
H
(
D
∣
日
志
密
度
)
=
0.8813
−
0.6
=
0.2813
gain(日志密度)=H(D)-H(D|日志密度)=0.8813-0.6=0.2813
gain(日志密度)=H(D)−H(D∣日志密度)=0.8813−0.6=0.2813
②好友密度:
H
(
D
∣
好
友
密
度
)
=
4
10
[
−
1
4
l
o
g
2
1
4
−
3
4
l
o
g
2
3
4
]
+
4
10
[
−
4
4
l
o
g
2
4
4
−
0
]
+
2
10
[
−
2
2
l
o
g
2
2
2
−
0
]
=
0.3245
H(D|好友密度)=\frac{4}{10} [-\frac{1}{4}log_2 \frac{1}{4}-\frac{3}{4}log_2\frac{3}{4}]+\frac{4}{10} [-\frac{4}{4}log_2 \frac{4}{4}-0]+\frac{2}{10} [-\frac{2}{2}log_2 \frac{2}{2}-0]=0.3245
H(D∣好友密度)=104[−41log241−43log243]+104[−44log244−0]+102[−22log222−0]=0.3245
g
a
i
n
(
好
友
密
度
)
=
H
(
D
)
−
H
(
D
∣
好
友
密
度
)
=
0.8813
−
0.3245
=
0.5568
gain(好友密度)=H(D)-H(D|好友密度)=0.8813-0.3245=0.5568
gain(好友密度)=H(D)−H(D∣好友密度)=0.8813−0.3245=0.5568
③是否使用真实头像:
H
(
D
∣
是
否
使
用
真
实
头
像
)
=
5
10
[
−
1
5
l
o
g
2
1
5
−
4
5
l
o
g
2
4
5
]
+
5
10
[
−
3
5
l
o
g
2
3
5
−
2
5
l
o
g
2
2
5
]
=
0.8464
H(D|是否使用真实头像)=\frac{5}{10} [-\frac{1}{5}log_2 \frac{1}{5}-\frac{4}{5}log_2\frac{4}{5}]+\frac{5}{10} [-\frac{3}{5}log_2 \frac{3}{5}-\frac{2}{5}log_2\frac{2}{5}]=0.8464
H(D∣是否使用真实头像)=105[−51log251−54log254]+105[−53log253−52log252]=0.8464
g
a
i
n
(
是
否
使
用
真
实
头
像
)
=
H
(
D
)
−
H
(
D
∣
是
否
使
用
真
实
头
像
)
=
0.8813
−
0.8464
=
0.0349
gain(是否使用真实头像)=H(D)-H(D|是否使用真实头像)=0.8813-0.8464=0.0349
gain(是否使用真实头像)=H(D)−H(D∣是否使用真实头像)=0.8813−0.8464=0.0349
g
a
i
n
(
好
友
密
度
)
>
g
a
i
n
(
日
志
密
度
)
>
g
a
i
n
(
是
否
使
用
真
实
头
像
)
gain(好友密度)>gain(日志密度)>gain(是否使用真实头像)
gain(好友密度)>gain(日志密度)>gain(是否使用真实头像)因此,首先选择好友密度作为分裂属性,后面步骤相同,本文略。
3、ID3算法缺陷
对于ID3算法,若我们将数据增加一列ID:1,2,3,4,5,6,7,8,9,10
此时,
H
(
D
∣
I
D
)
=
∑
j
=
1
m
∣
D
j
∣
∣
D
∣
∗
∑
i
=
1
c
p
(
x
i
)
l
o
g
p
(
x
i
)
=
1
10
[
−
1
1
l
o
g
2
1
1
−
0
]
+
.
.
.
+
1
10
[
−
1
1
l
o
g
2
1
1
−
0
]
]
=
0
H(D|ID)=\sum_{j=1}^m \frac{|D_j|}{|D|}*\sum^c_{i=1}p(x_i)logp(x_i)=\frac{1}{10} [-\frac{1}{1}log_2 \frac{1}{1}-0]+...+\frac{1}{10} [-\frac{1}{1}log_2 \frac{1}{1}-0]]=0
H(D∣ID)=j=1∑m∣D∣∣Dj∣∗i=1∑cp(xi)logp(xi)=101[−11log211−0]+...+101[−11log211−0]]=0
g
a
i
n
(
I
D
)
=
H
(
D
)
−
H
(
D
∣
I
D
)
=
0.8813
−
0
=
0.8813
gain(ID)=H(D)-H(D|ID)=0.8813-0=0.8813
gain(ID)=H(D)−H(D∣ID)=0.8813−0=0.8813此时信息增益总是最大的,而我们知道按照ID划分是没有意义的。由此,我们得出ID3算法的一个缺陷:偏向于选择多值属性!
为了解决这个问题,C4.5算法在其基础上做出了改进,选择分裂信息量来消除属性取值越多信息增益越大的缺陷。
(2)C4.5算法
1、算法原理:引入分裂信息熵splitInf来消除信息增益的计算缺陷(若一个属性的取值较多,会使Gain变大,splitinf也会越大,相互抵消。),选择信息增益率越大的属性作为分裂属性。
对信息增益率的理解——信息增益率:若原数据信息熵为
I
0
I_0
I0,根据属性A划分后得到信息熵
I
1
I_1
I1,
I
2
I_2
I2,计算得到每个划分的分裂信息熵
s
p
l
i
t
I
n
f
splitInf
splitInf;信息增益率为:
[
I
0
−
(
I
1
+
I
2
)
]
/
s
p
l
i
t
I
n
f
[I_0-(I_1+I_2)]/splitInf
[I0−(I1+I2)]/splitInf
首先,介绍C4.5算法的计算公式:
总信息熵:
H
(
D
)
=
−
∑
i
=
1
c
p
(
x
i
)
l
o
g
p
(
x
i
)
H(D)=-\sum^c_{i=1}p(x_i)logp(x_i)
H(D)=−i=1∑cp(xi)logp(xi)某属性分裂后的信息熵:
H
(
D
∣
分
裂
属
性
A
)
=
∑
j
=
1
m
∣
D
j
∣
∣
D
∣
∗
∑
i
=
1
c
p
(
x
i
)
l
o
g
p
(
x
i
)
H(D|分裂属性A)=\sum_{j=1}^m \frac{|D_j|}{|D|}*\sum^c_{i=1}p(x_i)logp(x_i)
H(D∣分裂属性A)=j=1∑m∣D∣∣Dj∣∗i=1∑cp(xi)logp(xi)某属性分裂后的分裂信息熵:
S
p
l
i
t
I
n
f
A
=
−
∑
j
=
1
m
∣
D
j
∣
∣
D
∣
l
o
g
2
∣
D
j
∣
∣
D
∣
SplitInf_A=-\sum_{j=1}^m\frac{|D_j|}{|D|}log_2\frac{|D_j|}{|D|}
SplitInfA=−j=1∑m∣D∣∣Dj∣log2∣D∣∣Dj∣信息增益率:
g
a
i
n
_
r
a
t
i
o
(
分
裂
属
性
A
)
=
g
a
i
n
(
分
裂
属
性
A
)
S
p
l
i
t
I
n
f
A
gain\_ratio(分裂属性A)=\frac{gain(分裂属性A)}{SplitInf_A}
gain_ratio(分裂属性A)=SplitInfAgain(分裂属性A)
2、案例计算
S
p
l
i
t
I
n
f
(
日
志
密
度
)
=
−
3
10
l
o
g
2
3
10
−
4
10
l
o
g
2
4
10
−
3
10
l
o
g
2
3
10
=
1.5709
SplitInf(日志密度)=-\frac{3}{10}log_2\frac{3}{10}-\frac{4}{10}log_2\frac{4}{10}-\frac{3}{10}log_2\frac{3}{10}=1.5709
SplitInf(日志密度)=−103log2103−104log2104−103log2103=1.5709
S
p
l
i
t
I
n
f
(
好
友
密
度
)
=
−
4
10
l
o
g
2
4
10
−
4
10
l
o
g
2
4
10
−
2
10
l
o
g
2
2
10
=
1.5219
SplitInf(好友密度)=-\frac{4}{10}log_2\frac{4}{10}-\frac{4}{10}log_2\frac{4}{10}-\frac{2}{10}log_2\frac{2}{10}=1.5219
SplitInf(好友密度)=−104log2104−104log2104−102log2102=1.5219
S
p
l
i
t
I
n
f
(
是
否
使
用
真
实
头
像
)
=
−
5
10
l
o
g
2
5
10
−
5
10
l
o
g
2
5
10
=
1
SplitInf(是否使用真实头像)=-\frac{5}{10}log_2\frac{5}{10}-\frac{5}{10}log_2\frac{5}{10}=1
SplitInf(是否使用真实头像)=−105log2105−105log2105=1
G
a
i
n
_
R
a
t
i
o
(
日
志
密
度
)
=
g
a
i
n
(
日
志
密
度
)
s
p
l
i
t
I
n
f
(
日
志
密
度
)
=
0.2813
1.5709
=
0.1791
Gain\_Ratio(日志密度)=\frac{gain(日志密度)}{splitInf(日志密度)}=\frac{0.2813}{1.5709}=0.1791
Gain_Ratio(日志密度)=splitInf(日志密度)gain(日志密度)=1.57090.2813=0.1791
G
a
i
n
_
R
a
t
i
o
(
好
友
密
度
)
=
g
a
i
n
(
好
友
密
度
)
s
p
l
i
t
I
n
f
(
好
友
密
度
)
=
0.5568
1.5219
=
0.3659
Gain\_Ratio(好友密度)=\frac{gain(好友密度)}{splitInf(好友密度)}=\frac{0.5568}{1.5219}=0.3659
Gain_Ratio(好友密度)=splitInf(好友密度)gain(好友密度)=1.52190.5568=0.3659
G
a
i
n
_
R
a
t
i
o
(
是
否
使
用
真
实
头
像
)
=
g
a
i
n
(
是
否
使
用
真
实
头
像
)
s
p
l
i
t
I
n
f
(
是
否
使
用
真
实
头
像
)
=
0.0349
1
=
0.0349
Gain\_Ratio(是否使用真实头像)=\frac{gain(是否使用真实头像)}{splitInf(是否使用真实头像)}=\frac{0.0349}{1}=0.0349
Gain_Ratio(是否使用真实头像)=splitInf(是否使用真实头像)gain(是否使用真实头像)=10.0349=0.0349
G
a
i
n
_
R
a
t
i
o
(
好
友
密
度
)
>
G
a
i
n
_
R
a
t
i
o
(
日
志
密
度
)
>
G
a
i
n
_
R
a
t
i
o
(
是
否
使
用
真
实
头
像
)
Gain\_Ratio(好友密度)>Gain\_Ratio(日志密度)>Gain\_Ratio(是否使用真实头像)
Gain_Ratio(好友密度)>Gain_Ratio(日志密度)>Gain_Ratio(是否使用真实头像)因此,首先选择好友密度作为分裂属性。
3、C4.5算法的优点
①解决了ID3算法偏向于多值属性的缺陷(引入
S
p
l
i
t
I
n
f
SplitInf
SplitInf)
②能够处理缺失值
对于上例,若日志密度存在缺失值如下:
日志密度 | 好友密度 | 是否使用真实头像 | 账户是否真实 |
---|---|---|---|
s | l | yes | yes |
m | l | no | yes |
l | m | yes | yes |
m | m | yes | yes |
l | m | yes | yes |
? | m | no | yes |
s | s | no | no |
m | s | no | no |
? | s | no | yes |
s | s | yes | no |
日志密度 | 分类:yes | 分类:no | 合计 |
---|---|---|---|
s | 1 | 2 | 3 |
m | 2 | 1 | 3 |
l | 2 | 0 | 2 |
S
t
e
p
1
′
Step1'
Step1′去除缺失值后此属性中各水平的比例
对任意未知的日志密度的值。取“s”的概率为3/8;取“m”的概率为3/8;取“l”的概率为2/8。
S
t
e
p
2
′
Step2'
Step2′按比例填充
S1:日志密度=s的数量——3+2*(3/8)
S2:日志密度=m的数量——3+2*(3/8)
S3:日志密度=l的数量——2+2*(2/8)
③能处理连续变量
C4.5算法处理连续属性的原理是:对不同的可能划分,分别计算所得的信息增益率,选择信息增益率最大的那个划分区间。
S
t
e
p
1
′
Step 1'
Step1′ 将属性取值排序,计算相邻值的中点
v
i
v_i
vi;
S
t
e
p
2
′
Step 2'
Step2′对其中每个取值
v
i
v_i
vi作为阈值 将数据集划分为两个部分;
S
t
e
p
3
′
Step 3'
Step3′ 计算每个分支的信息增益率;
S
t
e
p
4
′
Step 4'
Step4′ 选择最大信息增益的分支作为阈值,将数据分裂为离散型
PS.详情可见《数据挖掘导论》P99-P100
(3)CART算法(Classification and Regression Tree)
1、分类树
CART算法原理:使用二叉树将预测空间划分为若干子集,随着从根节点到叶节点的移动,每个节点选出最优的分支规则对应的划分区域,目标变量在该节点上的条件分布也随之被确定。
分类准则——基尼系数
首先,介绍CART算法的计算公式:
总Gini:
G
i
n
i
(
D
)
=
1
−
∑
i
=
1
c
p
(
x
i
)
2
Gini(D)=1-\sum^c_{i=1}p(x_i)^2
Gini(D)=1−i=1∑cp(xi)2 某属性分裂后的Gini:
G
i
n
i
(
D
∣
分
裂
属
性
A
)
=
∑
j
=
1
m
∣
D
j
∣
∣
D
∣
∗
G
i
n
i
(
D
j
)
Gini(D|分裂属性A)=\sum_{j=1}^m\frac{|D_j|}{|D|}*Gini(D_j)
Gini(D∣分裂属性A)=j=1∑m∣D∣∣Dj∣∗Gini(Dj) Gini增益:
Δ
G
i
n
i
(
D
∣
分
裂
属
性
A
)
=
G
i
n
i
(
D
)
−
G
i
n
i
(
D
∣
分
裂
属
性
A
)
\Delta Gini(D|分裂属性A)=Gini(D)-Gini(D|分裂属性A)
ΔGini(D∣分裂属性A)=Gini(D)−Gini(D∣分裂属性A)
以是否使用真实头像为例:
G
i
n
i
(
是
否
使
用
真
实
头
像
)
=
5
10
∗
(
1
−
(
4
5
)
2
−
(
1
5
)
2
)
+
5
10
∗
(
1
−
(
3
5
)
2
−
(
2
5
)
2
)
Gini(是否使用真实头像)=\frac{5}{10}* (1-(\frac{4}{5})^2-(\frac{1}{5})^2 )+\frac{5}{10}* (1-(\frac{3}{5})^2-(\frac{2}{5})^2 )
Gini(是否使用真实头像)=105∗(1−(54)2−(51)2)+105∗(1−(53)2−(52)2) 样本分布均匀时Gini指标最大;分类越纯Gini越小。选择Gini系数增益最大的变量最为分类属性。
2、回归树
分类准则:最小方差原理
①基于树的方法:将特征空间划分成一系列长方形,然后对每个长方形拟合简单的模型(常数)
拟合的模型为:
f
^
(
x
)
=
∑
(
m
=
1
)
5
c
m
I
{
X
1
,
X
2
∈
R
m
}
\hat f(x)=\sum_{(m=1)}^5c_m I\{X_1,X_2∈R_m\}
f^(x)=(m=1)∑5cmI{X1,X2∈Rm} ②回归树的分裂准则——最小方差法
对每个变量、根据不同的分割点计算二叉树两边分裂的数值均值,计算其方差,方差最小的分裂点为其最终分裂点,各个变量方差值对比,选择最小方差的变量作为分裂属性。
回归树的生成计算请戳☞[传送门]☜
决策树剪枝
决 策 树 剪 枝 方 法 { 预 剪 枝 : 在 树 完 全 生 长 之 前 停 止 部 分 分 裂 后 剪 枝 : 在 树 完 全 生 长 之 后 减 去 部 分 枝 丫 决策树剪枝方法\begin{cases}预剪枝:在树完全生长之前停止部分分裂\\后剪枝:在树完全生长之后减去部分枝丫\end{cases} 决策树剪枝方法{预剪枝:在树完全生长之前停止部分分裂后剪枝:在树完全生长之后减去部分枝丫
预剪枝(Pre-Pruning)
①若节点中所有观测属于一类[没必要再分],停止划分
②若树的深度达到预定阈值,停止划分
③若该节点所含观测值小于设定父节点应含观测值的阈值,停止划分
④若该节点子节点所含观测数小于设定阈值,停止划分
⑤若没有属性满足设定的分裂准则的阈值[纯度增加量不够],停止划分
后剪枝(Post-Pruning)
以CCP(Cost Complexity Pruning)为例——
CCP剪枝:选择节点表面误差率增益值最小的非叶子节点,删除该非叶子节点的左右子节点,若有多个非叶子节点的表面误差率增益值相同小,则选择非叶子节点中子节点数最多的非叶子节点进行剪枝。
CCP剪枝的步骤:
1)从原始的决策树开始生成一个子树序列(均非叶子节点)
{
T
0
,
T
1
,
…
,
T
n
}
\{T_0,T_1,…,T_n \}
{T0,T1,…,Tn},其中
T
(
i
+
1
)
T_{(i+1)}
T(i+1) 从
T
i
T_i
Ti 产生,
T
n
T_n
Tn 为根节点
2)计算所有节点的误差率增益值,选择误差率增益值最小的非叶子节点
3)对选中节点进行剪枝
4)重复
误差率增益值的计算公式为:
α
=
R
(
t
)
−
R
(
T
)
N
(
T
)
−
1
\alpha=\frac{R(t)-R(T)}{N(T)-1}
α=N(T)−1R(t)−R(T) ((非叶节点误差-叶节点误差)/(叶节点数-1))
其中,
-
α 衡量的是每个节点所能减少的分类误差率。α越小,说明该节点所能减少的分类误差率越小,继续往下分类意义不大,可以剪枝,将该结点作为叶结点。
-
R(t)-表示非叶子节点的误差代价,R(t)=r(t)*p(t), r(t)为该节点的错误率, p(t) 为节点的数据量占比
-
R(T)-表示子树叶子节点的误差代价, R ( T ) = ∑ ( i = 1 ) m r i ( t ) p i ( t ) R(T)=\sum_{(i=1)}^mr_i (t) p_i (t) R(T)=∑(i=1)mri(t)pi(t), r i ( t ) r_i (t) ri(t)
为子节点i的错误率, p i ( t ) p_i (t) pi(t) 表示节点i的数据量占比 -
N(T)-表示子树的叶结点个数
eg.
总样本量:55+25=80
① 对t4节点,
错误占比: 4 46 + 4 \frac{4}{46+4} 46+44
R ( t ) = r ( t ) ∗ p ( t ) R(t)=r(t)*p(t) R(t)=r(t)∗p(t),t4错误率占所有观测的占比情况: R ( t 4 ) = 4 50 ∗ 50 80 = 1 20 R(t4)=\frac{4}{50}*\frac{50}{80}=\frac{1}{20} R(t4)=504∗8050=201
R ( T ) = ∑ ( i = 1 ) m r i ( t ) p i ( t ) R(T)=\sum^m_{(i=1)} r_i (t) p_i (t) R(T)=∑(i=1)mri(t)pi(t),
t8和t9叶节点错误率: R ( T 4 ) = 1 45 ∗ 45 80 + 2 5 ∗ 5 80 = 3 80 R(T4)=\frac{1}{45}*\frac{45}{80}+\frac{2}{5}*\frac{5}{80}=\frac{3}{80} R(T4)=451∗8045+52∗805=803 (N(t)=2,两个叶节点)
CCP误差为: α = R ( t ) − R ( T ) N ( T ) − 1 = 1 20 − 3 80 2 − 1 = 0.0125 α=\frac{R(t)-R(T)}{N(T)-1}=\frac{\frac{1}{20}-\frac{3}{80}}{2-1}=0.0125 α=N(T)−1R(t)−R(T)=2−1201−803=0.0125
② 对于非叶子节点t3的子树
节点错误率: 5 15 + 5 \frac{5}{15+5} 15+55
t3节点错误占比: R ( t 3 ) = 5 20 ∗ 20 80 = 1 16 R(t3)=\frac{5}{20}*\frac{20}{80}=\frac{1}{16} R(t3)=205∗8020=161
t6,t7的错误率: R ( T 3 ) = 1 5 ∗ 5 80 + 1 15 ∗ 15 80 = 1 40 R(T3)=\frac{1}{5}*\frac{5}{80}+\frac{1}{15}*\frac{15}{80}=\frac{1}{40} R(T3)=51∗805+151∗8015=401 (N(t)=2,两个叶节点)
CCP误差为: α = R ( t ) − R ( T ) N ( T ) − 1 = 1 16 − 1 40 2 − 1 = 0.0375 α=\frac{R(t)-R(T)}{N(T)-1}=\frac{\frac{1}{16}-\frac{1}{40}}{2-1}=0.0375 α=N(T)−1R(t)−R(T)=2−1161−401=0.0375
③ 对于非叶子节点t2的子树,
节点误差占比: R ( t ) = r ( t ) ∗ p ( t ) = 10 60 ∗ 60 80 = 1 8 R(t)=r(t)*p(t)=\frac{10}{60}*\frac{60}{80}=\frac{1}{8} R(t)=r(t)∗p(t)=6010∗8060=81
对应叶子节点误差率: R ( T ) = ∑ ( i = 1 ) m r i ( t ) ∗ p i ( t ) = 1 45 ∗ 45 80 + 2 5 ∗ 5 80 + 0 6 ∗ 6 80 + 0 4 ∗ 4 80 = 3 80 R(T)=\sum_{(i=1)}^m r_i (t)*p_i (t)=\frac{1}{45}*\frac{45}{80}+\frac{2}{5}*\frac{5}{80}+\frac{0}{6}*\frac{6}{80}+\frac{0}{4}*\frac{4}{80}=\frac{3}{80} R(T)=∑(i=1)mri(t)∗pi(t)=451∗8045+52∗805+60∗806+40∗804=803,N(T)=4
CCP误差为: α = R ( t ) − R ( T ) ( N ( T ) − 1 = 1 8 − 3 80 4 − 1 = 0.0292 α=\frac{R(t)-R(T)}{(N(T)-1}=\frac{\frac{1}{8}-\frac{3}{80}}{4-1}=0.0292 α=(N(T)−1R(t)−R(T)=4−181−803=0.0292 关于上面决策树的所有节点的α值计算结果为:(自下而上剪枝)
T 0 : α ( t 4 ) = 0.0125 α ( t 5 ) = 0.05 α ( t 2 ) = 0.0292 α ( t 3 ) = 0.0375 T_0: α(t4)=0.0125 α(t5)=0.05 α(t2)=0.0292 α(t3)=0.0375 T0:α(t4)=0.0125α(t5)=0.05α(t2)=0.0292α(t3)=0.0375(减去t4枝叶变为叶节点)
T 1 : α ( t 5 ) = 0.05 α ( t 2 ) = 0.0375 α ( t 3 ) = 0.0375 T_1:α(t5)=0.05 α(t2)=0.0375 α(t3)=0.0375 T1:α(t5)=0.05α(t2)=0.0375α(t3)=0.0375(t2与t3的α 值相同,但是裁剪掉前者可以得到更小的决策树,减去t2变为叶节点)
以上就是CCP代价复杂度剪枝的全过程。
决策树的Python实现
例子依然采用上述手算例:
日志密度 | 好友密度 | 是否使用真实头像 | 账户是否真实 |
---|---|---|---|
s | l | yes | yes |
m | l | no | yes |
l | m | yes | yes |
m | m | yes | yes |
l | m | yes | yes |
l | m | no | yes |
s | s | no | no |
m | s | no | no |
m | s | no | yes |
s | s | yes | no |
1、导入需要的包
import pandas as pd
import numpy as np
from sklearn import tree
from sklearn.preprocessing import LabelEncoder
2、读入数据
data = pd.read_csv('data/example.csv',engine='python')
data
3、数据处理
# 多值型分类变量转化
x1 = pd.get_dummies(pd.DataFrame(data['日志密度'].values.tolist()),prefix='日志密度',prefix_sep='_',drop_first=True).\
groupby(axis=1,level=0).max()
x2 = pd.get_dummies(pd.DataFrame(data['好友密度'].values.tolist()),prefix='好友密度',prefix_sep='_',drop_first=True).\
groupby(axis=1,level=0).max()
del data['日志密度']
del data['好友密度']
data = pd.concat([data,x1,x2],axis=1)
data
# 二值型变量转化
data['是否使用真实头像'] = LabelEncoder().fit_transform(np.array(data['是否使用真实头像']))
data['账户是否真实'] = LabelEncoder().fit_transform(np.array(data['账户是否真实']))
4、数据转化
y = data['账户是否真实']
x = data.drop(['账户是否真实'],axis=1)
5、建模
tree_model = tree.DecisionTreeClassifier(criterion='gini')
tree_model.fit(x,y)
6、画决策树
import graphviz
dot_data = tree.export_graphviz(tree_model,
out_file=None,
feature_names= ['是否使用真实头像', '日志密度_m', '日志密度_s', '好友密度_m', '好友密度_s'],
class_names= ['no','yes'],
filled=True,
rounded=True,
special_characters=True)
graph = graphviz.Source(dot_data)
graph
得到如下图:
可见,和上述手算例得到相同结果!
决策树在真实数据集上的R语言和python实现及其调参结果请戳☞决策树的R与PYTHON调参对比☜