决策树(decision tree) 是一类常见的机器学习方法。顾名思义,决策树是基于树结构来进行决策的,其基本流程遵循简单且直观的"分而治之" (divide-and-conquer) 策略。
决策树学习的关键是如何选择最优划分属性,使得分支结点的"纯度" (purity) 越来越高。
1决策树算法相关术语
1.1信息熵
“信息熵” (information entropy)是度量样本集合纯度最常用的一种指标。样本集合D的信息熵定义:
E
n
t
(
D
)
=
−
∑
k
=
1
∣
γ
∣
p
k
l
o
g
2
p
k
Ent(D)=-\sum_{k=1}^{|\gamma|}p_k\, log_2\, p_k
Ent(D)=−k=1∑∣γ∣pklog2pk
Ent(D)的值越小,则D 的纯度越高,最小值为0。
1.2信息增益
假定离散属性a有V 个可能的取值
a
1
,
a
2
,
.
.
.
,
a
V
{a^1,a^2,...,a^V}
a1,a2,...,aV,若使用a 来对样本集D 进行划分,则会产生V 个分支结点,那么可计算用属性a 对样本集D 进行划分所获得的"信息增益" (information gain),公式:
G
a
i
n
(
D
,
a
)
=
E
n
t
(
D
)
−
∑
v
=
1
V
∣
D
v
∣
∣
D
∣
E
n
t
(
D
v
)
Gain(D,a)=Ent(D)-\sum_{v=1}^{V}\frac{|D^v|}{|D|}\, Ent(D^v)
Gain(D,a)=Ent(D)−v=1∑V∣D∣∣Dv∣Ent(Dv)
一般而言,信息增益越大,则意味着使用属性a来进行划分所获得的"纯度提升"越大。因此,我们可用信息增益来选择决策树的划分属性。著名的ID3(Iterative Dichotomiser 3)决策树学习算法就是以信息增益为准则来选择划分属性。
1.3增益率
信息增益准则对可取值数目较多的属性有所偏好,为减少这种偏好可能带来的不利影响,著名的C4.5决策树算法不直接使用信息增益,而是使用"增益率" (gain ratio) 来选择最优划分属性。增益率定义为:
G
a
i
n
_
r
a
t
i
o
(
D
,
a
)
=
G
a
i
n
(
D
,
a
)
)
I
V
(
a
)
)
Gain\_ratio(D,a)=\frac{Gain(D,a))}{IV(a))}
Gain_ratio(D,a)=IV(a))Gain(D,a))
需注意的是,增益率准则对可取值数目较少的属性有所偏好,因此,C4.5算法不是直接用增益率,而采用先从候选划分属性中找出信息增益高于平均水平的属性,再从中选择增益率最高的。
1.4基尼指数
CART决策树使用"基尼指数" (Gini index)来选择划分属性,是Classification and Regression Tree(分类和回归树)的简称,分类和回归任务都可用。数据集D的纯度可用基尼指数进行度量。
1.5剪枝处理
剪枝(pruning)是决策树学习算法对付"过拟合"的主要手段。基本策略有"预剪枝" (prepruning)和"后剪枝"(postpruning)。
1.6连续值处理
如何在决策树学习中使用连续属性?
最简单的策略是采用二分法(bi-partition)对连续属性进行离散化处理。
2Sklearn代码实现
决策树是一种用来 classification 和 regression 的无参监督学习方法。其目的是创建一种模型从数据特征中学习简单的决策规则来预测一个目标变量的值。
Sklearn库中类DecisionTreeClassifier分类算法,类DecisionTreeRegressor 回归算法。
决策树算法: ID3, C4.5, C5.0 和 CART,Sklearn库使用 CART 算法的优化版本。
示例:鸢尾花数据集分类任务
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.tree import DecisionTreeClassifier
import sklearn.metrics as sm
from sklearn.model_selection import train_test_split
# 加载数据
iris = datasets.load_iris()
x = iris.data
y = iris.target
fnames = iris.feature_names
# 划分训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=37, test_size=0.2)
# 创建模型
model = DecisionTreeClassifier()
# 训练模型
model.fit(x_train, y_train)
# 预测
pred_y = model.predict(x_test)
acc = model.score(x_test, y_test)
print('score', acc)
# 获取决策树的特征重要性指标
dt_fi = model.feature_importances_
print(dt_fi)
# 模型评分
print(sm.r2_score(y_test, pred_y))
# 绘制数据散点图
plt.title('Iris Decision Tree Classifier')
label_dict = iris.target_names
for label, marker, color in zip(range(0, 3), ('*', 's', 'o'), ('blue', 'red', 'green')):
plt.scatter(x=x_test[y_test == label][:, 0],
y=x_test[y_test == label][:, 1],
marker=marker,
color=color,
label=label_dict[label])
# plt.scatter(x_test[:, 0], x_test[:, 1], c=pred_y, cmap='brg', s=80)
plt.xlabel(fnames[0], fontsize=14)
plt.ylabel(fnames[1], fontsize=14)
# 图例
plt.legend(loc='upper right', fancybox=True)
# 刻度字体大小
plt.tick_params(labelsize=10)
plt.show()
# 柱状图显示特征重要性
plt.figure('Feature Ipltortance')
plt.title('Iris Features')
plt.ylabel('Ipltortance', fontsize=12)
plt.grid(axis='y', linestyle=':')
# 从高到低排序
sorted_indices = np.argsort(dt_fi)[::-1]
x_tick = np.arange(4)
fnames = np.array(fnames)
plt.bar(x_tick, dt_fi[sorted_indices], 0.8, color='dodgerblue', label='DT FI')
plt.xticks(x_tick, fnames[sorted_indices])
plt.legend()
# 自动调整子图参数, 防止坐标轴标签、刻度标签以及标题出现重叠
plt.tight_layout()
plt.show()
运行效果,如下图: