介绍决策树算法的文章很多,讲的也非常好,这篇文章从基础概念铺垫,到决策树算法的生成,决策树算法的剪枝,一步一步来描述决策树算法。
算法简介
决策树可以用来干嘛?当然是用来做决策,他可以用来处理两类问题:(1)处理分类问题(2)处理回归问题。本文只介绍分类问题的解决思路。
该算法的关键的是“树”,我们就是要找到这样一棵树,来帮助我们做决策。这里有很重要的一个过程,就是这棵树是怎么生成的。待会儿再详细说明。
生成这棵树以后,每一个分支代表一种情况,对每个新输入的样本进行预测的时候,只需要按照树的分支结构,一步一步妄下判断,就可以得到预测值了。
了解必要概念
为了更好的理解决策树算法,我们需要了解几个基础的概念。如果你已经了解相应概念,可以跳过概念部分。
-
熵
在信息论与概率统计中,熵用来衡量一个变量的不确定性。 假设变量包含有限种可能性, 是一个离散随机变量,概率分布为:
那么随机变量的熵定义为:(注意:下式log 通常以 2 或者 e 为底。)
为加深对熵的理解,我们举个例:
情形一:掷骰子(六个面都是1);
情形二:掷硬币(有正面或者反面);
情形三:掷骰子(六个面分别是1,2,3,4,5,6)。
我们分别来求解一下两种情况的熵。
情形一,由于只有一种可能性:
情形二,有2种可能:
情形三,有6种可能:
对于三种情形
并且可以看到:
情形一每次可能出现1种情况,情形非常确定,熵是最低的。 情形二每次可能出现2种情况,熵的值排在中间。 情形三每次可能出现6种情况,情形最复杂,熵也是最高的。
所以得到规律:不确定性越高,熵越高;越确定的事物,熵越低。
对于同一事件,有两种情况,一种肯定不会发生,另一种是肯定会发生,都表示事件的结果很确定,所以两种情况的熵都相对很低。所以通俗的讲,事件的结果越分散,各种结果出现的次数越平均,那么熵也就越高。
这点特别重要,待会儿也提到决策树是如何利用这一点的。
-
信息增益
刚才我们提到了熵的概念,它表示事情的不确定性。接下来我们要讨论信息增益。
上一步中,每个情形只有单个事件。现在我们要提到一种情形,这种情形下,有两个事件和,同时对系统产生影响。 那么总的熵:
D 表示系统的各种变量的集合。
现在我们把这件事先给“确定”下来,那么X确定以后,系统的熵:
从数值上看, 和存在如下大小关系
那是因为
表示的是确定,其他变量(也就是)不确定的情况下,系统的不确定性;
H(D)表示的是系统所有变量(和)都不确定的情况下,系统的不确定性。
显而易见,更加“不确定”,因为当X确定下来以后,整个系统的不确定性肯定是减少的。
而这个差值,就是变量X带来的信息增益,计算方法如下:
表示得知X后,系统不确定性减少的程度。
-
信息增益的计算公式
输入:训练数据集,特征,训练数据集对应的类型
输出:特征X对训练数据集D的信息增益
(1) 先计算数据集的经验熵H(D)
注意:经验熵的计算,更偏重的是结果出现的可能性,表示分类结果的不确定性。这里的计算并不需要单个变量的变化性。
(2)计算特征X确定的情况下,经验条件熵
根据特征A的n个不同的取值,将数据集划分为n个子集。表示的是第i个子集。
(3)
信息增益的概念和计算方法,已经介绍完了。下一小节就进入正题了。
决策树的生成
决策树算法的核心,就在于决策树的生成和剪枝。
决策树的生成算法有2种:(1)ID3 算法(2)C4.5算法
那么我们先介绍ID3算法:
输入: 训练数据集,特征集,阈值 输出:决策树
步骤如下:
(1)若D中所有实例都属于同一类,则为单节点树,并将T$;
(2)若,则为单节点树,并将D中的实例数最大的类作为该节点的类标记,返回;
(3)否则,按照信息增益公式,计算信息增益最大的特征;
(4)如果的信息增益小于阈值,则置T为单节点树,并将D中实例数最大的类作为该节点的类标记,返回;
(5)否则,对的每一个可能值,依将分割为若干非空子集,将D_i中的实例数最大的类作为标记,构建子节点,由节点及其子节点构成树,返回;
(6)对第i个子节点,以为训练集,以为特征集,递归调用步骤(1)~(5)
以上就是ID3算法生成决策树的过程,C4.5的过程类似,仅仅是把衡量信息增益的指标,从信息增益“量”,替换为信息增益“比”,即信息增益的比例。
决策树的剪枝
决策树的坚持往往通过及消化决策树整体的损失函数,或者代价函数来实现。
设树T的叶节点个数为|T|,t是树的叶节点,该叶节点有个样本点,其中k类的样本点有为叶节点t熵的经验熵,为参数,则决策树学习的损失函数可以定义为:
其中经验熵为
在损失函数中,将右端第一项记作
于是损失函数为:
其中C(T) 表示模型对训练集的预测误差,即模型与训练集的拟合程度。 表示模型复杂度,参数 控制两者之间的影响力。
决策树的剪枝,就是通过控制的大小,来调整两者之间的平衡。
具体算法如下:
输入:决策树生成算法产生的整个树,参数\alpha;
输出:修剪后的树
(1)计算每个节点的经验熵。
(2)递归地从树的叶节点往上回缩。 设一组夜间点回缩到父节点之前和之后的整体树分别为 ,其对应的损失函数分别为与, 如果
则进行剪枝,即将父节点变为新的叶节点。
(3)返回(2),直到不能继续为止,得到损失函数最小的子树
利用sklearn中的决策树算法,拟合鸢尾花数据集
首先导入数据集,特征一共包含0,1,2,3列,我们取2,3两列为特征进行分析,画出其数据点的分布:
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
iris = datasets.load_iris()
X = iris.data[:,2:]
y = iris.target
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.scatter(X[y==2,0], X[y==2,1])
plt.show()
结果如下:
然后,导入决策树算法,进行拟合
from sklearn.tree import DecisionTreeClassifier
dt_clf = DecisionTreeClassifier(max_depth=2, criterion="entropy", random_state=42)
dt_clf.fit(X, y)
DecisionTreeClassifier(class_weight=None, criterion='entropy', max_depth=2,
max_features=None, max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, presort=False, random_state=42,
splitter='best')
这里借助一个工具函数,用来画决策树的边界
def plot_decision_boundary(model, axis):
x0, x1 = np.meshgrid(
np.linspace(axis[0], axis[1], int((axis[1]-axis[0])*100)).reshape(-1, 1),
np.linspace(axis[2], axis[3], int((axis[3]-axis[2])*100)).reshape(-1, 1),
)
X_new = np.c_[x0.ravel(), x1.ravel()]
y_predict = model.predict(X_new)
zz = y_predict.reshape(x0.shape)
from matplotlib.colors import ListedColormap
custom_cmap = ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])
plt.contourf(x0, x1, zz, linewidth=5, cmap=custom_cmap)
然后我们划出决策树算法生成的分布图:
plot_decision_boundary(dt_clf, axis=[0.5, 7.5, 0, 3])
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.scatter(X[y==2,0], X[y==2,1])
plt.show()
结果如下:
结果显示: 我们把横坐标表示的点记作x,纵坐标表示的点记作y 利用决策树进行决策的过程如下:那么
if (x < 2.4) {
return '红色点'
}
if (y > 1.6) {
return '绿色点'
}
return '红色点'
总结
决策树的生成过程,利用了ID3 的算法,C4.5算法也是比较类似的,采用的是信息增益比。
此外,还可以使用CART算法对决策树进行生成和剪枝。本文暂未介绍到。