决策树理论部分
前言
决策树(decsision tree)是一类常见的机器学习算法。以周志华老师《机器学习》中西瓜数据集为例,我们希望从给定训练集中学得一个模型用于对测试集分类。本文将详细解读书中代码,并使用sklearn库实现管道泄漏信号四分类。
编号 | 色泽 | 根蒂 | 敲声 | 纹理 | 脐部 | 触感 | 好瓜 |
---|---|---|---|---|---|---|---|
1 | 青绿 | 蜷缩 | 浊响 | 清晰 | 凹陷 | 硬滑 | 是 |
2 | 乌黑 | 蜷缩 | 沉闷 | 清晰 | 凹陷 | 硬滑 | 是 |
3 | 乌黑 | 蜷缩 | 浊响 | 清晰 | 凹陷 | 硬滑 | 是 |
4 | 青绿 | 蜷缩 | 沉闷 | 清晰 | 凹陷 | 硬滑 | 是 |
5 | 浅白 | 蜷缩 | 浊响 | 清晰 | 凹陷 | 硬滑 | 是 |
6 | 青绿 | 稍蜷 | 浊响 | 清晰 | 稍凹 | 软粘 | 是 |
7 | 乌黑 | 稍蜷 | 浊响 | 稍糊 | 稍凹 | 软粘 | 是 |
8 | 乌黑 | 稍蜷 | 浊响 | 清晰 | 稍凹 | 硬滑 | 是 |
9 | 乌黑 | 稍蜷 | 沉闷 | 稍糊 | 稍凹 | 硬滑 | 否 |
10 | 青绿 | 硬挺 | 清脆 | 清晰 | 平坦 | 软粘 | 否 |
11 | 浅白 | 硬挺 | 清脆 | 模糊 | 平坦 | 硬滑 | 否 |
12 | 浅白 | 蜷缩 | 浊响 | 模糊 | 平坦 | 软粘 | 否 |
13 | 青绿 | 稍蜷 | 浊响 | 稍糊 | 凹陷 | 硬滑 | 否 |
14 | 浅白 | 稍蜷 | 沉闷 | 模糊 | 凹陷 | 硬滑 | 否 |
15 | 乌黑 | 稍蜷 | 浊响 | 清晰 | 稍凹 | 软粘 | 否 |
16 | 浅白 | 蜷缩 | 浊响 | 模糊 | 平坦 | 硬滑 | 否 |
17 | 青绿 | 蜷缩 | 沉闷 | 稍糊 | 稍凹 | 硬滑 | 否 |
1.1 信息熵
“信息熵”是度量样本集合纯度最常用的一种指标。假定当前样本集合D中第k类样本所占的比例是pk,则D的信息熵定义为
E n t ( D ) = − ∑ k = 1 ∣ y ∣ p k log 2 p k Ent\left( D\right) =-\sum ^{\left| y\right| }_{k=1}p_{k}\log _{2}p_{k} Ent(D)=−k=1∑∣y∣pklog2pk
以表中数据集为例,共有17个训练样例,用于学习一颗能预测没剖开的西瓜是不是好瓜的决策树。显然|y|=2,在决策树开始学习时,根结点包含D中的所有样例,其中正例p1=8/17,反例p2=9/17,根据公式可算出信息熵为
E n t ( D ) = − ∑ k = 1 2 p k log 2 p k = − ( 8 17 log 2 8 17 + 9 17 log 2 9 17 ) = 0.998 \begin{aligned}Ent\left( D\right) =-\sum ^{2}_{k=1}p_{k}\log _{2}p_{k} =-\left( \dfrac {8}{17}\log _{2}\dfrac {8}{17}+\dfrac {9}{17}\log _{2}\dfrac {9}{17}\right) =0.998\end{aligned} Ent(D)=−k=1∑2pklog2pk=−(178log2178+179log2179)=0.998
1.1.1 代码实现
在编写代码之前,先对数据集进行标签化
色泽:0代表浅白 1代表青绿 2代表乌黑
根蒂:0代表蜷缩 1代表稍蜷 2代表硬挺
敲声:0代表沉闷 1代表浊响 2代表清脆
纹理:0代表清晰 1代表稍糊 2代表模糊
脐部:0代表凹陷 1代表稍凹 2代表平坦
触感:0代表硬滑 1代表软粘
好瓜:‘yes’代表好瓜,‘no’代表坏瓜
确定好这些之后,我们创建数据集并计算信息熵
from math import log
import operator
def createDataSet():
dataSet = [[1,0,1,0,0,0,'yes'],
[2,0,0,0,0,0,'yes'],
[2,0,1,0,0,0,'yes'],
[1,0,1,0,0,0,'yes'],
[0,0,1,0,0,0,'yes'],
[1,1,1,0,1,1,'yes'],
[2,1,1,1,1,1,'yes'],
[2,1,1,0,1,0,'yes'],
[2,1,0,1,1,0,'no'],
[1,2,2,0,2,1,'no'],
[0,2,2,2,2,1,'no'],
[0,0,1,2,2,1,'no'],
[1,1,1,1,0,0,'no'],
[0,1,0,1,0,0,'no'],
[2,1,1,0,1,1,'no'],
[0,0,1,1,1,1,'no'],
[1,0,0,1,1,0,'no']]
labels = ['色泽','根蒂','敲声','纹理','脐部','触感']
return dataSet,labels
def calcShannonEnt(dataSet):
numEntries = len(dataSet) #数据集的行数
labelCounts = {
} #生成字典
for featVec in dataSet:
currentLabel = featVec[-1] #提取标签
if currentLabel not in labelCounts.keys():
labelCounts[currentLabel] = 0 #标签不在字典中,就生成这个标签的键值对
labelCounts