Python机器学习之决策树算法实例详解


Posted in Python onDecember 06, 2017

本文实例讲述了Python机器学习之决策树算法。分享给大家供大家参考,具体如下:

决策树学习是应用最广泛的归纳推理算法之一,是一种逼近离散值目标函数的方法,在这种方法中学习到的函数被表示为一棵决策树。决策树可以使用不熟悉的数据集合,并从中提取出一系列规则,机器学习算法最终将使用这些从数据集中创造的规则。决策树的优点为:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据。缺点为:可能产生过度匹配的问题。决策树适于处理离散型和连续型的数据。

在决策树中最重要的就是如何选取用于划分的特征

在算法中一般选用ID3,D3算法的核心问题是选取在树的每个节点要测试的特征或者属性,希望选择的是最有助于分类实例的属性。如何定量地衡量一个属性的价值呢?这里需要引入熵和信息增益的概念。熵是信息论中广泛使用的一个度量标准,刻画了任意样本集的纯度。

假设有10个训练样本,其中6个的分类标签为yes,4个的分类标签为no,那熵是多少呢?在该例子中,分类的数目为2(yes,no),yes的概率为0.6,no的概率为0.4,则熵为 :

Python机器学习之决策树算法实例详解

Python机器学习之决策树算法实例详解

其中value(A)是属性A所有可能值的集合,Python机器学习之决策树算法实例详解是S中属性A的值为v的子集,即Python机器学习之决策树算法实例详解。上述公式的第一项为原集合S的熵,第二项是用A分类S后熵的期望值,该项描述的期望熵就是每个子集的熵的加权和,权值为属于的样本占原始样本S的比例Python机器学习之决策树算法实例详解。所以Gain(S, A)是由于知道属性A的值而导致的期望熵减少。

完整的代码:

# -*- coding: cp936 -*-
from numpy import *
import operator
from math import log
import operator
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
def calcShannonEnt(dataSet):
  numEntries = len(dataSet)
  labelCounts = {} # a dictionary for feature
  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:
    #print(key)
    #print(labelCounts[key])
    prob = float(labelCounts[key])/numEntries
    #print(prob)
    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[:axis]
      reducedFeatVec.extend(featVec[axis+1:])
      retDataSet.append(reducedFeatVec)
  return retDataSet
#选取特征,划分数据集,计算得出最好的划分数据集的特征
def chooseBestFeatureToSplit(dataSet):
  numFeatures = len(dataSet[0]) - 1 #剩下的是特征的个数
  baseEntropy = calcShannonEnt(dataSet)#计算数据集的熵,放到baseEntropy中
  bestInfoGain = 0.0;bestFeature = -1 #初始化熵增益
  for i in range(numFeatures):
    featList = [example[i] for example in dataSet] #featList存储对应特征所有可能得取值
    uniqueVals = set(featList)
    newEntropy = 0.0
    for value in uniqueVals:#下面是计算每种划分方式的信息熵,特征i个,每个特征value个值
      subDataSet = splitDataSet(dataSet, i ,value)
      prob = len(subDataSet)/float(len(dataSet)) #特征样本在总样本中的权重
      newEntropy = prob * calcShannonEnt(subDataSet)
    infoGain = baseEntropy - newEntropy #计算i个特征的信息熵
    #print(i)
    #print(infoGain)
    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):
  classList = [example[-1] for example in dataSet]#将最后一行的数据放到classList中,所有的类别的值
  if classList.count(classList[0]) == len(classList): #类别完全相同不需要再划分
    return classList[0]
  if len(dataSet[0]) == 1:#这里为什么是1呢?就是说特征数为1的时候
    return majorityCnt(classList)#就返回这个特征就行了,因为就这一个特征
  bestFeat = chooseBestFeatureToSplit(dataSet)
  print('the bestFeatue in creating is :')
  print(bestFeat)
  bestFeatLabel = labels[bestFeat]#运行结果'no surfacing'
  myTree = {bestFeatLabel:{}}#嵌套字典,目前value是一个空字典
  del(labels[bestFeat])
  featValues = [example[bestFeat] for example in dataSet]#第0个特征对应的取值
  uniqueVals = set(featValues)
  for value in uniqueVals: #根据当前特征值的取值进行下一级的划分
    subLabels = labels[:]
    myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet,bestFeat,value),subLabels)
  return myTree
#对上面简单的数据进行小测试
def testTree1():
  myDat,labels=createDataSet()
  val = calcShannonEnt(myDat)
  print 'The classify accuracy is: %.2f%%' % val
  retDataSet1 = splitDataSet(myDat,0,1)
  print (myDat)
  print(retDataSet1)
  retDataSet0 = splitDataSet(myDat,0,0)
  print (myDat)
  print(retDataSet0)
  bestfeature = chooseBestFeatureToSplit(myDat)
  print('the bestFeatue is :')
  print(bestfeature)
  tree = createTree(myDat,labels)
  print(tree)

对应的结果是:

>>> import TREE
>>> TREE.testTree1()
The classify accuracy is: 0.97%
[[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
[[1, 'yes'], [1, 'yes'], [0, 'no']]
[[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
[[1, 'no'], [1, 'no']]
the bestFeatue is :
0
the bestFeatue in creating is :
0
the bestFeatue in creating is :
0
{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}

最好再增加使用决策树的分类函数

同时因为构建决策树是非常耗时间的,因为最好是将构建好的树通过 python 的 pickle 序列化对象,将对象保存在磁盘上,等到需要用的时候再读出

def classify(inputTree,featLabels,testVec):
  firstStr = inputTree.keys()[0]
  secondDict = inputTree[firstStr]
  featIndex = featLabels.index(firstStr)
  key = testVec[featIndex]
  valueOfFeat = secondDict[key]
  if isinstance(valueOfFeat, dict):
    classLabel = classify(valueOfFeat, featLabels, testVec)
  else: classLabel = valueOfFeat
  return classLabel
def storeTree(inputTree,filename):
  import pickle
  fw = open(filename,'w')
  pickle.dump(inputTree,fw)
  fw.close()
def grabTree(filename):
  import pickle
  fr = open(filename)
  return pickle.load(fr)

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
使用python获取CPU和内存信息的思路与实现(linux系统)
Jan 03 Python
Python实现的下载8000首儿歌的代码分享
Nov 21 Python
python3.4用函数操作mysql5.7数据库
Jun 23 Python
教你使用python实现微信每天给女朋友说晚安
Mar 23 Python
浅谈Python 列表字典赋值的陷阱
Jan 20 Python
python 多线程重启方法
Feb 18 Python
python 用所有标点符号分隔句子的示例
Jul 15 Python
关于tf.TFRecordReader()函数的用法解析
Feb 17 Python
使用Python三角函数公式计算三角形的夹角案例
Apr 15 Python
使用Keras构造简单的CNN网络实例
Jun 29 Python
Python3 pyecharts生成Html文件柱状图及折线图代码实例
Sep 29 Python
使用pytorch实现线性回归
Apr 11 Python
快速入门python学习笔记
Dec 06 #Python
Python中django学习心得
Dec 06 #Python
Python标准库inspect的具体使用方法
Dec 06 #Python
读取本地json文件,解析json(实例讲解)
Dec 06 #Python
Python语言描述最大连续子序列和
Dec 05 #Python
python matplotlib坐标轴设置的方法
Dec 05 #Python
详解K-means算法在Python中的实现
Dec 05 #Python
You might like
PHP 配置文件中open_basedir选项作用
2009/07/19 PHP
深入分析php中接口与抽象类的区别
2013/06/08 PHP
PHP中对于浮点型的数据需要用不同的方法解决
2014/03/11 PHP
PHP生成网站桌面快捷方式代码分享
2014/10/11 PHP
PHP开发之归档格式phar文件概念与用法详解【创建,使用,解包还原提取】
2017/11/17 PHP
jquery text,radio,checkbox,select操作实现代码
2009/07/09 Javascript
JavaScript分页功能的实现方法
2015/04/25 Javascript
jQuery检测某个元素是否存在代码分享
2015/07/09 Javascript
js实现瀑布流的三种方式比较
2020/06/28 Javascript
jquery实现界面无刷新加载登陆注册
2016/07/30 Javascript
ES6新数据结构Set与WeakSet用法分析
2017/03/31 Javascript
微信小程序之圆形进度条实现思路
2018/02/22 Javascript
基于JS实现一个随机生成验证码功能
2019/05/29 Javascript
jQuery实现倒计时功能完整示例
2020/06/01 jQuery
[59:30]完美世界DOTA2联赛PWL S3 access vs LBZS 第二场 12.20
2020/12/23 DOTA
python数据结构之链表的实例讲解
2017/07/25 Python
解决Pyinstaller 打包exe文件 取消dos窗口(黑框框)的问题
2019/06/21 Python
40行Python代码实现天气预报和每日鸡汤推送功能
2020/02/27 Python
使用keras2.0 将Merge层改为函数式
2020/05/23 Python
如何教少儿学习Python编程
2020/07/10 Python
paramiko使用tail实时获取服务器的日志输出详解
2020/12/06 Python
解释DataSet(ds) 和 ds as DataSet 的含义
2014/07/27 面试题
初中生自我鉴定
2014/02/04 职场文书
《维生素c的故事》教学反思
2014/02/18 职场文书
委托书范本
2014/09/13 职场文书
2015年入党积极分子评语
2015/03/26 职场文书
物流业务员岗位职责
2015/04/03 职场文书
行政撤诉申请书
2015/05/18 职场文书
2015年基建工作总结范文
2015/05/23 职场文书
医院病假条怎么写
2015/08/17 职场文书
Nginx配置80端口访问8080及项目名地址方法解析
2021/03/31 Servers
CSS3实现三角形不断放大效果
2021/04/13 HTML / CSS
Python将CSV文件转化为HTML文件的操作方法
2021/06/30 Python
Java并发编程必备之Future机制
2021/06/30 Java/Android
Python+Matplotlib+LaTeX玩转数学公式
2022/02/24 Python
python turtle绘制多边形和跳跃和改变速度特效
2022/03/16 Python