机器学习实战之决策树(一)构造决策树
决策树(一)构造决策树
- 1.简介
- 1.1 优缺点
- 1.2 流程
- 1.3 决策树的构造
- 1.4 海洋生物数据
- 2.信息增益
- 2.1 几个概念
- 2.2 计算给定数据集的熵
- 3 划分数据集
- 3.1 按照给定特征划分数据集
- 3.2 选择最好的数据集划分方式
- 4 递归构建决策树
- 4.1 多数表决
- 4.2 创建树的函数代码
转载请注明作者和出处:https://blog.csdn.net/weixin_45814668
微信公众号:qiongjian0427
知乎:https://www.zhihu.com/people/qiongjian0427
Github代码获取:https://github.com/qiongjian/Machine-learning/
Python版本: Python3.x
1.简介
本文内容基本来自机器学习实战这本书。
k-近邻算法最大的缺点就是无法给出数据的内在含义,决策树的主要优势就在于数据形式非常容易理解。
下图所示决策树,长方形代表判断模块(decision block),椭圆形代表终止模块(terminating block),表示已经得出结论,可以终止运行。从判断模块引出的左右箭头称作分支(branch),它可以到达另一个判断模块或者终止模块。
1.1 优缺点
优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据。
缺点:可能会产生过度匹配问题。
适用数据类型:数值型和标称型。
1.2 流程
(1) 收集数据:可以使用任何方法。
(2) 准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化。
(3) 分析数据:可以使用任何方法,构造树完成之后,我们应该检查图形是否符合预期。
(4) 训练算法:构造树的数据结构。
(5) 测试算法:使用经验树计算错误率。
(6) 使用算法:此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义。
1.3 决策树的构造
构造决策树需要解决的第一个问题就是,当前数据集那个特征在划分数据时起决定性作用。为了找到这个特征,需要对所有的特征进行评估。
(1)选择一个决定性特征,将训练数据集分成子集,这些子集分布在第一个决策点的分支上。
(2) 如果某个分支上的子集属于同一类,则说明这个子集在当前条件下是最好的分类,不需要再进行分割。
(3)如果某个分支上的子集不属于同一类,说明子集不能够被正确的分类,那么就对这些子集选择新的特征,继续分割,直至所有子集都属于同一类。
创建分支的伪代码createBranch()如下:
检测数据集中的每个子项是否属于同一分类:If so return 类标签Else寻找划分数据集的最好特征划分数据集创建分支节点for 每个划分的子集调用函数createBranch并增加返回结果到分支节点中 return 分支节点
1.4 海洋生物数据
本文使用ID3算法划分数据集,每次划分数据集时我们只选取一个特征属性。
下表展示了海洋生物数据,特征包括:不浮出水面是否可以生存,和是否有脚蹼。
现在我们想要决定依据第一个特征还是第二个特征划分数据。在回答这个问题之前,我们必须采用量化的方法判断如何划分数据。
表1:海洋生物数据
个数 | 不浮出水面是否可以生存 | 是否有脚蹼 | 属于鱼类 |
---|---|---|---|
1 | 是 | 是 | 是 |
2 | 是 | 是 | 是 |
3 | 是 | 否 | 否 |
4 | 否 | 是 | 否 |
5 | 否 | 是 | 否 |
2.信息增益
2.1 几个概念
(1)划分数据的大原则:将无序的数据变得更加有序。
(2)信息论:量化处理信息的分支科学。
(3)信息增益:划分数据之前之后信息发生的变化。信息增益最高的特征就是最好的选择。
(4)香农熵(简称熵entropy):集合信息度量的方式。定义为信息的期望值。来源于信息论之父克劳德.香农。
(5)如果待分类的事务可能划分在多个分类之中,则符号Xi的信息定义为:
p(xi)是选择该分类的概率。
为了计算熵,我们需要计算所有类别所有可能值包含的信息期望值,通过下面的公式得到:
n是分类的数目。
2.2 计算给定数据集的熵
python代码如下:
from math import log
def calcShannonEnt(dataSet):# 求list的长度,表示计算参与训练的数据量numEntries = len(dataSet)# 计算分类标签label出现的次数labelCounts = {}# the the number of unique elements and their occurancefor featVec in dataSet:# 将当前实例的标签存储,即每一行数据的最后一个数据代表的是标签currentLabel = featVec[-1]# 为所有可能的分类创建字典,如果当前的键值不存在,则扩展字典并将当前键值加入字典。每个键值都记录了当前类别出现的次数。if currentLabel not in labelCounts.keys():labelCounts[currentLabel] = 0labelCounts[currentLabel] += 1# 对于 label 标签的占比,求出 label 标签的香农熵shannonEnt = 0.0for key in labelCounts:# 使用所有类标签的发生频率计算类别出现的概率。prob = float(labelCounts[key])/numEntries# 计算香农熵,以 2 为底求对数shannonEnt -= prob * log(prob, 2)return shannonEnt
利用createDataSet()函数得到表1中鱼类的鉴定数据集:
def createDataSet():dataSet = [[1, 1, 'yes'],[1, 1, 'yes'],[1, 0, 'no'],[0, 1, 'no'],[0, 1, 'no']]labels = ['no surfacing', 'flippers']return dataSet, labels
运行结果:
myDat,labels=createDataSet()
print(myDat)
print(calcShannonEnt(myDat))
熵越高则混合的数据越多。
我们可以在数据集中添加更多的分类,观察熵是如何变化的。
如添加第三个名为maybe的分类,测试熵的变化:
3 划分数据集
3.1 按照给定特征划分数据集
添加 splitDataSet 函数,按照给定特征划分数据集
def splitDataSet(dateSet, axis, value): #dateSet: 待划分的数据集,axis: 划分数据集的特征,value: 特征的返回值retDataSet = [] # 因python不用考虑内存分配问题,在函数中传递的是列表的引用,所以需声明一个新列表对象for featVec in dateSet:if featVec[axis] == value: # 该特征值等于判断值reducedFeatVec = featVec[:axis] reducedFeatVec.extend(featVec[axis+1:]) #上一步和这一步是排除掉特征值retDataSet.append(reducedFeatVec) # 加入返回的数据集return retDataSet
这里说明python中extend()和append()的不同
假定存在两个列表a和b
3.2 选择最好的数据集划分方式
接下来将遍历整个数据集,循环计算香农熵和 splitDataSet 函数,找到最好的特征划分方式。熵计算将会告诉我们如何划分数据集时最好的数据组织方式。
在函数中调用的数据需要满足两个要求:
第一个要求是,数据必须是一种由列表 元素组成的列表,而且所有的列表元素都要具有相同的数据长度;
第二个要求是,数据的最后一列或者每个实例的最后一个元素是当前实例的类别标签。
数据集满足一旦满足上述要求,我们就可以在函数的第一行判定当前数据集包含多少特征属性。
添加 chooseBestFeatureToSplit 函数,选择最好的数据集划分方式:
def chooseBestFeatureToSplit(dataSet):numFeatures = len(dataSet[0]) - 1baseEntropy = calcShannonEnt(dataSet) # 原始的香农熵bestInfoGain = 0.0bestFeature = -1for i in range(numFeatures):# 创建唯一的分类标签列表featList = [example[i] for example in dataSet]uniqueVals = set(featList)newEntropy = 0.0# 计算每种划分方式的信息熵for value in uniqueVals:subDataSet = splitDataSet(dataSet, i, value)prob = len(subDataSet) / float(len(dataSet)) # 概率newEntropy += prob * calcShannonEnt(subDataSet) # 香农熵,也就是信息量infoGain = baseEntropy - newEntropy # 该特征的熵# 计算最好的信息增益if infoGain > bestInfoGain:bestInfoGain = infoGainbestFeature = ireturn bestFeature
测试输出结果
代码运行结果告诉我们,第0个特征是最好的用于划分数据集的特征。
数据集中的数据来源于表1,如果我们按照第一个特征属性划分数据,也就是说第一个特征是1的放在一 个组, 第一个特征是0的放在另一个组,数据一致性如何?按照上述的方法划分数据集,第一个特征 为1的海洋生物分组将有两个属于鱼类,一个属 于非鱼类;另个分组则全部属 于非鱼类。
如果按照第二个特征分组,结果又是怎么样呢?第一个海洋动物分组将有两个属于鱼类,两个属于非鱼类;另一个分组则只有一个非鱼类。
第一种划分很好地处理 了相关数据。
4 递归构建决策树
4.1 多数表决
从数据集构造决策树算法所需要的子功能模块,其工作原理如下:
(1)得到原始数据集。
(2)基于最好的属性值划分数据集,由于特征值可能多余两个,因此可能存在大于两个分支的数据集划分。
(3)第一次划分之后,数据将被向下传递到树分支的下一个节点,在这个节点上,我们可以再次划分数据。因此可以采用递归的原则处理数据集。
递归结束的条件是:程序遍历完所有划分数据集的属性,或者每个分支下的所有实例都具有相同的分类。如果所有实例具有相同的分类,则得到一个叶子节点或者终止块。任何到达叶子节点的数据必然属于叶子节点的分类。
如果数据集已经处理了所有属性,但是类标签依然不是唯一的,此时我们需要决定如何定义该叶子节点,在这种情况下,我们通常会采用多数表决的方法决定叶子节点的分类。
import operator
def majorityCnt(classList):#分类计数classCount = {}for vote in classList:if vote not in classCount.keys(): classCount[vote] = 0classCount[vote] += 1 # 取出次数最多的分类名称sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)return sortedClassCount[0][0]
4.2 创建树的函数代码
添加 createTree 函数,创建树:
def createTree(dataSet, labels):# 创建列表变量classList = [example[-1] for example in dataSet]# 判断:类别完全相同则停止继续划分if classList.count(classList[0]) == len(classList):return classList[0]# 遍历完所有特征时返回出现次数最多的类别if len(dataSet[0]) == 1:return majorityCnt(classList)# 取出最好的分类特征bestFeat = chooseBestFeatureToSplit(dataSet)bestFeatLable = labels[bestFeat]#储存树所有的信息myTree = {bestFeatLable:{}}del(labels[bestFeat])# 得到列表包含的所有属性值featValues = [example[bestFeat] for example in dataSet]uniqueVals = set(featValues)# 递归创建树for value in uniqueVals:subLabels = labels[:]myTree[bestFeatLable][value] = createTree(splitDataSet(dataSet, bestFeat, value), subLabels)return myTree
代码运行结果:
变量myTree包含了很多代表树结构信息的嵌套字典,从左边开始,第一个关键字no surfacing是第一个划分数据集的特征名称,该关键字的值也是另一个数据字典。
第二个关键字是no surfacing特征划分的数据集,这些关键字的值是no surfacing节点的子节点。
这些值可能是类标签,也可能是另一个数据字典。如果值是类标签,则该子节点是叶子节点;如果值是另一个数据字典,则子节点是一个判断节点, 这种格式结构不断重复就构成了整棵树。
本节的例子中,这棵树包含了3个叶子节点以及2个判断节点。
END
机器学习实战之决策树(一)构造决策树相关推荐
- 【阿旭机器学习实战】【13】决策树分类模型实战:泰坦尼克号生存预测
[阿旭机器学习实战]系列文章主要介绍机器学习的各种算法模型及其实战案例,欢迎点赞,关注共同学习交流. 本文用机器学习中的决策树分类模型对泰坦尼克号生存项目进行预测. 关于决策树的详细介绍及原理参见前一 ...
- 《机器学习实战》——第3章 决策树
3.1 决策树的构造 优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据. 缺点:可能会产生过度匹配的问题. 适用数据类型:数值型和标称型. 创建分支的伪代码函数 c ...
- 决策树之构造决策树(一)
决策树时一种常用的数据挖掘算法,其优势在于数据形式非常容易理解,缺点在于很可能产生过度匹配的问题(即过拟合问题,如何解决过拟合问题待续.......).决策树的一个重要任务就是为了理解数据中所蕴含的数 ...
- 【机器学习实战】第3章 决策树(Decision Tree)
第3章 决策树 <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/ ...
- 机器学习实战(MachineLearinginAction) 第三章 决策树
决策树(decision tree)很流行的一个原因就是对机器学习算法的知识要求很低. 决策模块(decision block) 终止模块(terminating block):表示已经得出结论,可以 ...
- 【机器学习实战】第3章 决策树(DecisionTree)
第3章 决策树 <script type="text/javascript" src=" http://cdn.mathjax.org/mathjax/latest ...
- 读书笔记:机器学习实战(2)——章3的决策树代码和个人理解与注释
首先是对于决策树的个人理解: 通过寻找最大信息增益(或最小信息熵)的分类特征,从部分已知类别的数据中提取分类规则的一种分类方法. 信息熵: 其中,log底数为2,额,好吧,图片我从百度截的.. 这里只 ...
- 机器学习实战(代码部分)-- 决策树(Ⅰ 计算给定数据的香农熵)
3-1 计算给定数据的香农熵 1. 算法思想 (1)计算出总共有多少组数据(返回数据行数). (2)初始化分类字典和香农熵,其中分类字典初始化为空,香农熵初始化为0. (3)计算所有数据的类别(假定为 ...
- Python《机器学习实战》读书笔记(三)——决策树
第三章 决策树 引言 3-1 决策树的构造 3-1-1 信息增益 3-1-2 划分数据集 3-1-3 递归构建决策树 3-2 在Python中使用Matplotlib注解绘制树形图 3-2-1 Mat ...
- 《机器学习实战》学习笔记(三):决策树
欢迎关注WX公众号:[程序员管小亮] [机器学习]<机器学习实战>读书笔记及代码 总目录 https://blog.csdn.net/TeFuirnever/article/details ...
最新文章
- oracle virtualbox 添加共享硬盘
- 线性代数可以速成吗_广播/学习吉他速成靠谱吗?真的可以速成吗?
- k8s command args
- Stream流中的常用方法_forEach
- 关于sqlserver 2008 无法远程连接的问题
- 树莓派搭建局域网内的静态网页
- Linux查看系统自启动服务
- Android -Recovery
- 如何解决移动硬盘弹出时报错:设备正在使用中
- 使用8080并口协议驱动NT35510LCD显示屏
- Word排版-页眉上的横线
- unsigned char型整数
- 收银系统可以管理童装店衣服不同的尺码吗?
- Centos8 安装 MySQL8.0.26
- 从一线码农到阿里技术合伙人 P11的少林扫地僧多隆,人家牛逼是种习惯
- S5PV210开发系列五 sd卡驱动实现
- 面试的时候突然遇到答不上的问题怎么办?
- 使用zuma免费建站后应如何维护网站?
- php mmseg,xsplit A PHP extension for Chinese segmentation using MMSEG algorithm[zz]
- [DP] BZOJ 4244 邮戳拉力赛