上一章我们讲的kNN算法,虽然可以完成很多分类任务,但它最大的缺点是无法给出数据的内在含义,而决策树的主要优势就在于数据形式非常容易理解。决策树算法能够读取数据集合,决策树的一个重要任务是为了数据所蕴含的知识信息,因此,决策树可以使用不熟悉的数据集合,并从中提取一系列规则,在这些机器根据数据集创建规则是,就是机器学习的过程。
下面我们就来介绍一下决策树算法。
一、决策树算法
在构造决策树时,第一个需要解决的问题就是,如何确定出哪个特征在划分数据分类是起决定性作用,或者说使用哪个特征分类能实现最好的分类效果。这样,为了找到决定性的特征,划分川最好的结果,我们就需要评估每个特征。当找到最优特征后,依此特征,数据集就被划分为几个数据子集,这些数据自己会分布在该决策点的所有分支中。此时,如果某个分支下的数据属于同一类型,则该分支下的数据分类已经完成,无需进行下一步的数据集分类;如果分支下的数据子集内数据不属于同一类型,那么就要重复划分该数据集的过程,按照划分原始数据集相同的原则,确定出该数据子集中的最优特征,继续对数据子集进行分类,直到所有的特征已经遍历完成,或者所有叶结点分支下的数据具有相同的分类。
创建分支的伪代码createBranch()如下:
if so return 类标签;
else
寻找划分数据集的最好特征
划分数据集
创建分支结点
for 每个分支结点
调用函数createBranch并增加返回结点到分支结点中//递归调用createBranch()
return 分支结点
下面是决策树算法的一般流程:
- 收集数据
- 准备数据
- 分析数据
- 训练数据
- 测试算法
- 使用算法
二、最好的特征选取规则:信息增益
划分数据集的大原则是:将无序的数据变得更加有序。在划分数据集前后信息发生的变化称为信息增益,如果我们知道如何计算信息增益,就可以计算每个特征值划分数据集获得的信息增益,而获取信息增益最高的特征就是最好的特征。
接下来,我们讲学习如何计算信息增益,而提到信息增益我们又不得不提到一个概念"香农熵",或者简称熵。熵定义为信息的期望值。
如果待分类的事物可能会出现多个结果x,则第i个结果xi发生的概率为p(xi),那么我们可以由此计算出xi的信息熵为l(xi)=p(xi)log(1/p(xi))=-p(xi)log(p(xi))
那么,对于所有可能出现的结果,事物所包含的信息希望值(信息熵)就为:H=-Σp(xi)log(p(xi)),i属于所有可能的结果
这样,假设利用数据集中某一特征A对数据集D(D的分类类别有n种)进行分类,而特征A取值有k种,那么此时,利用特征A对数据集进行分类的信息增益为:
信息增益H(D,A)=原始数据集的信息熵H(D)-特征A对数据集进行划分后信息熵H(D/A)
其中H(D/A)=∑|Aj|/|D|*H(Aj),j属于A的k种取值,|Aj|和|D|分别表示,特征A第j种取值的样本数占所有取值样本总数的比例,以及数据集的样本总数
三、构造决策树
在知道了如何选取划分数据的最优特征后,我们就可以依据此来构建决策树了。
计算数据集的香农熵:
# 计算给定数据集的熵
def calEnt(dataSet):
# 获取数据集的行数
numEntries = len(dataSet)
# 设置字典的数据结构
labelCounts = {
}
# 提取数据集每一行的特征向量
for featVec in dataSet:
# 获取特征向量的最后一列标签
currentLabel = featVec[-1]
# 检测字典的关键字key是否存在该标签
# 如果不存在keys()关键字
if currentLabel not in labelCounts.keys():
# 当前标签/0键值对存入字典
labelCounts[currentLabel] = 0
# 否则将当前标签对应的键值加1
labelCounts[currentLabel]+=1
# 初始化熵为0
Ent = 0.0
# 对于数据集中所有的分类类别
for key in labelCounts:
# 计算各类别出现的频率
prob = float(labelCounts[key]/numEntries)
# 计算各个类别信息期望值
Ent -= prob*log(prob, 2)
# 返回熵
return Ent
创建数据集:
def createDataSet():
dataSet = [[1, 1, 'yes'], [1, 1, 'yes'], [1