决策树
1 什么是决策树
生活中我们经常会遇到需要进行决策的事情,而在得到最终决定的过程中,我们通过一些策略或方法来进行判断,并不断思考,最终得到一个判断或结论。
决策树是一种树形结构,可以把我们进行决策的过程直观表示出来。从根结点出发,自上而下,对样本数据进行分类,其中内部结点表示一个特征或属性,叶结点代表着最终样本被归到的某一个类别。
1.1 栗子
假设HR筛选简历以年龄(中年、青年)、学历(本科、研究生、博士)、工作经验(无、0~3年、3年以上)、写代码(会、不会)来决定是否面试。
根据以上这个假设,对于ABCDE五份简历,可以得到如下表格:
年龄 | 学历 | 工作经验 | 写代码 | 类别 | |
---|---|---|---|---|---|
A | 中年 | 博士 | 3年以上 | 不会 | 不通过 |
B | 青年 | 本科 | 0~3年 | 会 | 通过 |
C | 青年 | 研究生 | 3年以上 | 不会 | 不通过 |
D | 青年 | 本科 | 3年以上 | 会 | 通过 |
E | 青年 | 本科 | 无 | 不会 | 不通过 |
那么由这个表格我们要如何构建决策树呢?选取最优的决策树显然是一个NP难问题,实际的学习算法基于启发式算法。
2 信息熵
高中化学自发反应学到过熵和熵变,所以熵(entropy)是描述体系混乱程度的物理量这点不难理解。而信息论里的熵是对不确定性的测量,跟混乱程度感觉上异曲同工。
2.1 定义
香农定义信息熵为离散随机事件的出现概率。所以一个系统越有序,信息熵就越低,反之越高。
如果一个随机变量 X X X 的可能取值有{ x 1 , x 1 , . . . , x k x_1,x_1,...,x_k x1,x1,...,xk},对应的概率分布为 P ( X = x i ) = p i ( i = 1 , 2 , . . . , k ) P(X=x_i)=p_i \ \ \text (i=1,2,...,k) P(X=xi)=pi (i=1,2,...,k) ,则 X X X 的信息熵为:
H
(
X
)
=
−
∑
x
∈
X
p
(
x
)
log
p
(
x
)
H(X) = -\sum_{x\in X}p(x)\log p(x)
H(X)=−x∈X∑p(x)logp(x)
e.g.
假设对于一个数据集,样本标签分为{A,B,C,D}四个类别,每种类别的数据占比为{1\3,1\9,1\3,2\9},那么这个数据集的信息熵为 H ( x ) = − ( 1 3 log 1 3 + 1 9 log 1 9 + 1 3 log 1 3 + 2 9 log 2 9 ) = 0.569 H(x)=-\left(\frac{1}{3}\log \frac{1}{3}+\frac{1}{9}\log \frac{1}{9} +\frac{1}{3}\log \frac{1}{3} +\frac{2}{9}\log \frac{2}{9} \right)=0.569 H(x)=−(31log31+91log91+31log31+92log92)=0.569
假设对于一个数据集,样本标签分为{A,B,C,D}四个类别,每种类别的数据占比为{1,0,0,0},那么这个数据集的信息熵为 H ( x ) = − ( 1 log 1 + 0 log 0 + 0 log 0 + 0 log 0 ) = 0 H(x)=-\left(1\log 1+0\log 0 +0\log 0 +0\log0 \right)=0 H(x)=−(1log1+0log0+0log0+0log0)=0
所以根据样本数据的维度和对应维度下的取值,通过循环遍历所有的特征值使得划分后树的信息熵降低这种方式可以划分一棵决策树。
3 算法
3.1 ID3-信息增益
特征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为样本集合,H(D)为D的经验熵,H(D|A)为A对于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为样本集合,类别数为K,
C
k
C_k
Ck 为D中属于第k类的样本子集,|
C
k
C_k
Ck| 表示该子集的元素个数,|D| 表示样本集合的元素个数。
经验条件熵:
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|}\left(- \sum_{k=1}^k\frac{|D_{ik}|}{|D_i|}\log_2\frac{|D_{ik}|}{|D_i|}\right)
H(D∣A)=i=1∑n∣D∣∣Di∣H(Di)=i=1∑n∣D∣∣Di∣(−k=1∑k∣Di∣∣Dik∣log2∣Di∣∣Dik∣)
其中,D为样本集合,
D
i
D_i
Di是D中特征A取第
i
i
i个值的样本子集,
D
i
k
D_{ik}
Dik 为
D
i
D_i
Di中属于第k类的样本子集。
3.1.1 栗子
根据上面的算法,结合前面给出的栗子,以年龄特征为例进行计算。
经验熵:
H
(
D
)
=
−
∑
k
=
1
K
∣
C
k
∣
∣
D
∣
log
2
∣
C
k
∣
∣
D
∣
=
−
3
5
log
2
3
5
−
2
5
log
2
2
5
=
0.971
H(D) =- \sum_{k=1}^K\frac{|C_k|}{|D|}\log_2\frac{|C_k|}{|D|}\\ = -\frac{3}{5}\log_2\frac{3}{5} -\frac{2}{5}\log_2\frac{2}{5}= 0.971
H(D)=−k=1∑K∣D∣∣Ck∣log2∣D∣∣Ck∣=−53log253−52log252=0.971
经验条件熵:
H
(
D
∣
年
龄
)
=
∑
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
∣
)
=
1
5
H
(
中
年
)
+
4
5
H
(
青
年
)
=
1
5
(
−
0
)
+
4
5
(
−
2
4
log
2
2
4
−
2
4
log
2
2
4
)
=
0.8
H(D|年龄) = \sum_{i=1}^n\frac{|D_i|}{|D|}H(D_i)\\ = \sum_{i=1}^n\frac{|D_i|}{|D|}\left(- \sum_{k=1}^k\frac{|D_{ik}|}{|D_i|}\log_2\frac{|D_{ik}|}{|D_i|}\right)\\ = \frac{1}{5}H(中年)+\frac{4}{5}H(青年)\\ = \frac{1}{5}(-0)+\frac{4}{5}\left( -\frac{2}{4}\log_2\frac{2}{4} -\frac{2}{4}\log_2\frac{2}{4} \right)=0.8
H(D∣年龄)=i=1∑n∣D∣∣Di∣H(Di)=i=1∑n∣D∣∣Di∣(−k=1∑k∣Di∣∣Dik∣log2∣Di∣∣Dik∣)=51H(中年)+54H(青年)=51(−0)+54(−42log242−42log242)=0.8
年龄特征的信息增益为:
g
(
D
,
年
龄
)
=
H
(
D
)
−
H
(
D
∣
年
龄
)
=
0.971
−
0.8
=
0.171
g(D,年龄) = H(D) - H(D|年龄) = 0.971 - 0.8 = 0.171
g(D,年龄)=H(D)−H(D∣年龄)=0.971−0.8=0.171
同理可得到其余特征的信息增益,进行比较就可以构建一棵决策树。
3.2 C4.5-信息增益比
特征A对于数据D的信息增益比:
g
R
(
D
,
A
)
=
g
(
D
,
A
)
H
A
(
D
)
g_R(D,A) = \frac{g(D,A)}{H_A(D)}
gR(D,A)=HA(D)g(D,A)
其中,g(D,A)是A特征的信息增益,
H
A
(
D
)
H_A(D)
HA(D)是关于A的取值熵。
数据集D关于A的取值熵:
H
A
(
D
)
=
−
∑
i
=
1
n
∣
D
i
∣
∣
D
∣
log
2
∣
D
i
∣
∣
D
∣
H_A(D) = - \sum_{i=1}^n\frac{|D_i|}{|D|}\log_2\frac{|D_i|}{|D|}
HA(D)=−i=1∑n∣D∣∣Di∣log2∣D∣∣Di∣
其中,D为样本集合,
D
i
D_i
Di是D中特征A取第
i
i
i个值的样本子集。
3.2.1 栗子
关于年龄的取值熵:
H
年
龄
(
D
)
=
−
∑
i
=
1
n
∣
D
i
∣
∣
D
∣
log
2
∣
D
i
∣
∣
D
∣
=
−
1
5
log
2
1
5
−
4
5
log
2
4
5
=
0.722
H_{年龄}(D) = - \sum_{i=1}^n\frac{|D_i|}{|D|}\log_2\frac{|D_i|}{|D|}\\ =-\frac{1}{5}\log_2\frac{1}{5}-\frac{4}{5}\log_2\frac{4}{5} = 0.722
H年龄(D)=−i=1∑n∣D∣∣Di∣log2∣D∣∣Di∣=−51log251−54log254=0.722
年龄的信息增益比:
g
R
(
D
,
年
龄
)
=
g
(
D
,
年
龄
)
H
年
龄
(
D
)
=
0.171
0.722
=
0.236
g_R(D,年龄) = \frac{g(D,年龄)}{H_{年龄}(D)}\\ = \frac{0.171}{0.722} = 0.236
gR(D,年龄)=H年龄(D)g(D,年龄)=0.7220.171=0.236
同理可得到其余特征的信息增益比,然后构建决策树。
3.3 CART-基尼指数
3.3.1 基尼指数(Gini)
基尼不纯度,表示在样本集合中随机选中一个样本分错的概率。
G
i
n
i
(
D
)
=
1
−
∑
k
=
1
n
(
∣
C
k
∣
∣
D
∣
)
2
Gini(D) = 1 - \sum_{k=1}^n \left(\frac{|C_k|}{|D|}\right)^2
Gini(D)=1−k=1∑n(∣D∣∣Ck∣)2
特征A的Gini指数为:
G
i
n
i
(
D
∣
A
)
=
∑
i
=
1
n
∣
D
i
∣
∣
D
∣
G
i
n
i
(
D
i
)
Gini(D|A) = \sum_{i=1}^n\frac{|D_i|}{|D|}Gini(D_i)
Gini(D∣A)=i=1∑n∣D∣∣Di∣Gini(Di)
3.3.2 CART(Classification And Regression Tree)
CART是二叉树,所以采用二元分割法,每一次只将数据按特征值分成两部分,可以通过计算不同划分下该特征的基尼指数来找到最优的划分。
4 过拟合
样本噪声数据干扰过大时,模型会对这些噪声进行拟合。不难理解决策树的过拟合,特征值越多,确定性也相应变高,极端到如DNA每个人都不同,完全生长的决策树最终将每个人都分为一类的话,就会导致过拟合。相应的模型泛化能力变得很差。
4.1 剪枝(Pruning)
剪枝可以解决过拟合的问题。剪枝过程对于结点类别采用多数投票的原则。
4.1.1 预剪枝
在决策树生成过程中提前结束增长。也就是通过计算当前的划分能否带来模型泛化能力上的提升,来决定是不是继续生长。具体有以下几种方式:
- 规定一个深度,树达到此深度时就停止。
- 规定结点的样本数量,当当前结点样本数量小于这个阈值时,停止生长。
- 计算每次划分对测试集的准确度的提升,当小于某个阈值时,停止生长。
4.2.2 后剪枝
等完全生成一棵决策树后,从最底层开始向上计算是否剪枝。
常见后剪枝方法有错误率降低剪枝(Reduced Error Pruning,REP)、悲观剪枝(Pessimistic Error Pruning,PEP)、代价复杂度(Cost Complexity Pruning,CCP)、最小误差剪枝(Minimum Error Pruning,MEP)、CVP(Critical Value Pruning)、OPP(Optimal Pruning)等。
e.g. CART剪枝方法CCP
完整生成决策树 T 0 T_0 T0,从 T 0 T_0 T0开始,生成一个子树序列{ T 0 , T 1 , T 2 , . . . , T N T_0,T_1,T_2,...,T_N T0,T1,T2,...,TN},其中 T i + 1 T_{i+1} Ti+1 由 T i T_i Ti 生成, T n T_n Tn 为树的根结点。一开始对 T 0 T_0 T0 根据真实误差选择最佳的决策树,裁剪关于训练数据集合误差增加量最小的分支,然后得到 T 1 T_1 T1 。其余以此类推。
树在结点t处剪枝后的误差增加率为:
α
=
R
(
t
)
−
R
(
T
t
)
∣
L
(
T
t
)
∣
−
1
\alpha = \frac{R{(t)}-R{(T_t)}}{|L(T_t)|-1}
α=∣L(Tt)∣−1R(t)−R(Tt)
R
(
t
)
R(t)
R(t)是进行剪枝后该结点误差,
R
(
T
t
)
R(T_t)
R(Tt)是未进行剪枝时子树
T
t
T_t
Tt的误差,
∣
L
(
T
t
)
∣
|L(T_t)|
∣L(Tt)∣是子树
T
t
T_t
Tt的叶子结点个数。
通过比较误差增加率,选取最小的进行剪枝,进而得到下一个子树。
参考书籍:《百面机器学习》 诸葛越 葫芦娃
5 回归问题
之前都是决策树解决分类的问题,基于信息熵利用概率计算基尼指数等来进行分类。决策树也可以解决回归问题,但是面对的每个样本数据可能是一个取值,所以在进行划分时,按照使得划分之后的两颗子树的误差平方和(Sum of Squares Error,SSE)最小来划分。
SSE:
S
S
E
=
∑
i
∈
S
1
(
y
i
−
y
1
ˉ
)
2
+
∑
i
∈
S
2
(
y
i
−
y
2
ˉ
)
2
SSE = \sum_{i\in S_1}(y_i-\bar{y_1})^2+\sum_{i\in S_2}(y_i-\bar{y_2})^2
SSE=i∈S1∑(yi−y1ˉ)2+i∈S2∑(yi−y2ˉ)2
对于新来的样本,它的预测值取当前结点的所有样本的平均值。
6 代码
from sklearn.tree import DecisionTreeClassifier #分类树
# Parameters 参数说明
# criterion 标准:{“gini”, “entropy”} default=”gini”
# 衡量分割质量的函数,有基尼和熵两种标准。
# splitter 分离器:{“best”, “random”}, default=”best”
# 每个节点上的拆分策略,也是用来控制随机选项的。“best”决策树会优先选择更重要的特征进行分枝,“random”决策树在分枝时对于特征的选择更加随机
# max_depth 最大深度:int, default=None
# 树的深度最大值。不设定就会一直生长直到所有叶子都是纯的或者所有叶子包含小于min_samples_split的样本
# min_samples_split 最小样本分裂:int or float, default=2
# 分割内部节点所需的最小样本数,不满足时就不会分枝。
# min_samples_leaf 最小样本叶子:int or float, default=1
# 叶节点所需的最小样本数
# max_features 最大特征数:int, float or {“auto”, “sqrt”, “log2”}, default=None
# 计算节点划分时选取的特征数量或比例。“auto”和“sqrt”是所有特征数量开根号,“log2”是log2(n_feateres),“None”选择所有的特征。
# random_state 随机状态:int, RandomState instance, default=None
# 不设置的话每次得到的分割可能会不同,因为每次不是把所有特征都选取。如果想固定的话要设置一个整数。
# max_leaf_nodes 最大叶节点:int, default=None
# 这棵树叶节点的数量。如果不为None,max_depth会被忽略。
# min_impurity_decrease 杂质减少:float, default=0.0
# 如果分裂导致杂质减少大于或等于这个值,则节点将被分割。是用来限制信息增益的大小,信息增益小于这个值就不分枝。
# 一般使用max_depth、min_samples_leaf、min_samples_split就能够得到一个较优性能的模型了
# Attributes 属性
# feature_importances_ :ndarray of shape (n_features,)
# 特征的重要性。这个属性越高,越有可能用来对树进行节点划分。
from sklearn.tree import DecisionTreeRegressor #回归树
# 跟分类树参数几乎一样
# criterion 标准:{“mse”, “friedman_mse”, “mae”}, default=”mse”
# 支持的标准是均值方差、friedman_mse、平均绝对误差
7 局限性
决策树的决策边界横平竖直,但对数据样本集最好的划分方式不一定是横平竖直的,所以可能会导致分类错误。进一步可以按照集成学习的思路,用随机森林算法。