文章目录
决策树是很好理解的,如下图。

构造决策树的关键是找到最优划分属性,这个过程中需要解决两个基本问题:
- 【选择划分属性】若样本有N个属性,那么有 N ! N! N!种属性划分的情况,采用穷举法是不可接受的;
- 【判定准则】需要有一种指标来判断属性划分的好坏。
然后还需要解决一些其它问题:
- 连续属性离散化
- 剪枝
公式符号约定
为了便于讨论,有必要统一公式语言,这里采用西瓜书中的公式语言。
样本集合为
D
D
D,
D
D
D的信息熵为
Ent
(
D
)
\operatorname{Ent}(D)
Ent(D)。
假定选取的属性
a
a
a有
V
V
V个可能的取值
{
a
1
,
a
2
,
.
.
.
,
a
V
}
\{a^1, a^2, ..., a^V\}
{a1,a2,...,aV},则用
a
a
a可以将集合划分为
V
V
V份,第
v
v
v份是属性
a
a
a取值为
a
v
a^v
av的所有样本集合记做
D
v
D^v
Dv。
集合加上绝对值就是值集合的大小,如
∣
D
∣
|D|
∣D∣表示集合中含有的样本数量。
ID3算法
ID3算法会执行多轮,每轮找一个“当前最优属性”。不难发现,循环N轮则会生成一个高度为N的决策树。
理论学习
【选择划分属性】ID3每轮选择的属性只是当前的最优属性,因此是一种贪心算法,这并不能保证最终选择的划分属性是最优的。但我们不能怪ID3,因为穷举法的性能是不可接受的,所以贪心法已经是一个很不错的妥协了。
例如对于有ABCDE
5个属性的样本集,前两轮选择了划分属性CE
,第三轮认为CEA
比CEB
和CED
都要好,那么根据贪心法就会选择CEA
,贪心法只考虑眼前的最优解。
【判定准则】ID3采用信息增益(information gain) 来判定属性选取的好坏,这借助于香农提出的信息论。
在信息论中信息熵(information entropy)越小则纯度越高,信息熵的公式自己查。
信息增益(information gain)是用划分前的信息熵减去划分后的信息熵,由于划分后集合会被划分为多份,因此划分后集合的信息熵需要加权平均后再比较。
信息熵计算公式:
Ent
(
D
)
=
−
∑
k
=
1
∣
Y
∣
p
k
log
2
p
k
\operatorname{Ent}(D)=-\sum_{k=1}^{|\mathcal{Y}|} p_{k} \log _{2} p_{k}
Ent(D)=−k=1∑∣Y∣pklog2pk
信息增益计算公式:
Gain
(
D
,
a
)
=
Ent
(
D
)
−
∑
v
=
1
V
∣
D
v
∣
∣
D
∣
Ent
(
D
v
)
\operatorname{Gain}(D, a)=\operatorname{Ent}(D)-\sum_{v=1}^{V} \frac{\left|D^{v}\right|}{|D|} \operatorname{Ent}\left(D^{v}\right)
Gain(D,a)=Ent(D)−v=1∑V∣D∣∣Dv∣Ent(Dv)
总结,ID3算法的关键点:贪心算法、信息增益、加权平均。
代码实现(Python)
信息熵计算函数:
ID3算法实现:
C4.5算法
ID3采用信息增益准则,缺点是会偏好取值数目较多的属性。例如ID3偏向选取职业而不是性别,因为职业有许多种取值这会在信息增益的计算中有优势。
C4.5对ID3做了改进,它采用信息增益率作为准则。
理论学习
信息增益率是添加了 IV ( a ) \operatorname{IV}(a) IV(a)作为分母,我们把它称为 a a a的固有值,固有值的计算公式和信息熵公式其实是一样的,属性 a a a的取值越多则固有值越大。
信息增益率计算公式:
Gain_ratio
(
D
,
a
)
=
Gain
(
D
,
a
)
IV
(
a
)
\operatorname{Gain\_ratio}(D, a)=\frac{\operatorname{Gain}(D, a)}{\operatorname{IV}(a)}
Gain_ratio(D,a)=IV(a)Gain(D,a)
固有值计算公式:
IV
(
a
)
=
−
∑
v
=
1
V
∣
D
v
∣
∣
D
∣
log
2
∣
D
v
∣
∣
D
∣
\operatorname{IV}(a)=-\sum_{v=1}^{V} \frac{\left|D^{v}\right|}{|D|} \log _{2} \frac{\left|D^{v}\right|}{|D|}
IV(a)=−v=1∑V∣D∣∣Dv∣log2∣D∣∣Dv∣
虽然信息增益率解决了ID3的问题(即偏好取值数量大的属性),但它的问题刚好相反,它偏好取值数量小的属性。【选取划分属性】为了解决这一问题,C4.5先选出信息增益高于平均值的属性,然后再从中选信息增益率最高的,这个办法虽然治标不治本但还是很有效的。
代码实现(Python)
信息增益率计算函数:
C4.5算法实现:
CART算法
理论学习
CART采用基尼指数(Gini index)作为属性划分准则,基尼值
Gini
(
D
)
\operatorname{Gini}(D)
Gini(D)越小则数据集的纯度越高。
Gini
(
D
)
=
∑
k
=
1
∣
Y
∣
∑
k
′
≠
k
p
k
p
k
′
=
1
−
∑
k
=
1
∣
Y
∣
p
k
2
\begin{aligned} \operatorname{Gini}(D) &=\sum_{k=1}^{|\mathcal{Y}|} \sum_{k^{\prime} \neq k} p_{k} p_{k^{\prime}} \\ &=1-\sum_{k=1}^{|\mathcal{Y}|} p_{k}^{2} \end{aligned}
Gini(D)=k=1∑∣Y∣k′̸=k∑pkpk′=1−k=1∑∣Y∣pk2
而属性
a
a
a的基尼指数的计算公式如下。
Gini_index
(
D
,
a
)
=
∑
v
=
1
V
∣
D
v
∣
∣
D
∣
Gini
(
D
v
)
\operatorname{Gini\_index}(D, a)=\sum_{v=1}^{V} \frac{\left|D^{v}\right|}{|D|} \operatorname{Gini}\left(D^{v}\right)
Gini_index(D,a)=v=1∑V∣D∣∣Dv∣Gini(Dv)
代码实现(Python)
使用sklearn库
import numpy as np
from sklearn import tree
from graphviz import Source
if __name__ == '__main__':
np.random.seed(42)
X = np.random.randint(10, size=(100, 4))
Y = np.random.randint(2, size=100)
a = np.column_stack((Y, X))
clf = tree.DecisionTreeClassifier(criterion='gini', max_depth=3)
clf = clf.fit(X, Y)
graph = Source(tree.export_graphviz(clf, out_file=None))
graph.format = 'png'
graph.render('cart_tree', view=True)
剪枝操作解决过拟合问题
剪枝分为预剪枝和后剪枝两种。预剪枝算法时间开销小,但有欠拟合的风险。后剪枝算法耗时久,但生成的模型往往优于预剪枝。
连续属性离散化
决策树的树形结构决定了它很难处理连续型属性(如年龄、收入、身高),因此需要进行离散化。
在C4.5中采取了最简单的离散化方法:二分法,对于连续型属性a,它还会寻找一个分界点t,分为小于t和大于t两类。假如样本在属性a上有n种取值,那么t的取值就有n-1种可能,如下
T
a
=
{
a
i
+
a
i
+
1
2
∣
1
⩽
i
⩽
n
−
1
}
T_{a}=\left\{\frac{a^{i}+a^{i+1}}{2} | 1 \leqslant i \leqslant n-1\right\}
Ta={2ai+ai+1∣1⩽i⩽n−1}