决策树(Decision Tree)原理小结
本博客中使用到的完整代码请移步至: 我的github:https://github.com/qingyujean/Magic-NLPer,求赞求星求鼓励~~~
适用问题:多类分类、回归
模型特点:分类树、回归树
模型类型:判别模型
损失函数:对数似然损失
学习策略:正则化的极大似然估计
学习算法:特征选择、树的生成、树的剪枝
1. 决策树
1.1 决策树基础概念
适用问题: 多类分类(ID3,C4.5,CART);回归(CART)
主要优点:
- 具有可读性(if-then 规则,推理过程容易理解);
- 分类速度快
- 可自动忽略对目标变量没有贡献的属性变量,也可为判断属性变量的重要性、减少变量的数目提供参考
决策树可以看成是一个if-then规则的集合
,决策树的根结点到叶子结点的一条路径构成一条规则
。决策树的路径或其对应的if-then规则的集合具有一个重要的性质:互斥并且完备。即每个实例都被一条且只被一条路径所覆盖。
决策树还可以看成是在给定特征条件下类的条件概率分布
,这一条件概率分布定义在特征空间的一个划分
上。
1.2 决策树的学习
决策树学习的本质
: 从训练集中归纳出一组分类规则。或者从另一角度看,决策树学习是由训练集估计条件概率模型。
决策树的目标
: 找出一个与训练数据矛盾较小的决策树(不相矛盾的决策树可能有多个,也可能一个也没有),同时具有很好的泛化能力。
用损失函数
表示目标: 正则化的极大似然函数。
学习策略: 以损失函数为目标函数的最小化。
学习的算法: 通常是一个递归的选择最优特征,并根据该特征对训练数据进行分割,使得各个子数据集有一个最好的分类的过程。此过程对应着特征空间的划分
,也对应着树的生成
。
树的剪枝: 避免过拟合,是模型更泛化。
决策树分类边界的特点
:
与坐标轴平行(每个特征可视为坐标空间的一个轴)
1.3 决策树学习的3个步骤
- 特征选择:信息增益(ID3),信息增益率(C4.5),基尼系数(CART)
特征选择选取对训练数据具有分类能力的特征,是决定使用哪个特征来划分特征空间。
- 决策树的生成:3种算法(ID3,C4.5,CART)
- 决策树的剪枝:预剪枝,后剪枝
预剪枝
:在决策树生成过程中,对每个节点在划分前进行估计,若当前划分不能带来决策树泛化性能提升,则停止划分,并将当前节点标记为叶子结点。
优点
:很多分支都没有“展开”,降低了过拟合的风险,同时显著减少了训练时间开销和测试开销。
缺点
:预剪枝基于“贪心”
本质,可能会带来欠拟合风险,因为有些分支虽然当前划分不能暂时不能提升性能,但后续展开划分后却有可能带来性能的提升。
后剪枝
:先从训练集生成一个完整的决策树,在自底向上的对非叶子结点进行考察,若将该节点对应的子树替换成叶子结点能带来决策树泛化性能提升,则将该子树替换成叶子结点。
优点
:欠拟合风险小,泛化性能往往优于预剪枝。
缺点
:树生长完全后才进行剪枝,并且要自底向上对树中所有非叶子结点进行逐一考察,训练时间开销要比预剪枝大得多。
树的生成只考虑局部最优,树的剪枝考虑全局最优
。
2. ID3算法
ID3算法使用信息增益
作为特征选择的准则,每次选择信息增益最大
的特征。信息增益与"熵"
的概念联系紧密,关于各种“熵”
可以参考最大熵(max entropy)模型原理小结的第1节。
2.1 特征选择准则:信息增益(information gain)
信息增益的计算要用到熵,这里给出简要的熵的一些概念:熵是随机变量不确定性的度量
。
H ( X ) = − ∑ i = 1 n p i l o g p i H(X)=-\sum\limits_{i=1}^n p_ilogp_i H(X)=−i=1∑npilogpi
熵只依赖于X的概率分布,与X的取值无关。所以X的熵也可记为 H ( p ) H(p) H(p)。
条件熵 H ( Y ∣ X ) H(Y|X) H(Y∣X)表示在已知随机变量X的条件下随机变量Y的不确定性。
条件熵 H ( Y ∣ X ) H(Y|X) H(Y∣X)定义为X给定条件下Y的条件概率分布的熵对X的数学期望:
H ( Y ∣ X ) = ∑ i = 1 n p i H ( Y ∣ X = x i ) = − ∑ i = 1 n ∑ j = 1 n p ( x i ) p ( y j ∣ x i ) l o g p ( y j ∣ x i ) \begin{array}{ll} & H(Y|X)=\sum\limits_{i=1}^n p_iH(Y|X=x_i) \\ & \qquad\qquad=-\sum\limits_{i=1}^n \sum\limits_{j=1}^n p(x_i)p(y_j|x_i)log p(y_j|x_i)\end{array} H(Y∣X)=i=1∑npiH(Y∣X=xi)=−i=1∑nj=1∑np(xi)p(yj∣xi)logp(yj∣xi)
信息增益
表示得知特征X的信息而使得类Y的信息的不确定性减少的程度
。
特征A对训练数据集D的信息增益g(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)
经验熵
H(D)表示对数据集D进行分类的不确定性,经验条件熵
H(D|A)表示在特征A给定条件下对数据集D分类的不确定性。
信息增益的计算:
其中有K个类, C k C_k Ck表示属于类k的样本集合,特征A有n个取值,可以将数据集D划分为n个子集 D i D_i Di(i=1,2…,n), D i k D_{ik} Dik为自己 D i D_i Di中属于类 C k C_k Ck的样本集合:
H ( D ) = − ∑ k = 1 K ∣ C k ∣ ∣ D ∣ l o g ∣ C k ∣ ∣ D ∣ H(D)=-\sum\limits_{k=1}^K \frac{|C_k|}{|D|}log\frac{|C_k|}{|D|} H(D)=−k=1∑K∣D∣∣Ck∣log∣D∣∣Ck∣
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 ∣ l o g ∣ D i k ∣ ∣ D i ∣ H(D|A)=\sum\limits_{i=1}^n \frac{|D_i|}{|D|}H(D_i)=-\sum\limits_{i=1}^n \frac{|D_i|}{|D|}\sum\limits_{k=1}^K \frac{|D_{ik}|}{|D_i|}log\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∣log∣Di∣∣Dik∣
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.2 决策树生成算法
ID3算法核心:应用信息增益
准则选择特征。递归的构建决策树。
ID3相当于用极大似然法
进行概率模型的选择。
2.3 决策树剪枝算法
ID3算法只有树的生成,没有剪枝,所以该算法生成的树容易产生过拟合。
2.4 算法评价
算法评价摘自刘建平老师的 决策树算法原理(上) 。
不足:
- ID3
没有考虑连续特征
,比如长度,密度都是连续值,这限制了ID3的用途。 - ID3采用
信息增益大的特征
优先建立树节点。在相同条件下,会偏向于选择取值较多的特征
。 - ID3算法对于
缺失值
的情况没有做考虑。 - 没有考虑
过拟合
的问题,即没有“剪枝”
。
3. C4.5算法
C4.5算法对ID3进行了改进,具体做了哪些改进呢?
-
针对ID3没有连续值的情况,C4.5将
连续特征离散化
的方法,选择信息增益最大的分割点作为连续特征的二元离散分类点。使用信息增益比
作为特征选择的准则,每次选择信息增益比最大
的特征。需要注意的是,与离散属性不同的是,如果当前节点为连续属性,则该属性后面还可以参与子节点的产生选择过程。 -
针对ID3中信息增益会偏向于选择取值较多的特征的问题,C4.5采用了“信息增益比”即信息增益g(D,A)与 H A ( D ) H_A(D) HA(D)的比值作为特征选择准则。取值多的特征其信息增益g(D,A)会更大,但是其对应的特征熵 H A ( D ) H_A(D) HA(D)也会更大,以其作为分母,可对信息增益对取值较多的特征的偏好起到校正的作用。
-
针对
缺失值
的处理有2个问题:
(1)当样本的某些特征缺失时如何选择划分属性?这里将信息增益的计算式推广为:
g ( D , A ) = ρ ∗ g ( D ~ , A ) = ρ ∗ ( H ( D ~ ) − H ( D ~ ∣ A ) ) \begin{array}{ll} & g(D,A) =\rho\; *g(\tilde{D},A) \\ & \qquad\quad\;\;\,= \rho\; * \big(H(\tilde{D})-H(\tilde{D}|A)\big) \end{array} g(D,A)=ρ∗g(D~,A)=ρ∗(H(D~)−H(D~∣A))其中 D ~ \tilde{D} D~表示在属性A上没有缺失的样本集合, ρ \rho ρ表示 D ~ \tilde{D} D~的占比即 ∣ D ∣ ~ ∣ D ∣ \frac{\tilde{|D|}}{|D|} ∣D∣∣D∣~。
(2)给定划分属性后,样本的在该属性上的值缺失,那该样本如何进行划分?
将缺失特征的样本同时划分入所有的子节点,且样本权值 w x w_x wx在特征A对应的不同取值的子节点中调整为 r a ~ ∗ w x \tilde{r_a}*w_x ra~∗wx,其中 r a ~ \tilde{r_a} ra~表示 D ~ \tilde{D} D~中特征A取值为a的样本占比。
-
对于
过拟合
的问题,C4.5引入了正则化系数
进行初步的剪枝
。关于剪枝详见本章第4节内容和CART算法部分。
3.1 特征选择准则:信息增益比(information gain ratio)
信息增益比的计算:
信息增益比
g(D,A):
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)即信息增益, H A ( D ) H_A(D) HA(D)表示训练数据集D关于特征A的值的熵,即按特征A的取值对D进行划分后分类的不确定性,其计算公式为: H A ( D ) = − ∑ i = 1 n ∣ D i ∣ ∣ D ∣ l o g ∣ D i ∣ ∣ D ∣ H_A(D)=-\sum\limits_{i=1}^n \frac{|D_i|}{|D|}log\frac{|D_i|}{|D|} HA(D)=−i=1∑n∣D∣∣Di∣log∣D∣∣Di∣。
需
注意
的是:增益率准则会偏向于取值较少的特征
,因此C4.5不是直接选择增益率最大的候选划分属性/特征,而是使用了一个启发式:先从候选划分属性中找出信息增益高于平均水平的属性,再从中选择增益率最高的。
3.2 决策树生成算法
3.3 决策树剪枝算法
C4.5引入了正则化系数
进行初步的剪枝
。关于剪枝详见本章第4节内容和CART算法部分。
3.4 算法评价
算法评价摘自刘建平老师的 决策树算法原理(上) 。
C4.5虽然改进或者改善了ID3算法的几个主要的问题,仍然有优化的空间。
不足:
- 由于决策树算法非常容易过拟合,因此对于生成的决策树必须要进行剪枝。剪枝的算法有非常多,剪枝方法仍有优化的空间。
- C4.5生成的是多叉树,如果采用二叉树,可以提高运算效率。
- C4.5只能用于分类,如果能将决策树用于回归的话可以扩大它的使用范围。
- C4.5由于使用了熵模型,里面有大量的耗时的对数运算,如果是连续值还有大量的排序运算。如果能够加以模型简化可以减少运算强度但又不牺牲太多准确性的话,那就更好了。
4. 剪枝算法
为什么要剪枝?:决策树的生成,会过多的考虑如何提高对训练数据集的正确分类,从而构建出过于复杂的决策树。
剪枝:将已经生成的树进行简化的过程。
剪枝:通过极小化
决策树的整体的损失函数
来实现。
决策树学习的 损失函数
可以定义为:
C α ( T ) = ∑ t = 1 ∣ T ∣ N t H t ( T ) + α ∣ T ∣ C_\alpha(T)=\sum\limits_{t=1}^{|T|}N_tH_t(T)+\alpha|T| Cα(T)=t=1∑∣T∣NtHt(T)+α∣T∣
其中树T的叶子结点个数为|T|,t是叶子结点,Nt表示叶子结点t有Nt个样本点,其中属于k类的样本点有
N
t
k
N_{tk}
Ntk个,
α
≥
0
\alpha \ge0
α≥0。
H
t
(
T
)
H_t(T)
Ht(T)表示叶子结点t上的经验熵
,
H
t
(
T
)
=
−
∑
k
=
1
K
N
t
k
N
t
l
o
g
N
t
k
N
t
H_t(T)=-\sum\limits_{k=1}^{K} \frac{N_{tk}}{N_t}log\frac{N_{tk}}{N_t}
Ht(T)=−k=1∑KNtNtklogNtNtk。
即 C ( T ) = ∑ t = 1 ∣ T ∣ N t H t ( T ) = ∑ t = 1 ∣ T ∣ ∑ k = 1 K N t k l o g N t k N t C(T)=\sum\limits_{t=1}^{|T|}N_tH_t(T)=\sum\limits_{t=1}^{|T|}\sum\limits_{k=1}^{K} N_{tk}log\frac{N_{tk}}{N_t} 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∣
其中,C(T)表示模型对训练数据的预测误差
,即模型与训练数据的拟合程度
,|T|表示模型的复杂度
,参数
α
\alpha
α控制两者之间的影响。
α
\alpha
α越大,将促使选择简单的模型/树,
α
\alpha
α较小,将促使选择复杂的模型/树。
剪枝,就是当
α
\alpha
α确定时,选择损失函数最小
的模型,即损失函数最小的子树。
α
\alpha
α确定时,子树越大,与训练数据拟合越好,但模型越复杂;子树越小,模型复杂度低,但和训练数据的拟合就不好。损失函数表示了对两者的平衡。
决策树的生成只考虑了通过提高信息增益或者信息增益比来对训练数据更好的拟合,决策树的剪枝则通过优化损失函数还考虑了减小模型复杂度
。
决策树的生成
学习局部
的模型,决策树剪枝
学习整体
的模型。
损失函数
C
α
(
T
)
C_\alpha(T)
Cα(T)的极小化
等价于正则化的极大似然估计
,所以利用损失函数最小化进行剪枝
就是用正则化的极大似然估计
进行模型选择
。
加深考虑剪枝的损失函数
C α ( T ) C_\alpha(T) Cα(T)与正则化极大似然估计的理解
:
极大似然估计:就是在现已有的“事实”下(即已有的训练数据集下),使得model以更大(最大)概率拟合现有数据分布;
而C(T)极小化,即经验熵 H t ( T ) H_t(T) Ht(T)就要越小,即叶子结点中类别越“pure”,即训练集拟合越充分;
而正则化的极大似然估计与损失函数 C α ( T ) C_\alpha(T) Cα(T)等价,即通过剪枝(剪枝可理解为正则化手段)来控制模型的复杂度,从而达到降低过拟合风险。
5. CART算法
CART相对于C4.5和ID3进行了改进,又做了哪些改进呢?
CART分类树
算法使用“基尼系数”
作为特征选择的准则。无论是ID3中的信息增益,还是C4.5中的信息增益比,都是基于“熵”模型的计算,会涉及大量的对数运算,影响运算效率。而在CART分类树算法中使用的基尼系数既能像“熵”一样衡量不确定性(即划分后的子集样本是否pure),计算又相对简单。- CART算法中的决策树是
二叉树
。所以针对离散属性
时,CART对特征的多个取值不停的进行二分,而一次二分不能将特征A完全划分开,所以特征A还是可以参与后续的子节点的产生选择过程。 - 针对
连续特征
,像C4.5一样也采用了将连续特征离散化
的方法,只不过CART分类树在选择划分点时使用的衡量标准是基尼系数。同样需要注意,如果当前节点为连续属性,则该属性后面还可以参与子节点的产生选择过程。 - CART算法既能做
回归
(输出是连续值),此时特征划分准则是“平方误差最小化”
;也能做分类
(输出是离散值),此时特征划分准则是“基尼系数最小化”
。
CART算法有2步:
-
(1)决策树的
生成
:基于训练数据集
生成尽量大
的决策树 -
(2)决策树的
剪枝
:基于验证集
,对已生成的决策树进行剪枝,并选择最优子树
,剪枝标准:损失函数最小化
5.1 特征选择准则:基尼系数(Gini Index)
G i n i ( p ) = 1 − ∑ k = 1 K p k 2 Gini(p)=1-\sum\limits_{k=1}^K p_k^2 Gini(p)=1−k=1∑Kpk2
其中pk表示样本点属于第k类的概率。
G i n i ( D ) = 1 − ∑ k = 1 K ( ∣ C k ∣ ∣ D ∣ ) 2 Gini(D)=1-\sum\limits_{k=1}^K (\frac{|C_k|}{|D|})^2 Gini(D)=1−k=1∑K(∣D∣∣Ck∣)2
其中Ck表示样本集合D中属于k类的样本子集。
基尼系数的计算:
如果样本集合D根据特征A是否取某一可能值a被分割线D1和D2,则 在特征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{|D1|}{|D|}Gini(D1)+\frac{|D2|}{|D|}Gini(D2)
Gini(D,A)=∣D∣∣D1∣Gini(D1)+∣D∣∣D2∣Gini(D2)
基尼系数
Gini(D)表示集合D的不确定性
,基尼系数Gini(D,A)表示经过A=a分割后集合D的不确定性
。基尼指数值越大,样本集合不确定性就越大,与熵类似。
5.2 决策树生成算法
5.2.1 回归树生成
对于连续值
的处理, CART分类树
采用“基尼系数”作为特征划分准则,而CART回归树
采用的是“平方误差最小化”
准则。
预测
时,回归树将叶子结点中的均值
或者中位数
作为最终预测结果。
5.2.2 分类树生成
CART分类树使用基尼系数
作为特征选择的准则,每次选择基尼系数最小
的特征。
5.3 决策树剪枝算法
由2步构成:已知生成算法"野蛮生长"生成T0
-
(1)从T0
底部
开始不断剪枝,直到根节点,形成一个子树序列
{T0,T1,…,Tn} -
(2)通过
交叉验证
,在独立的验证集
上对子树进行测试,从中选择最优子树
,即使得损失函数 C α ( T ) C_\alpha(T) Cα(T)最小的子树,记为 T α T_\alpha Tα。最优子树是唯一的
。
5.4 算法评价
不足:
- 仍然是 “单变量决策树”,即在做特征选择时,都是选取单一特征进行划分,而分类决策往往会由多个属性共同决定。
- 样本发生改变,树结构也会随之改变。解决:集成多棵树(如随机森林(random forest))
6. 决策树延伸
上面讲述特征选择时,都是选取单一特征进行划分,可称为 “单变量决策树”,单变量决策树分类边界
的特点是与坐标轴平行
(每个特征可视为坐标空间的一个轴)。那 “多变量决策树” 是什么意思呢?
"多变量决策树"
:决策树中,内部节点不再是对某个属性,而是对多个属性的线性组合
进行测试,换言之,每个节点是一个形如
∑
i
=
1
d
w
i
a
i
=
t
\sum\limits_{i=1}^dw_ia_i=t
i=1∑dwiai=t的线性分类器
,wi是属性ai的权重,wi和t可在该节点所含的样本集合属性集上学的。此时的分类边界就不再是平行于坐标轴,而是由很多斜线连接组成
。
7. 决策树算法总结
这部分内容摘自刘建平老师的 决策树算法原理(下) 。
算法 | 处理任务 | 树结构 | 特征选择准则 | 是否支持处理连续值 | 是否支持处理缺失值 | 是否含剪枝 |
---|---|---|---|---|---|---|
ID3 | 分类 | 多叉树 | 信息增益 | 否 | 否 | 否 |
C4.5 | 分类 | 多叉树 | 信息增益比 | 是 | 是 | 是 |
CART | 分类;回归 | 二叉树 | 基尼系数;平方误差 | 是 | 是 | 是 |
决策树的优点:
- 简单直观,生成的决策树很直观。
- 基本不需要预处理,不需要提前归一化,处理缺失值。
- 使用决策树预测的代价是 O ( l o g 2 m ) O(log_2m) O(log2m)。 m为样本数。
- 既可以处理离散值也可以处理连续值。很多算法只是专注于离散值或者连续值。
- 可以处理多维度输出的分类问题。
- 相比于神经网络之类的黑盒分类模型,决策树在逻辑上可以得到很好的解释
- 可以交叉验证的剪枝来选择模型,从而提高泛化能力。
- 对于异常点的容错能力好,健壮性高。
决策树的缺点:
- 决策树算法非常容易过拟合,导致泛化能力不强。可以通过设置节点最少样本数量和限制决策树深度来改进。
- 决策树会因为样本发生一点点的改动,就会导致树结构的剧烈改变。这个可以通过
集成学习
之类的方法解决。 - 寻找最优的决策树是一个NP难的问题,我们一般是通过启发式方法,容易陷入
局部最优
。可以通过集成学习
之类的方法来改善。 - 有些比较复杂的关系,决策树很难学习,比如 异或。这个就没有办法了,一般这种关系可以换
神经网络
分类方法来解决。 - 如果某些特征的样本比例过大,生成决策树容易偏向于这些特征。这个可以通过调节
样本权重
来改善。
8. 决策树使用Demo
鸢尾花分类
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
import numpy as np
from matplotlib.colors import ListedColormap
import matplotlib.pyplot as plt
from pydotplus import graph_from_dot_data
from sklearn.tree import export_graphviz
准备鸢尾花数据集
iris = datasets.load_iris()
print(iris['data'].shape, iris['target'].shape) # (150, 4) (150,) 一共有4个特征
X = iris.data[:,[2,3]] # 只使用2个特征
y = iris.target
print('Class labels:', np.unique(y))
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1, stratify=y)
print(X_train.shape, y_train.shape)
输出:
(150, 4) (150,)
Class labels: [0 1 2]
(105, 2) (105,)
训练并绘制决策边界:
tree = DecisionTreeClassifier(criterion='gini', max_depth=4, random_state=1)
tree.fit(X_train, y_train)
X_combined = np.vstack((X_train, X_test))
y_combined = np.hstack((y_train, y_test))
# 绘制决策边界
plot_decision_regions(X_combined, y_combined, classifier=tree, test_idx=range(105, 150))
plt.xlabel('petal length [cm]')
plt.ylabel('petal width [cm]')
plt.legend(loc='upper left')
plt.show()
绘制决策树的结构和结果:
dot_data = export_graphviz(tree,
filled=True,
rounded=True,
class_names=['Setosa', 'Versicolor', 'Virginica'],
feature_names=['petal length', 'petal width'],
out_file=None)
graph = graph_from_dot_data(dot_data)
graph.write_png('tree.png')
完整代码
完整代码请移步至: 我的github:https://github.com/qingyujean/Magic-NLPer,求赞求星求鼓励~~~
参考
- [1] 统计学习方法(第2版) 李航
- [2] 决策树算法原理(上) 刘建平
- [3] 决策树算法原理(下) 刘建平
- [4] 机器学习(西瓜书) 周志华
- [5] Python_Machine_Learning_2nd_Edition