决策树
一棵决策树(Decision Tree)是一个树结构(可以是二叉树或非二叉树),每个非叶节点对应一个特征,该节点的每个分支代表这个特征的一个取值,而每个叶节点存放一个类别或一个回归函数。
决策树树模型由一组 if-then-else 规则构成。
决策树的构造算法被称为递归分区法。
1. 本质和概述
1.1 本质
核心:一组嵌套的判定规则
决策树算法是,通过决定性特征学习数据集中的规则,对未知数据集进行划分的算法;其中叶子节点为决策(分类)结果,非叶子节点为选择进行划分的特征(决定性特征、最优特征)。

1.2 概念/术语
-
拆分值
一个预测变量值,它将一组记录分为两部分,使得一部分中的预测变量小于拆分 值,而另一部分中的预测变量大于拆分值。 -
节点
节点是拆分值的图形化表示(或规则表示)。 -
非叶子节点(含根节点) = 决策节点 = 特征 = 条件判断
-
叶子节点 = 分类/决策结果
一组 if-then 规则的终点,或一个树分支的终点 -
损失
在拆分过程的某一阶段中误分类的个数。损失越大,不纯度越高。 -
不纯度 = 熵= 不确定性 = 异质性
不纯度:表示在数据的一个细分中发现多个类混杂的程度。细分中混杂的类越多,该细分的不纯度就越高(种类越少纯度越高)
熵:是信息论中描述事件结果的不确定性的指标。
熵是纯度的对立面,跟不纯度表达的是同一个意思。(熵 = 不确定性 = 不纯度 ) -
递归拆分
反复对数据进行划分和细分,目的是使每个最终细分内的结果尽可能同质。
每个递归构建的新的分裂点(节点)都会不断地降低不纯度(熵),最终在叶子节点上,不纯度降为0 -
剪枝
为了降低过拟合,对一棵完全长成树逐步剪枝的过程。
分裂点阈值的确定
决策树本质就是想在每个特征上找一个阈值,根据这些阈值来对数据分类。这个阈值是通过遍历来找到的。
2. 常用算法:分裂点选择依据
决策树的构造过程是一个迭代的过程。每次迭代中,采用不同特征作为分裂点,来将样本数据划分成不同的类别。被用作分裂点的特征叫做分裂特征。
选择分裂特征的目标,是让各个分裂子集尽可能地“纯”,即尽量让一个分裂子集中的样本都属于同一类别。(种类越少纯度越高——越往下纯度越高)
如何选择分裂特征的使用先后顺序?
如何使得各个分裂子集“纯?
经典算法大致有 ID3、C4.5 和 CART,其中用到的关键指标分别是:信息增益、信息增益率和基尼系数。
注:基尼系数和熵是类似的概念,只不过量化的公式不同。
2.0 信息熵
信息熵在机器学习中也叫做经验熵,因为熵的计算是依据样本数据而来。
- 信息量
信息的大小跟随机事件的概率有关。
越小概率的事情发生了产生的信息量越大;
越大概率的事情发生了产生的信息量越小 - 不纯度/复杂度
信息熵还可以作为一个系统复杂程度的度量。
如果系统越复杂,出现不同情况的种类越多,那么他的信息熵是比较大的。
如果一个系统越简单,出现情况种类很少(极端情况为1种情况,那么对应概率为1,那么对应的信息熵为0),此时的信息熵较小。 - 信息熵
当前样本集合 Y 的信息熵的定义式为:

其中,i=1,2,…k 为当前样本集合 Y的 k 个可能结果;pi 为集合 Y 中第 k 类样本所占的比例。
当样本只属于某一类时熵最小,当样本均匀的分布于所有类中时熵最大。因此,如果能找到一个分裂让熵最小,这就是我们想要的最佳分裂。
【大白话理解】
Y 在机器学习中可以表示不同的属性值也可以表示不同的标签值;
整个式子是集合中所有种类的熵(信息量)之总和;
属性或者标签有几个 类别(n) 就有几个熵的和;
问:如何理解熵 ?或者说 熵的公式的来源是什么?
答:可以看成 sum( p * log( 1 p \frac{1}{p} p1) ) 更好理解,其中 p 代表事件发生的概率 ,log( 1 p \frac{1}{p} p1) 表示该事件的储存空间!例如:
一个随机变量有8种可能,相当于8个事件,如果是0和1表示,一共需要 log2(8)=3 bit
换句话说,如果一个事件的概率是1/8,需要 log2(8)=3 bit
再换句话说,如果一个事件的概率是p,需要 log2( 1 p \frac{1}{p} p1) bit
再泛化,概率是变量,就是 log2( 1 p ( x ) \frac{1}{p(x)} p(x)1)
再泛化,2是变量,就是 log( 1 p ( x ) \frac{1}{p(x)} p(x)1)
那么,既然表示其中一个事件需要这么多字节,那么表示所有事件平均需要多少bit呢?很自然就是求期望:
sum( p(x) log( 1 p ( x ) \frac{1}{p(x)} p(x)1 )
把倒数变成负号:
-sum( p(x) logp(x) )
注:对数以 2 为底时熵的单位称作比特(bit);以e(自然对数)为底时被称为纳特(nat)。
- 例子

可以看出,熵越大的事件不确定性也越大,这也和我们的直觉相同:两方差距不大,结果的不确定性就很大。
- 条件熵
Y 的不确定性受到 X 条件的影响,此时就需要计算在有 X 影响时 Y 的熵是多少。我们称之为条件熵。

条件熵描述的是增加了某个条件后,事件的熵是多少。直观上说,增加了某个条件会让事情的不确定性降低(最不济也是不变)。(通常,这个不确定性降低的程度叫做信息增益。)
【大白话解释】每种属性值的概率 ✖️ 该种属性值的情况下标签值的信息熵。
(条件熵的本质跟条件概率是一回事)
2.1 ID3
核心:以信息增益为度量,选择分裂后信息增益最大的特征进行分裂。
-
信息增益
不确定性降低的程度叫做信息增益,定义式为:

熵减少则意味着纯度增高(类别减少;信息增益即前后两次熵的差。信息增益 = 划分前熵 - 划分后熵
注:
ID3仅仅适用于二分类问题。
ID3仅仅能够处理离散属性。
信息增益
缺点:信息增益偏向取值较多的特征
原因:当特征的取值较多时,根据此特征划分更容易得到纯度更高的子集,因此划分之后的熵更低,由于划分前的熵是一定的,因此信息增益更大,因此信息增益比较偏向取值较多的特征。
2.2 C4.5
C4.5 选用信息增益比(Gain Ratio)——用衡量不确定性降低的百分比而不是单纯的量——作为选择分支的标准。
- 信息增益率

信息增益比 = 惩罚参数 * 信息增益
注意:其中的HA(D),对于样本集合D,将当前特征A作为随机变量(取值是特征A的各个特征值),求得的经验熵。
信息增益比本质: 是在信息增益的基础之上乘上一个惩罚参数。特征个数较多时,惩罚参数较小;特征个数较少时,惩罚参数较大。

信息增益比
缺点:信息增益比偏向取值较少的特征
原因:当特征取值较少时HA(D)的值较小,因此其倒数较大,因而信息增益比较大。因而偏向取值较少的特征。
2.3 分类与回归树(CART )
CART (Classification and Regression Tree),分类和回归树,不仅可以用来做分类,还可以用来做回归。
CART 算法的运行过程和 ID3 及 C4.5 大致相同,不同之处在于:
- CART 的特征选取依据不是增益量或者增益率,而是 Gini 系数(Gini Coefficient)。每次选择 Gini 系数最小的特征作为最优切分点;
- CART 是一棵严格二叉树。每次分裂只做二分。
-
基尼指数
Gini指数表示在样本集合中一个随机选中的样本被分错的概率。
Gini指数表示集合的不确定性,或者是不纯度。基尼指数越大,集合不确定性越高,不纯度也越大。这一点和熵类似。
-
样本集合D的Gini指数 : 假设集合中有K个类别,则:

基尼指数(基尼不纯度)= 样本被选中的概率 * 样本被分错的概率 -
基于特征A划分样本集合D之后的基尼指数

2.4 对比
- 信息增益会倾向于取值较多的特征(因为取值越多意味着确定性越高,前后的信息熵差值就会更大)
- 信息增益比就是对信息增益的一个改进,一定程度上对取值比较多的特征进行惩罚,避免ID3出现过拟合的情况,提升决策树的泛化能力
- ID3 只能处理离散型变量,而 C4.5 和 CART 都可以处理连续型变量。
C4.5处理连续型变量时,通过对数据排序之后找到类别不同的分割线作为切分点,根据切分点把连续属性转换为布尔型,从而将连续型变量转换多个取值区间的离散型变量。而对于CART,由于其构建时每次都会对特征进行二值划分,因此可以很好地适用于连续性变量。 - ID3 和 C4.5 只能处理分类问题,而CART(Classification and Regression Tree,分类回归树)从名字就可以看出其不仅可以用于分类,也可以应用于回归任务(回归树使用最小平方误差准则)
- …
3. 决策树优化:剪枝
决策树算法很容易过拟合(overfitting),剪枝算法就是用来防止决策树过拟合,提高泛华性能的方法。
剪枝分为预剪枝与后剪枝。
3.1 剪枝原因(问题)
- 控制叶子节点数
防止叶子节点过多,叶子节点含有的样本数过少而导致泛化能力很差的情况。 - 控制树的高度
决策树本质上是 if-else的多层嵌套, 层数多代表 if 就非常多,这样就需要苛刻的条件才能满足这个很深的叶子节点(即这个类别),言外之意,它缺少必要的泛化能力,测试集的数据有可能不会走到这里。
为了解决以上通过训练构建出的决策树的深度过大,叶子节点过多,叶子节点含有的样本数过少的问题(实际上就是一棵树多余的树枝),就需要想办法剪去这些树枝,从而得到一棵不高不胖的决策树。
3.2 剪枝方法
剪枝是优化决策树的常用手段。剪枝方法大致可以分为两类:
- 预剪枝(局部剪枝):在构造过程中,当某个节点满足剪枝条件,则直接停止此分支的构造;
- 后剪枝(全局剪枝):先构造完成完整的决策树,再通过某些条件遍历树进行剪枝。
4. 代码
4.1 例子1
- 数据准备
from sklearn.datasets import make_blobs
X, y = make_blobs(n_samples=300, centers=4,
random_state=0, cluster_std=1.0)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='rainbow')

- 简单的决策树
from sklearn.tree import DecisionTreeClassifier
tree = DecisionTreeClassifier().fit(X, y)
- 可视化
# 快速写一个辅助函数,对分类器的结果进行可视化:
def visualize_classifier(model, X, y, ax=None, cmap='rainbow'):
ax = ax or plt.gca()
# Plot the training points
ax.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=cmap,
clim=(y.min(), y.max()), zorder=3)
ax.axis('tight')
ax.axis('off')
xlim = ax.get_xlim()
ylim = ax.get_ylim()
# fit the estimator
model.fit(X, y)
xx, yy = np.meshgrid(np.linspace(*xlim, num=200),
np.linspace(*ylim, num=200))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
# Create a color plot with the results
n_classes = len(np.unique(y))
contours = ax.contourf(xx, yy, Z, alpha=0.3,
levels=np.arange(n_classes + 1) - 0.5,
cmap=cmap, clim=(y.min(), y.max()),
zorder=1)
ax.set(xlim=xlim, ylim=ylim)
visualize_classifier(DecisionTreeClassifier(), X, y)

- 分步查看
第一步:

1 到 4 步(完整过程):

通过观察第一张的最终效果,可以知道,这棵决策树刚刚分到第 5 层数据就出现了过拟合。
这种过拟合其实正是决策树的一般属性——决策树非常容易陷得很深,因此往往会拟合局部数据,而没有对整个数据分布的大局观。
这也是为什么要控制树的深度的原因。
通过组合多个过拟合评估器来降低过拟合程度的想法其实是一种集成学习方法,称为装袋算法。装袋算法使用并行评估器对数据进行有放回抽取集成(也可以说是大杂烩),每个评估器都对数据过拟合,通过求均值可以获得更好的分类结果。随机决策树的集成算法就是随机森林。
4.2 例子2
- 模块导入
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns; sns.set()
from sklearn.datasets import make_blobs
from sklearn.tree import DecisionTreeClassifier
- 数据准备
X, y = make_blobs(n_samples=500, n_features=2,
centers=5, cluster_std= 0.5, random_state=0)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='viridis', s=10)

- 模型拟合
dt_model = DecisionTreeClassifier()
dt_model.fit(X, y)
- 新数据
X_new = [-4, -4] + [16, 14] * np.random.rand(10000, 2)
plt.scatter(X_new[:, 0], X_new[:, 1])

- 可视化结果
y_pred = dt_model.predict(X_new)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='viridis', s=10)
plt.scatter(X_new[:, 0], X_new[:, 1],
c=y_pred, cmap='viridis', s=1, alpha=0.5)

特意把新数据的生成数量提升了一个量级,就是为了更清晰地看到决策边界!
5. 总结
核心问题:如何选择分裂特征,才能使得能够更快的降低数据分类的熵/不纯度。(树越深本身就可以不断降低不纯度,我们需要做的是如何加快这个速度而且不过拟合)
参考
9646



被折叠的 条评论
为什么被折叠?



