决策树是一种基本的分类与回归方法。决策树的学习包含三个步骤:特征选择、决策树的生成、决策树的修剪。决策树根据不同的特征选择原则分为ID3算法、C4.5算法、CART算法。
基本概念
在介绍决策树之前先来了解一些基本相关概念。
1、熵
熵是随机变量不确定性的度量。设X是一个有限取值的离散随机变量,其概率分布为:
P(X=xi)=pi,i=1,2,…n
随机变量X的熵定义:
H(p)=H(X)=−i=1∑npilogpi
熵只与X的分布有关,与X取值无关
当随机变量只有两个取值时,例如1,0,即X的分布:
P(X=1)=p,P(X=0)=1−p
熵为:
H(p)=−plogp−(1−p)log(1−p)
这时,熵H(p) 随概率p变化的曲线如图所示:

当p=0 或p=1 时H(p)=0 随机变量完全没有不确定性。当p=0.5 时,H(p)=1,熵取值最大,随机变量不确定性最大。
2、条件熵
定义为X给定条件下Y的条件概率分布的熵对X 的数学期望:
H(Y∣X)=i=1∑npiH(Y∣X=xi)
其中pi=P(X=xi),i=1,2,…,n
3、信息增益
表示得知特征X 的信息而使得类Y 的信息的不确定性减少的程度。
特征A对训练数据集D的信息增益g(D∣A),定义为集合D的经验熵H(D)与特征A给定的条件下D的经验条件熵H(D∣A)之差
g(D,A)=H(D)−H(D∣A)
熵与条件熵的差称为互信息。
给定训练数据集D和特征A,熵H(D) 表示对数据集D进行分类的不确定性。条件熵H(D∣A) 表示在特征A给定条件下对数据集D进行分类的不确定性。二者的差,即信息增益,表示由于特征A而使得对数据集D的分类的不确定性减少的程度,不同的特征有不同的信息增益,信息增益大的特征有更强的分类能力。
4、信息增益比
特征A对训练数据集D的信息增益gR(D∣A),定义为其信息增益g(D,A) 与训练数据集D 关于特征A 的值的熵HA(D)之比:
gR(D,A)=HA(D)g(D,A)HA(D)=−i=1∑nDDilog2DDi
n 是特征A 的取值个数。
ID3 算法
ID3算法的通过信息增益来进行特征选择生成决策树。
信息增益算法
输入:训练数据集D和特征A
输出:特征A对训练数据集D的信息增益g(D,A)
- 数据集D的经验熵H(D)=−∑k=1K∣D∣∣Ck∣log2∣D∣∣Ck∣
- 特征A对数据集D的经验条件熵H(D∣A)=∑i=1n∣D∣∣Di∣H(Di)=−∑i=1n∣D∣∣Di∣∑k=1K∣Di∣∣Dik∣log2∣Di∣∣Dik∣
- 信息增益g(D,A)=H(D)−H(D∣A)
计算所有的特征的信息增益,根据信息增益的大小确定最优特征。
通过下面这个例子来说明ID3算法生成决策树的过程。
下表是由15个样本组成的贷款申请训练数据。

希望通过所给的训练数据学习一个贷款申请决策树,用以对未来的贷款申请进行分类。
首先计算熵
H(D)=−159log2159−156log2156=0.971
然后计算各个特征对数据集D的信息增益,分别以A1,A2,A3,A4 表示年龄、有工作、有房子和信贷情况4个特征。则:
H(D∣A1)=155H(D1)+155H(D2)+155H(D3)=−155(53log253+52log252)−155(52log252+53log253)−155(54log254+51log251)=0.888
D1,D2,D3 分别表示A1(年龄) 取值为青年、老年、中年的样本子集。
年龄对应的信息增益为 g(D,A1)=H(D)−H(D∣A1)=0.083
同理计算是否有工作的信息增益为:
H(D∣A2)=H(D)−[155H(D1)+1510H(D2)]=0.971−[155×0+1510(−104log2104−106log2106)]=0.324
是否有房子的信息增益为:
H(D∣A3)=H(D)−[156H(D1)+159H(D2)]=0.971−[156×0+159(−93log293−96log296)]=0.420
信贷情况的信息增益:
H(D∣A4)=0.971−0.608=0420
比较后,发现特征A3 (有自己的房子)的信息增益最大,所以选择特征A3 作为最优特征。所以A3 作为根结点的特征。然后将数据集分为两个子集D1(拥有自己的房子)和D2(没有自己的房子)。D1 只有同一类样本点,所以他成为一个叶子结点。对于D2 需要从特征A1(年龄)、A2(有工作)、A4(信贷情况)中选择新的特征。计算各个特征的信息增益:
g(D2,A1)=H(D2)−H(D2∣A1)=0.251g(D2,A2)=H(D2)−H(D2∣A1)=0.918g(D2,A3)=H(D2)−H(D2∣A1)=0.474
选择信息增益最大的特征A2 作为结点特征。A2 有两个可能的取值,从这一结点引出两个子结点:一个对应有工作的子结点,包含三个样本,均属于同一类,所以这是一个叶子节点。另一个是无工作的子结点,包含6个 样本,也属于同一类,所以这是一个叶子节点。所以就生成了如下的决策树:

ID3 算法具体流程如下:
输入:训练数据集D, 特征集A,阈值ϵ
输出:决策树T
- 如果D属于同一类Ck,T为单节点树,类Ck作为该节点的类标记,返回T
- 如果A是空集,置T为单节点树,实例数最多的类作为该节点类标记,返回T
- 计算g, 选择信息增益最大的特征Ag
- 如果Ag的信息增益小于ϵ,T为单节点树,D中实例数最大的类Ck作为类标记,返回T
-
Ag划分若干非空子集Di,
-
Di训练集,A−Ag为特征集,递归调用前面步骤,得到Ti,返回Ti
ID3 算法缺陷:
(1)容易过拟合
(2)没有考虑连续特征的处理
(3)没有考虑对缺失值的处理
(4)采用信息增益的特征选择方法,在相同的情况下,取值较多的特征比取值少的特征信息增益大。
为了改进这些不足,C4.5算法对ID3生成决策树算法进行了改进。
C4.5 算法
对于ID3算法的第一个缺陷,C4.5算法通过剪枝的方式,增强了模型的泛化能力。
对于第二个缺陷:不能处理连续特征, C4.5的思路是将连续的特征离散化。比如特征A的连续特征值有n个,从小到大排列为a1,a2,...,an,则C4.5取相邻两样本值的平均数,一共取得n-1个划分点,其中第i个划分点Ti表示为:Ti=2ai+ai+1。对于这n-1个点,分别计算以该点作为二元分类点时的信息增益:
g(D,a)=H(D)−H(D∣a)
选择n-1个信息增益中最大的点作为该连续特征的二元离散分类点。比如取到的增益最大的点为at,则小于at的值为类别1,大于at的值为类别2,这样我们就做到了连续特征的离散化。要注意的是,与离散属性不同的是,如果当前节点为连续属性,则该属性后面还可以参与子节点的产生选择过程。
对于第三个缺陷:没有考虑对缺失值的处理。C4.5主要解决两个问题:(1)如何在属性值缺失的情况下进行划分属性选择?(2)给定划分属性,若样本在该属性上缺失,如何对样本进行划分。
给定训练集D和属性A,令D^ 表示D中在属性A上没有缺失值的样本子集。假定A的取值有v个:{a1,a2,…,av},令D^v 表示在属性A上取值为av 的样本子集(如:是否有工作)。D^k 表示D^ 中第k类样本子集。为每一个样本x赋予一个权重wx,定义:
对于属性A,无缺失样本所占的比例为:
ρ=∑x∈Dwx∑x∈D^wx
无缺失样本中第k类所占的比例为:
p^k=∑x∈D^wx∑x∈D^kwx
无缺失样本中在属性A上取值为av 的样本所占的比例为:
r^v=∑x∈D^wx∑x∈D^vwx
样本存在缺失值的情况下,采用以下的信息增益计算方式:
g(D,A)=ρ×g(D^,A)=ρ×(H(D^)−H(D^∣A))
其中:
H(D^)=−k=1∑kp^klog2p^kH(D^∣A)=v=1∑vr^vH(D^v)
其实就是:第一步先计算无缺失值的样本的各个特征的信息增益,然后乘以该特征的无缺失样本的占比。再选择信息增益最大的特征作为划分特征。这也就回答了第一个问题。
对于问题(2),可以将缺失特征的样本同时划分入所有的子节点,不过将该样本的权重按各个子节点样本的数量比例来分配。比如缺失特征A的样本a之前权重为1,特征A有3个特征值A1,A2,A3。 3个特征值对应的无缺失A特征的样本个数为2,3,4.则a同时划分入A1,A2,A3。对应权重调节为2/9,3/9, 4/9。
对于第四个缺陷:特征数越多的特征对应的特征熵越大,它作为分母,可以校正信息增益容易偏向于取值较多的特征的问题。即采用信息增益比来选择特征:
gR(D,A)=HA(D)g(D,A)HA(D)=−i=1∑nDDilog2DDi
C4.5算法具体流程如下:
输入:训练数据集D, 特征集A,阈值ϵ
输出:决策树T
- 如果D属于同一类Ck,T为单节点树,类Ck作为该节点的类标记,返回T
- 如果A是空集, 置T为单节点树,实例数最多的作为该节点类标记,返回T
- 计算g, 选择信息增益比最大的特征Ag
- 如果Ag的信息增益比小于ϵ,T为单节点树,D中实例数最大的类Ck作为类标记,返回T
-
Ag划分若干非空子集Di,
-
Di训练集,A−Ag为特征集,递归调用前面步骤,得到Ti,返回Ti
C4.5缺陷:只能用于分类,不能用于解决回归问题。
决策树的剪枝
决策树生成算法递归地产生决策树,直到不能继续下去为止。这样产生的树往往对训练数据的分类很准确,但对未知的测试数据的分类却没有那么准确,即出现过拟合现象。过拟合的原因在于学习时过多地考忠如何提高对训练数据的正确分类,从而构建出过于复杂的决策树。解决这个问题的办法是考虑决策树的复杂度,对已生成的决策树进行简化。
在决策树学习中将已生成的树进行简化的过程称为剪枝(pruning) 。具体地,剪枝从已生成的树上裁掉一-些子树或叶结点,并将其根结点或父结点作为新的叶结点,从而简化分类树模型。
剪枝的过程往往通过极小化决策树的损失函数或代价函数来实现。
树T的叶结点个数为∣T∣,t是树T的叶结点,该结点有Nt个样本点,其中k类的样本点有Ntk个,Ht(T)为叶结点t上的经验熵, α⩾0为参数,决策树学习的损失函数可以定义为
Cα(T)=i=1∑∣T∣NtHt(T)+α∣T∣
其中
Ht(T)=−k∑NtNtklogNtNtk
C(T)=t=1∑∣T∣NtHt(T)=−t=1∑∣T∣k=1∑KNtklogNtNtk
这时有
Cα(T)=C(T)+α∣T∣
其中C(T)表示模型对训练数据的误差,∣T∣表示模型复杂度,参数α⩾0控制两者之间的影响。
(1) 当α 较大时,∣T∣ 较小,树的模型相对简单。
(2) 当α 较小时,∣T∣ 较大,树的模型相对复杂。
(3)当α=0 时,只考虑模型与训练数据的拟合程度,不考虑模型的复杂度。
以上定义的损失函数的极小化等价于正则化的极大似然估计。
树的剪枝算法如下:
输入:生成算法生成的整个树T,参数α
输出:修剪后的子树Tα
-
计算每个叶结点的经验熵
-
递归的从树的叶结点向上回溯
假设一组叶结点回溯到其父结点之前与之后的整体树分别是TB和TA,其对应的损失函数分别是Cα(TA)和Cα(TB),如果Cα(TA)⩽Cα(TB)则进行剪枝,即将父结点变为新的叶结点:

- 返回2,直至不能继续为止,得到损失函数最小的子树Tα