python机器学习之决策树分类详解
作者:Jeffrey_Cui 发布时间:2023-04-28 14:31:05
决策树分类与上一篇博客k近邻分类的最大的区别就在于,k近邻是没有训练过程的,而决策树是通过对训练数据进行分析,从而构造决策树,通过决策树来对测试数据进行分类,同样是属于监督学习的范畴。决策树的结果类似如下图:
图中方形方框代表叶节点,带圆边的方框代表决策节点,决策节点与叶节点的不同之处就是决策节点还需要通过判断该节点的状态来进一步分类。
那么如何通过训练数据来得到这样的决策树呢?
这里涉及要信息论中一个很重要的信息度量方式,香农熵。通过香农熵可以计算信息增益。
香农熵的计算公式如下:
p(xi)代表数据被分在i类的概率,可以通过计算数据集中i类的个数与总的数据个数之比得到,计算香农熵的python代码如下:
from math import log
def calcShannonEnt(dataSet):
numEntries=len(dataSet)
labelCounts={}
for featVec in dataSet:
currentLabel=featVec[-1]
if currentLabel not in labelCounts.keys():
labelCounts[currentLabel]=0
labelCounts[currentLabel]+=1
shannonEnt=0.0
for key in labelCounts:
prob=float(labelCounts[key])/numEntries
shannonEnt-=prob*log(prob,2)
return shannonEnt
一般来说,数据集中,不同的类别越多,即信息量越大,那么熵值越大,通过计算熵,就可以知道选择哪一个特征能够最好的分开数据,这个特征就是一个决策节点。
下面就可以根据训练数据开始构造决策树。
首先编写一个根据给定特征划分数据集的函数:
#划分数据集,返回第axis轴为value值的数据集
def splitDataSet(dataset,axis,value):
retDataSet=[]
for featVec in dataset:
if featVec[axis]==value:
reducedFeatVec=featVec[:]
del(reducedFeatVec[axis])
retDataSet.append(reducedFeatVec)
return retDataSet
下面找出数据集中能够最好划分数据的那个特征,它的原理是计算经过每一个特征轴划分后的数据的信息增益,信息增益越大,代表通过该特征轴划分是最优的。
#选择最好的数据集划分方式,返回最佳的轴
def chooseBestFeatureToSplit(dataset):
numFeatures=len(dataset[0])-1
baseEntrypy=calcShannonEnt(dataset)
bestInfoGain=0.0
bestFeature=-1
for i in range(numFeatures):
featList=[example[i] for example in dataset]
uniqueVals=set(featList)
newEntrypy=0.0
for value in uniqueVals:
subDataSet=splitDataSet(dataset,i,value)
prob=len(subDataSet)/float(len(dataset))
newEntrypy+=prob*calcShannonEnt(subDataSet)
infoGain=baseEntrypy-newEntrypy #计算信息增益,信息增益最大,就是最好的划分
if infoGain>bestInfoGain:
bestInfoGain=infoGain
bestFeature=i
return bestFeature
找出最优的划分轴之后,便可以通过递归来构建决策树,递归有两个终止条件,第一个是程序遍历完所有划分数据集的特征轴,第二 个是每个分支下的所有实例都有相同的分类。那么,这里有一个问题,就是当遍历完所有数据集时,分出来的数据还不是同一类别,这种时候,一般选取类别最多的作为该叶节点的分类。
首先编写一个在类别向量中找出类别最多的那一类:
#计算类型列表中,类型最多的类型
def majorityCnt(classList):
classCount={}
for vote in classList:
if vote not in classCount.keys():
classCount[vote]=0
classCount[vote]+=1
sortedClassCount=sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]
递归创建决策树:
#根据训练数据创建树
def createTree(dataSet,labels):
myLabels=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)
bestFeatLabel=myLabels[bestFeat]
myTree={bestFeatLabel:{}}
del(myLabels[bestFeat])
featValue=[example[bestFeat] for example in dataSet]
uniqueVal=set(featValue)
for value in uniqueVal:
subLabels=myLabels[:]
myTree[bestFeatLabel][value]=createTree(splitDataSet(dataSet,bestFeat,value),subLabels)
return myTree
将上述代码保存到tree.py中,在命令窗口输入以下代码:
>>> dataSet=[[1,1,'yes'],
[1,1,'yes'],
[1,0,'no'],
[0,1,'no'],
[0,1,'no']]
>>> labels=['no sufacing','flippers']
>>> tree.createTree(dataSet,labels)
{'no sufacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}
就得到了决策树的结构,可以画出树的结构图
上面数据的实际意义是通过生物特征,来判断是否属于鱼类,第一列数据中1代表在水中可以生存,0代表在水中不可以生存。第二列中1代表有脚蹼,0代表没有脚蹼。yes是鱼类,no不是鱼类。label是训练数据中每一列代表的意义。那么通过训练数据我们就构造出了决策树,由图可知,我们首先可以根据第一列特征,即在水中是否可以生存来进行第一步判断,不可以生存的肯定不是鱼类,可以生存的还要看是否有脚蹼,有脚蹼的才是鱼类。
不难看出,决策树最大的优势就是它的数据形式易于理解,分类方式直观。
训练出决策树之后,我们就可以根据根据决策树来对新的测试数据进行分类。
分类代码如下:
#根据决策树分类
def classify(inputTree,featLabels,testVec):
firstStr=inputTree.keys()[0]
secondDict=inputTree[firstStr]
featIndex=featLabels.index(firstStr)
for key in secondDict.keys():
if testVec[featIndex]==key:
if type(secondDict[key]).__name__=='dict':
classLabel=classify(secondDict[key],featLabels,testVec)
else:
classLabel=secondDict[key]
return classLabel
这里有一个通过决策数算法进行分类的一个实例,眼科医生是如何判断患者需要佩戴隐形眼镜的类型的。
判断的结果有三种,硬材料,软材料和不适合佩戴。
训练数据采用隐形眼镜数据集,数据集来自UCI数据库,它包含了很多患者眼部状况的观察条件以及医生推荐的眼镜类型。
数据集如下:
测试代码如下:
def example():
fr=open('lenses.txt')
lenses=[inst.strip().split('\t') for inst in fr.readlines()]
lensesLabels=['age','prescript','astigmatic','tearRate']
lensesTree=createTree(lenses,lensesLabels)
return lensesTree
结果:
决策树结构如下:
这样,医生便可以一步步的观察来最终得知该患者适合什么材料的隐形眼镜了。
来源:http://blog.csdn.net/cui134/article/details/28427137


猜你喜欢
- vue项目页面空白但不报错产生的原因分析vue项目中我们请求一个路由,打开页面发现页面是空白的,产生的主要原因有四种:1.路由重复如果配置了
- 一、常见模型分类1.1、循环服务器模型循环接收客户端请求,处理请求。同一时刻只能处理一个请求,处理完毕后再处理下一个。优点:实现简单,占用资
- 函数调用方法:numpy.array(object, dtype=None)各个参数意义:object:创建的数组的对象,可以为单个值,列表
- 在国外一博客看到的技巧,终于解决IE的这个老大难问题。我在IE的setAttribute bug也提到其解决方法,一是innerHTML,一
- 简介说明本文介绍用Navicat添加字段(字符串类型)并设置默认值时的报错问题。问题描述在Java开发过程中,经常会遇到给已有的表添加字段的
- 最近工作中的一个项目需要自动发送一些信息邮件到指定邮箱的需求,那么如何实现Python自动发送邮件的功能呢?接下来我们就来简单的介绍下如何利
- 简介Tornado龙卷风是一个开源的网络服务器框架,它是基于社交聚合网站FriendFeed的实时信息服务开发而来的。2007年由4名Goo
- 主要是用函数torch.nn.utils.rnn.PackedSequence()和torch.nn.utils.rnn.pack_padd
- 最近很少写CSS了,以后也可能写的会很少了,所以还是想把自已的一些经验能和大家分享一下,希望能给大家一些帮助!这篇文章主要写的提高网页在客户
- 目的检测字符串中是否包含某字符集合中的字符方法 最简洁的方法如下,清晰,通用,快速,适用于任何序列和容器def containAny(seq
- 本文实例总结了Python实现string字符串连接的方法。分享给大家供大家参考,具体如下:以下基于python 2.7版本,代码片段真实有
- 有件东西我观察了很多年,那就是很少有开发者会去使用SQL Server中的一个非常有用的东西——EX
- asp之家注:学习asp网页编程的朋友一定用过ACCESS数据库,access的简单方便,大大降低了asp初学者学习asp的门槛,对于学习a
- Django中每一个模型model都对应于数据库中的一张表,每个模型中的字段都对应于数据库表的列。方便的是,django可以自动生成这些cr
- 杭州最美的季节里,淘宝无障碍访问改善小组有幸邀请到盲人在线站长——争渡读屏团队成员——杨永全同学和我们一起面对面交流网站无障碍访问方面的问题
- 下面列出了asp远程网页数据采集程序中经常用到的函数,很实用,特别是正则表达式过滤函数。包括了使用xmlhttp采集远程网页内容,使用ado
- Python中的列表基于PyListObject实现,列表支持元素的插入、删除、更新操作,因此PyListObject是一个变长对象(列表的
- 本文实例讲述了Python实现简单求解给定整数的质因数算法。分享给大家供大家参考,具体如下:接着做题遇到求解质因数分解的问题,思想很简单,就
- 不久之前,笔者一个在企业中从事网管工作的朋友向我求助关于SQL Server服务器内存升级后遇到的问题。原来,他们企业准备上一个企业邮箱系统
- bitbucket 搭建搭建过程如下所示:1 jdk 8如果有的话就不用安装了,此处采用rpm方式安装(不用配置环境变量)把下载好的文件放在