决策树,老熟人了,机器学习最常见的算法之一;GBDT,XGBoost的基础,搞懂它很关键,能给别人讲清楚也就基本搞懂了。
本文默认读者已经学过决策树,算是一个课后笔记,风格是一切从简,希望以后的我能看着开头的思维导图就能在10分钟内给别人讲明白什么是决策树。
我尽量用自己的话来描述,而不是课本的规范化语言,可能会有些不严谨的地方。(主要参考的是西瓜书)
希望能提供一个与网络上其他讲决策树的博文不一样的视角。
决策树的本质
其实就是一堆if-else构成的树,比如下面这颗决策树,就是一颗根据天气和温度决定要不要出门的决策树。
用代码表示就是:
if 天气 == "雨":
print("宅家")
else:
if 温度 == "凉":
print("出门")
else:
print("宅家")
同时可以看到:
-
蓝色的非叶子结点就是用来判断是否要出门的特征
-
绿色的叶子结点就是分类的结果,在机器学习里就是标签
怎么创建一棵决策树
现在已经对决策树有个感性认识了,关键是怎么创建一棵决策树。肯定不能凭空想象暗度陈仓就弄出一棵树来,对于机器学习问题,决策树的构建基于数据集。
这里给出一个数据集,统计了小樱在不同天气和温度的情况下选择出门🏃还是宅家🏠
序号 | 天气 | 温度 | 选择 |
---|---|---|---|
1 | 晴☀️ | 热🔥 | 宅家🏠 |
2 | 晴☀️ | 热🔥 | 宅家🏠 |
3 | 晴☀️ | 热🔥 | 出门🏃 |
4 | 晴☀️ | 凉❄️ | 出门🏃 |
5 | 晴☀️ | 凉❄️ | 出门🏃 |
6 | 雨☔️ | 凉❄️ | 宅家🏠 |
7 | 雨☔️ | 凉❄️ | 宅家🏠 |
8 | 雨☔️ | 凉❄️ | 宅家🏠 |
9 | 雨☔️ | 凉❄️ | 宅家🏠 |
10 | 雨☔️ | 凉❄️ | 宅家🏠 |
然后思路应该是:把困难的问题分解成简单的问题
一下搞出个决策树还是太难了,先来思考下怎么创建树的结点吧,毕竟结点有了,多创几个结点连在一起就是一棵决策树了。
怎么创建结点
之前谈过,非叶子结点就是用来判断标签的特征,上面那个数据集通过简单的统计可以知道:
- 有5天晴天☀️,5天下雨☔️。
- 3天热天🔥,7天凉天❄️。
把特征作为结点,就可以把原本大的数据集,分成小的数据集,这也符合我们解决问题的思路。比如原本完整的数据集是这样的:
数字和图标分别代表样本序号和样本标签。
假设分别以天气和温度来划分数据集,就把大的数据集化成了小的数据集。
分析问题变化的情况:
- 问题数变多了,本来1个大问题,现在是2个小问题
- 数据集变小了
- 特征变少了,用天气划分数据集后,就只剩下温度了,同理用温度划分数据集后只剩天气了。
理论上还是血赚,毕竟算1000个2+2要比算一个21000更容易。
怎么判断哪个特征更适合做结点?
但上面有两种划分方式,凭直觉,应该选哪个特征来划分?
其实不能凭直觉,选法很简单:“尽可能使划分后数据子集的样本更纯。”更纯的意思就是更单一的意思,比如以天气来划分,是下雨时☔️小樱都选择了待家里🏠。这个够单一了吧。
但作为算法,需要有一个公式能算出数据集样本的纯度,这就引出了决策树的几个算法
选择特征的算法
1. ID3算法
信息熵
先拍出一个公式,这个公式就能算数据集样本的纯度。
Ent
(
D
)
=
−
∑
k
=
1
K
p
k
l
o
g
2
p
k
\text{Ent}(D)=-\sum^K_{k=1}p_klog_2p_k
Ent(D)=−k=1∑Kpklog2pk
公式计算的结果叫信息熵(information entropy),看过科幻的话对熵这个概念应该比较好理解,宇宙总在熵增,也就是宇宙总是朝着更混乱的方向前进。信息熵也差不多,样本的信息熵越大,样本越不纯(混乱)。
-
这里的 D D D是数据集,可以理解成上面那张表。
-
K K K表示这个数据集的样本有多少个标签,我们这里 K = 2 K=2 K=2,只有出门和宅家两个标签
-
p k p_k pk表示第k个标签的样本数占总样本数的比例,假设 k = 1 k=1 k=1表示宅家, k = 2 k=2 k=2表示出门,那 p 1 = 7 / 10 = 0.7 p_1=7/10=0.7 p1=7/10=0.7, p 2 = 0.3 p_2=0.3 p2=0.3
这个数据集的信息熵就是:
Ent
(
D
)
=
−
(
0.7
×
l
o
g
2
0.7
+
0.3
×
l
o
g
2
0.3
)
=
0.8813
\text{Ent}(D)=-(0.7\times log_20.7+0.3\times log_20.3)=0.8813
Ent(D)=−(0.7×log20.7+0.3×log20.3)=0.8813
这个公式为什么能衡量样本纯度?
其实还是用例子解释比较好,如果一个数据集,有一类标签的样本非常多,那这个类别的样本数的占比就非常高。可以理解为 p i = 1 p_i=1 pi=1,其他的 p k ∣ k ≠ i = 0 p_{k|k\ne i}=0 pk∣k=i=0。带进上面那个公式,算出的信息熵就是0,也就是样本很纯。
对于 K = 2 K=2 K=2的情况, Ent ( D ) = − ( p l o g 2 p + ( 1 − p ) l o g 2 ( 1 − p ) ) \text{Ent}(D)=-(plog_2p+(1-p)log_2(1-p)) Ent(D)=−(plog2p+(1−p)log2(1−p))
可以看到p接近0或1时信息熵低,样本更纯
总结一下,信息熵的作用:
- 衡量数据集纯不纯
- 信息熵越小,数据集越纯(样本越单一)
信息增益
那接下来的任务就简单了,分别计算以天气、温度划分后的数据子集的信息熵就好了。
使用一个叫信息增益的东西融合计算结果:
Gain
(
D
,
a
)
=
Ent
(
D
)
−
∑
v
=
1
V
∣
D
v
∣
∣
D
∣
Ent
(
D
v
)
\text{Gain}(D,a)=\text{Ent}(D)-\sum_{v=1}^V \frac{|D^v|}{|D|}\text{Ent}(D^v)
Gain(D,a)=Ent(D)−v=1∑V∣D∣∣Dv∣Ent(Dv)
符号解释:
- a a a表示特征,也就是“天气”和“温度”
- V V V表示特征有多少个取值,这里天气和温度都只有2个取值,也就是 V = 2 V=2 V=2
- ∣ D ∣ |D| ∣D∣和 ∣ D v ∣ |D^v| ∣Dv∣,这个表示数据集和数据子集的样本数量。
如果数据子集越纯,数据子集的信息熵就越小,则信息增益越大,因此选信息增益大的特征作为决策树结点
先计算4个子集的信息熵:
Ent
(
D
雨
)
=
−
(
1
×
l
o
g
2
0
+
0
×
l
o
g
2
1
)
=
0
Ent
(
D
晴
)
=
−
(
2
5
×
l
o
g
2
2
5
+
3
5
×
l
o
g
2
3
5
)
=
0.9709
Ent
(
D
凉
)
=
−
(
5
7
×
l
o
g
2
5
7
+
2
7
×
l
o
g
2
2
7
)
=
0.8631
Ent
(
D
热
)
=
−
(
2
3
×
l
o
g
2
2
3
+
1
3
×
l
o
g
2
1
3
)
=
0.9183
\begin{aligned} \text{Ent}(D^{雨})&=-(1\times log_20 + 0\times log_21) =0\\ \text{Ent}(D^{晴})&=-(\frac{2}{5}\times log_2\frac{2}{5} + \frac{3}{5}\times log_2\frac{3}{5}) =0.9709\\ \text{Ent}(D^{凉})&=-(\frac{5}{7}\times log_2\frac{5}{7} + \frac{2}{7}\times log_2\frac{2}{7}) =0.8631\\ \text{Ent}(D^{热})&=-(\frac{2}{3}\times log_2\frac{2}{3} + \frac{1}{3}\times log_2\frac{1}{3}) =0.9183\\ \end{aligned}
Ent(D雨)Ent(D晴)Ent(D凉)Ent(D热)=−(1×log20+0×log21)=0=−(52×log252+53×log253)=0.9709=−(75×log275+72×log272)=0.8631=−(32×log232+31×log231)=0.9183
计算
a
=
天
气
a=天气
a=天气和
a
=
温
度
a=温度
a=温度时的信息增益
Gain
(
D
,
a
=
天
气
)
=
Ent
(
D
)
−
(
∣
D
雨
∣
∣
D
∣
Ent
(
D
雨
)
+
∣
D
晴
∣
∣
D
∣
Ent
(
D
晴
)
)
=
0.8813
−
(
5
10
×
0
+
5
10
×
0.9709
)
=
0.3958
\begin{aligned} \text{Gain}(D,a=天气)&=\text{Ent}(D)-(\frac{|D^雨|}{|D|}\text{Ent}(D^雨) + \frac{|D^晴|}{|D|}\text{Ent}(D^晴))\\ &=0.8813-(\frac{5}{10}\times 0 + \frac{5}{10}\times 0.9709)\\ &=0.3958 \end{aligned}
Gain(D,a=天气)=Ent(D)−(∣D∣∣D雨∣Ent(D雨)+∣D∣∣D晴∣Ent(D晴))=0.8813−(105×0+105×0.9709)=0.3958
Gain ( D , a = 温 度 ) = Ent ( D ) − ( ∣ D 凉 ∣ ∣ D ∣ Ent ( D 凉 ) + ∣ D 热 ∣ ∣ D ∣ Ent ( D 热 ) ) = 0.8813 − ( 7 10 × 0.8631 + 3 10 × 0.9183 ) = 0.0016 \begin{aligned} \text{Gain}(D,a=温度)&=\text{Ent}(D)-(\frac{|D^凉|}{|D|}\text{Ent}(D^凉) + \frac{|D^热|}{|D|}\text{Ent}(D^热))\\ &=0.8813-(\frac{7}{10}\times 0.8631 + \frac{3}{10}\times 0.9183)\\ &=0.0016 \end{aligned} Gain(D,a=温度)=Ent(D)−(∣D∣∣D凉∣Ent(D凉)+∣D∣∣D热∣Ent(D热))=0.8813−(107×0.8631+103×0.9183)=0.0016
可以看到,天气的信息增益更大,所以第一个划分结点就选天气。
其实之后的操作也差不多,数据集更大些,特征更多些,选特征的操作还是一样的。
总结:
- 信息熵怎么算 Ent ( D ) = − ∑ k = 1 K p k l o g 2 p k \text{Ent}(D)=-\sum^K_{k=1}p_klog_2p_k Ent(D)=−∑k=1Kpklog2pk
- 信息增益怎么算 Gain ( D , a ) = Ent ( D ) − ∑ v = 1 V ∣ D v ∣ ∣ D ∣ Ent ( D v ) \text{Gain}(D,a)=\text{Ent}(D)-\sum_{v=1}^V \frac{|D^v|}{|D|}\text{Ent}(D^v) Gain(D,a)=Ent(D)−∑v=1V∣D∣∣Dv∣Ent(Dv)
2. C4.5算法
ID3有个小问题:如果特征取值越多,它的信息增益就越大,比如极端情况下,使用序号来作为决策树结点。
每一个数据子集只有1个样本,显然计算得到的样本子集的信息熵为0。信息增益
G
a
i
n
(
D
,
a
=
序
号
)
=
E
n
t
(
D
)
=
0.8813
Gain(D,a=序号)=Ent(D)=0.8813
Gain(D,a=序号)=Ent(D)=0.8813
那讲道理这是不科学的。
所以要给对这种特征取值多的特征一定的惩罚。
具体是使用信息增益率代替信息增益:
Gain_ratio ( D , a ) = Gain ( D , a ) IV ( a ) \text{Gain\_ratio}(D,a)=\frac{\text{Gain}(D,a)}{\text{IV}(a)} Gain_ratio(D,a)=IV(a)Gain(D,a)
IV ( a ) \text{IV}(a) IV(a)是特征 a a a的固有值(intrinsic value)。特点:
- 特征 a a a的取值数目越多, I V ( a ) IV(a) IV(a)越大
- 很像信息熵
IV ( a ) = − ∑ v = 1 V ∣ D v ∣ ∣ D ∣ l o g 2 ∣ D v ∣ ∣ D ∣ \text{IV}(a)=-\sum_{v=1}^V\frac{|D^v|}{|D|}log_2\frac{|D^v|}{|D|} IV(a)=−v=1∑V∣D∣∣Dv∣log2∣D∣∣Dv∣
可以这么理解,特征取值数目越多,说明你这个样本划分的越混乱。划分得越混乱,那信息增益率就越小。
使用信息增益率计算:
IV
(
a
=
天
气
)
=
−
(
5
10
l
o
g
2
5
10
+
5
10
l
o
g
2
5
10
)
=
1
IV
(
a
=
温
度
)
=
−
(
7
10
l
o
g
2
7
10
+
3
10
l
o
g
2
3
10
)
=
0.8813
IV
(
a
=
序
号
)
=
−
(
1
10
l
o
g
2
1
10
×
10
)
=
3.3219
Gain_ratio
(
D
,
a
=
天
气
)
=
Gain_ratio
(
D
,
a
=
天
气
)
IV
(
a
=
天
气
)
=
0.3958
1
=
0.3958
Gain_ratio
(
D
,
a
=
温
度
)
=
Gain_ratio
(
D
,
a
=
温
度
)
IV
(
a
=
温
度
)
=
0.0016
0.8813
=
0.0018
Gain_ratio
(
D
,
a
=
序
号
)
=
Gain_ratio
(
D
,
a
=
序
号
)
IV
(
a
=
序
号
)
=
0.8813
3.3219
=
0.2653
\begin{aligned} \text{IV}(a=天气)&=-(\frac{5}{10}log_2\frac{5}{10} + \frac{5}{10}log_2\frac{5}{10})=1\\ \text{IV}(a=温度)&=-(\frac{7}{10}log_2\frac{7}{10} + \frac{3}{10}log_2\frac{3}{10})=0.8813\\ \text{IV}(a=序号)&=-(\frac{1}{10}log_2\frac{1}{10} \times10)=3.3219\\ \text{Gain\_ratio}(D,a=天气)&=\frac{\text{Gain\_ratio}(D,a=天气)}{\text{IV}(a=天气)}= \frac{0.3958}{1}=0.3958\\ \text{Gain\_ratio}(D,a=温度)&=\frac{\text{Gain\_ratio}(D,a=温度)}{\text{IV}(a=温度)}= \frac{0.0016}{0.8813}=0.0018 \\ \text{Gain\_ratio}(D,a=序号)&=\frac{\text{Gain\_ratio}(D,a=序号)}{\text{IV}(a=序号)}= \frac{0.8813}{3.3219}=0.2653 \end{aligned}
IV(a=天气)IV(a=温度)IV(a=序号)Gain_ratio(D,a=天气)Gain_ratio(D,a=温度)Gain_ratio(D,a=序号)=−(105log2105+105log2105)=1=−(107log2107+103log2103)=0.8813=−(101log2101×10)=3.3219=IV(a=天气)Gain_ratio(D,a=天气)=10.3958=0.3958=IV(a=温度)Gain_ratio(D,a=温度)=0.88130.0016=0.0018=IV(a=序号)Gain_ratio(D,a=序号)=3.32190.8813=0.2653
经过信息增益率计算之后,还是选择天气作为结点。
3. 基尼指数
我觉得基尼指数和ID3的信息增益其实比较类似,理解了ID3,就很容易理解基尼指数了。
基尼值表示从数据集(有放回?)的随机抽取两个样本,这两个样本类别标记不一样的概率。
基尼值越低,表示抽到两个样本类别一样的概率越高,说明数据集越纯
Gini
(
D
)
=
1
−
∑
k
=
1
K
p
k
2
\text{Gini}(D)=1-\sum_{k=1}^Kp_k^2
Gini(D)=1−k=1∑Kpk2
所以就要求划分子集后,基尼指数越低越好。
基尼指数定义就是:
Gini_index ( D , a ) = ∑ v = 1 V ∣ D v ∣ ∣ D ∣ Gini ( D v ) \text{Gini\_index}(D,a)=\sum_{v=1}^V\frac{|D^v|}{|D|}\text{Gini}(D^v) Gini_index(D,a)=v=1∑V∣D∣∣Dv∣Gini(Dv)
总结:
- 基尼值越低,样本越纯