构造决策树时需要解决的第一个问题是:当前数据集中哪个特征在划分数据分类时起决定性作用。

划分数据集的原则:将无序的数据变得更加有序

信息增益:在划分数据集前后信息发生的变化

获得信息增益最大的特征就是最好的特征

熵:信息的期望值,表示信息的混乱程序,越混乱熵越大

信息增益可以表示为信息熵的减小

[https://blog.csdn.net/moxigandashu/article/details/71305273?locationNum=9&fps=1]


以下代码均在trees.py文件内。

计算给定数据集的信息熵:

from math import log
import operator
import treePlotter
def calcShannonEnt(dataset):numEntries=len(dataset)labelCounts={}for featVec in dataset:currentLabel=featVec[-1]if currentLabel not in labelCounts.keys():labelCounts[currentLabel]=0labelCounts[currentLabel]+=1shannonEnt=0.0for key in labelCounts:     #遍历字典,key是字典的键prob=float(labelCounts[key])/numEntriesshannonEnt-=prob*log(prob,2)return shannonEnt

根据给定特征及特征值划分数据集:

def splitDataSet(dataset,index,value):  #按照给定特征划分数据集。index,value两个参数用来确定特征及其特征值retDataset=[]for featVec in dataset:if featVec[index]==value:reducedFeatVec=featVec[:index]#print(reducedFeatVec)reducedFeatVec.extend(featVec[index+1:])#print(reducedFeatVec)retDataset.append(reducedFeatVec)#print(retDataset)return retDataset
def createDataSet():dataSet=[[1,1,'yes'],[1,1,'yes'],[1,0,'no'],[0,1,'no'],[0,1,'no']]features=['no surfacing','flippers']return dataSet,features

选择最好的数据集划分方式,即为确定最恰当的特征:

def chooseBestFeatureToSplit(dataset):numFeatures=len(dataset[0])-1   #确定特征个数baseEntropy=calcShannonEnt(dataset)bestInfoGain=0bestFeature=-1for i in range(numFeatures):featureList=[example[i] for example in dataset] #第i个特征的所有特征值uniqueVals=set(featureList) #将所有特征值去重,得到标称型数值newEntropy=0.0for value in uniqueVals:subDataset=splitDataSet(dataset,i,value)prob=len(subDataset)/float(len(dataset))    #第i个特征值为value的记录个数与数据集总数的比值代表第i个特征值为value的概率newEntropy+=prob*calcShannonEnt(subDataset)infoGain=baseEntropy-newEntropy     #信息增益等于熵的减少,或者说是数据无序度的减少if infoGain>bestInfoGain:bestInfoGain=infoGainbestFeature=ireturn bestFeature

标称型数值也叫离散型,表示数值只能在有限的目标集中取得,例如true和false


构建决策树的原理:得到原始数据集,然后基于最好的属性值划分数据集,由于特征值可能多于两个,因此可能存在大于两个分支的数据集划分。第一次划分之后,数据将被向下传递到树分支的下一个节点,在这个节点上,我们可以再次划分数据。因此我们可以采用递归的原则处理数据集。

递归结束的条件是:程序遍历完所有划分数据集的属性,或者每个分支下的所有实例都具有相同的分类。如果所有实例都具有相同的分类,则得到一个叶子节点或者终止块,任何到达叶子节点的数据必然属于叶子节点的分类。

如果数据集已经处理了所有特征,剩下的记录的标签仍然不唯一,这种情况下通常采用多数表决的方法决定改叶子节点的类别:

def majorityCnt(classList): #多数表决,决定叶子节点的分类classCount={}for vote in classList:if vote not in classCount.keys():classCount[vote]=0classCount[vote]+=1sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) #第二维降序排列return sortedClassCount[0][0]

递归创建树的函数代码:

def createTree(dataset,featureList):    #数据集,特征列表,产生决策树,返回值是字典featureListCopy=featureList[:]  #不能改变传递进来的实参featureListclassList=[record[-1] for record in dataset]    #标签列表,即为数据集最后一列if classList.count(classList[0])==len(classList):   #如果标签列表中第一个值出现的次数等于标签列表长度,就说明标签列表内的元素都相同了return classList[0]     #此时形成叶子节点,即为终止块if len(dataset[0])==1:  #如果数据集的第一行长度为1,说明决策树进行到使用完所有特征,只剩下标签而且标签不唯一,此时需要调用多数表决来决定此叶子节点的类别return majorityCnt(classList)bestFeat=chooseBestFeatureToSplit(dataset)  #选取最佳特征对应的索引bestFeatLabel=featureListCopy[bestFeat]     #找到最佳特征myTree={bestFeatLabel:{}}   #用字典存储决策树del featureListCopy[bestFeat]   #提出最佳特征featValues=[record[bestFeat] for record in dataset]  #最佳特征的所有取值uniqueVal=set(featValues)   #最佳特征取值形成的集合,去重for value in uniqueVal:     #value是最佳特征的值subFeatureList=featureListCopy[:]   #剔除最佳特征的特征列表myTree[bestFeatLabel][value]=createTree(splitDataSet(dataset,bestFeat,value),subFeatureList)    #splitDataSet(dataset,bestFeat,value)表示划分后的数据集return myTree

使用决策树的分类函数:

def classify(inputTree,featLabels,testVec): #参数分别是:决策树,特征列表,待分类样本firstNode=list(inputTree.keys())[0]secondDict=inputTree[firstNode]featIndex=featLabels.index(firstNode)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

使用pickle模块存储、获取决策树,避免每次使用决策树时都需要重新生成:

def storeTree(inputTree,filename):import picklefw=open(filename,'wb')  #wb表示以bytes的形式存储pickle.dump(inputTree,fw,)fw.close()
def getTree(filename):import picklefr=open(filename,'rb')  #rb表示以bytes的形式存储return pickle.load(fr)


以下代码均在treePlotter.py文件内:

使用matplotlib库的注解功能绘制树节点:

import matplotlib.pyplot as plt
decisionNode=dict(boxstyle="sawtooth",fc='0.8')
leafNode=dict(boxstyle='round4',fc='0.8')
arrow_args=dict(arrowstyle='<-')def plotNode(nodeTxt,centerPt,parentPt,nodeType):createPlot.picture.annotate(nodeTxt,xy=parentPt,xycoords='axes fraction',xytext=centerPt,textcoords='axes fraction',va='center',ha='center',bbox=nodeType,arrowprops=arrow_args)

获取叶节点数目:

def getNumberOfLeafs(myTree):   #计算决策树叶子节点数目numberOfLeafs=0firstNode=list(myTree.keys())[0]secondDict=myTree[firstNode]for key in secondDict.keys():if type(secondDict[key]).__name__ == 'dict':numberOfLeafs+=getNumberOfLeafs(secondDict[key])else:numberOfLeafs+=1return numberOfLeafs

 获取决策树层数:

def getTreeDepth(myTree):   #计算决策树的层数maxDepth=0firstNode=list(myTree.keys())[0]secondDic=myTree[firstNode]for key in secondDic.keys():if type(secondDic[key]).__name__=='dict':thisDepth=1+getTreeDepth(secondDic[key])  #计算此分支下的深度else:thisDepth=1if thisDepth>maxDepth:      #比较每个分支的层数与最大层数,用来更新最大层数。maxDepth=thisDepthreturn maxDepth

 plotTree函数:

def plotMidText(sonNode,parentPt,txtString): #将决策树的键值放在连接线的中间位置xMid=(parentPt[0]-sonNode[0])/2.0+sonNode[0]yMid=(parentPt[1]-sonNode[1])/2.0+sonNode[1]createPlot.picture.text(xMid,yMid,txtString)def plotTree(myTree,parentPt,nodeTxt):  #画出决策树numLeafs=getNumberOfLeafs(myTree)depth=getTreeDepth(myTree)firstNode=list(myTree.keys())[0]sonNode=(plotTree.xOff+(1.0+float(numLeafs))/2.0/plotTree.totalW,plotTree.yOff)plotMidText(sonNode, parentPt, nodeTxt)plotNode(firstNode, sonNode, parentPt, decisionNode)secondDict = myTree[firstNode]plotTree.yOff = plotTree.yOff - 1.0 / plotTree.totalDfor key in secondDict.keys():if type(secondDict[key]).__name__ == 'dict':  # test to see if the nodes are dictonaires, if not they are leaf nodesplotTree(secondDict[key], sonNode, str(key))  # recursionelse:plotTree.xOff = plotTree.xOff + 1.0 / plotTree.totalWplotNode(secondDict[key], (plotTree.xOff, plotTree.yOff), sonNode, leafNode)plotMidText((plotTree.xOff, plotTree.yOff), sonNode, str(key))plotTree.yOff = plotTree.yOff + 1.0 / plotTree.totalDdef createPlot(inTree):fig = plt.figure(1, facecolor='white')fig.clf()axprops = dict(xticks=[], yticks=[])createPlot.picture = plt.subplot(111, frameon=False, **axprops) #在函数内声明全局变量plotTree.totalW = float(getNumberOfLeafs(inTree))   #宽度plotTree.totalD = float(getTreeDepth(inTree))   #高度plotTree.xOff = -0.5 / plotTree.totalWplotTree.yOff = 1.0plotTree(inTree, (0.5, 1.0), '')plt.show()

手动声明两个决策树方便测试:

def retrieveTree(i):listOfTrees=[{'no surfacing':{0:'no',1:{'flippers':{0:'no',1:'yes'}}}},{'no surfacing':{0:'no',1:{'flippers':{0:{'head':{0:'no',1:'yes'}},1:'no'}}}}]return listOfTrees[i]


使用决策树执行具体数据的分类如下(使用决策树.py):

import trees
import treePlotterfr=open('lenses.txt')
lenses=[example.strip().split('\t') for example in fr.readlines()]
lensesLabels=['age','prescript','astigmatic','tearRate']
lensesTree=trees.createTree(lenses,lensesLabels)  #生成决策树,存储为字典
print(lensesTree)  #打印决策树字典
treePlotter.createPlot(lensesTree)  #画出决策树

以上代码会输出决策树字典:
{'tearRate': {'reduced': 'no lenses', 'normal': {'astigamtic': {'no': {'age': {'young': 'soft', 'pre': 'soft', 'presbyopic': {'prescript': {'hyper': 'soft', 'myope': 'no lenses'}}}}, 'yes': {'prescript': {'hyper': {'age': {'young': 'hard', 'pre': 'no lenses', 'presbyopic': 'no lenses'}}, 'myope': 'hard'}}}}}}
画出决策树如下:

使用此决策树来分类:

result=trees.classify(lensesTree,lensesLabels,['young', 'myope', 'no', 'reduced'])
print(result)

输出:

no lenses

转载于:https://www.cnblogs.com/zhhy236400/p/9846512.html

机器学习 决策树 ID3相关推荐

  1. 机器学习决策树ID3

    一.决策树(ID3算法) 1. 决策树的基本认识 决策树是一种依托决策而建立起来的一种树.在机器学习中,决策树是一种预测模型,代表的是一种对象属性与对象值之间的一种映射关系,每一个节点代表某个对象,树 ...

  2. 机器学习算法—决策树(ID3)算法

    机器学习--决策树(ID3)算法 1.决策树(ID3)算法 1.1 算法引入 我们首先以一个分类问题开始,假设我们有这样一份样本数据: 我们的目标是想通过色泽.根蒂.敲声.纹理.脐部.触感来判断这是不 ...

  3. 机器学习算法 04 —— 决策树(ID3、C4.5、CART,剪枝,特征提取,回归决策树)

    文章目录 系列文章 决策树 1 决策树算法简介 2 决策树分类的原理 2.1 信息熵 2.2 决策树划分依据-信息增益(ID3) 2.3 决策树划分依据-信息增益率(C4.5) 2.4 决策树划分依据 ...

  4. python决策树id3算法_python实现决策树ID3算法

    一.决策树概论 决策树是根据训练数据集,按属性跟类型,构建一棵树形结构.可以按照这棵树的结构,对测试数据进行分类.同时决策树也可以用来处理预测问题(回归). 二.决策树ID3的原理 有多种类型的决策树 ...

  5. ++代码实现 感知机的原理_决策树ID3原理及R语言python代码实现(西瓜书)

    决策树ID3原理及R语言python代码实现(西瓜书) 摘要: 决策树是机器学习中一种非常常见的分类与回归方法,可以认为是if-else结构的规则.分类决策树是由节点和有向边组成的树形结构,节点表示特 ...

  6. 3.1 机器学习 --- 决策树

    3.1 机器学习 - 决策树 一 金融评分卡 模型做好后尽量快的上线,以符合要求的模型,尽快上线. 超参数赋予权重,使得模型的参数不一致,而达到均衡样本数据 二 决策树原理 1. 找女朋友 性别:男 ...

  7. [机器学习]决策树选西瓜

    文章目录 一.决策树 1.画法 2.决策树的剪枝 3.挑西瓜决策树 3.1利用信息增益选择最优划分属性 二.sk-learn库对西瓜数据集,分别进行ID3.C4.5和CART的算法代码实现 1.ID3 ...

  8. 决策树ID3代码(Python)

    决策树ID3代码(Python) 上一节介绍了决策树的递归算法框架(create),这一节将用Python语言实现一个小程序.代码和数据来源于<机器学习实战>Peter Harringto ...

  9. 机器学习 | 决策树原理剪枝连续值缺失值处理

    机器学习 | 决策树 最近学习了西瓜书决策树一章,简单整理了笔记,后续会继续补充给 文章目录 机器学习 | 决策树 一.基本信息论 1. 信息量 2. 信息熵 二.决策树常用算法 1.ID3 2.C4 ...

最新文章

  1. 微服务架构必备的几点知识
  2. 2016年软考网络工程师考试命题范围变化之网络设备配置与复习技巧
  3. java 编程思想 笔记_java编程思想笔记20170215
  4. 强化学习-动态规划_强化学习-第5部分
  5. 【MFC系列-第17天】企业信息管理软件开发
  6. js防篡改对象之冻结对象
  7. PHP 常用代码大全
  8. Layui表单账号注册校验密码是否一致
  9. Spark 机器学习 —— ALS
  10. 深入理解 Javascript 面向对象编程
  11. Word文件没有保存怎么找回来?恢复文件
  12. 世界最早投入运行的计算机网络是,世界上最早投入运行的计算机网络是。
  13. 小白新手web开发简单总结(三)-一个简单的Web开发项目
  14. Aspack壳代码分析
  15. 诸葛——如何摆脱APP速死症?
  16. Android 页面Scheme配置
  17. office2019卸载组件_office2019软件安装教程
  18. 高温大量程热流传感器结构及信号调理电路的设计
  19. 使用face++的API接口-人脸识别
  20. 处理办公文档通过共享打印机无法打印

热门文章

  1. 批量修改文件权限 和所有者 chown nobody:nobody * -R chmod 775 * -R
  2. zabbix 客户端安装
  3. jquery入门 修改网页背景颜色
  4. oracle监听器动态注册于静态注册的区别
  5. linux字符界面教程,打造字符界面的多媒体Linux系统
  6. oracle数据库有哪些文件构成,Oracle数据库架构中包括几层?每层都有什么元素?...
  7. 西班牙放大招,利用区块链技术防腐
  8. 2021年Java面试题目最新总结【90%面试会踩的坑】
  9. matlab llc谐振电路,一个菜鸟对LLC谐振知识的渴望
  10. kerberos java实现,基于kerberos实现jaas登录