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 实现归并排序算法
Jun 05 Python
python中使用urllib2伪造HTTP报头的2个方法
Jul 07 Python
python使用pil生成图片验证码的方法
May 08 Python
利用Python找出序列中出现最多的元素示例代码
Dec 08 Python
Python简单爬虫导出CSV文件的实例讲解
Jul 06 Python
Python面向对象之反射/自省机制实例分析
Aug 24 Python
使用Python横向合并excel文件的实例
Dec 11 Python
Python数据抓取爬虫代理防封IP方法
Dec 23 Python
Python批量生成幻影坦克图片实例代码
Jun 04 Python
python如何建立全零数组
Jul 19 Python
如何用Python绘制3D柱形图
Sep 16 Python
python字典按照value排序方法
Dec 28 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自动识别文字编码并转换为目标编码的方法
2015/08/08 PHP
详解Laravel视图间共享数据与视图Composer
2016/08/04 PHP
云网广告中的代码,提示出错,大家找找
2006/11/21 Javascript
深入理解JavaScript系列(14) 作用域链介绍(Scope Chain)
2012/04/12 Javascript
Extjs中ComboBoxTree实现的下拉框树效果(自写)
2013/05/28 Javascript
Javascript selection的兼容性写法介绍
2013/12/20 Javascript
JavaScript图片轮播代码分享
2015/07/31 Javascript
jQuery插件实现文字无缝向上滚动效果代码
2016/02/25 Javascript
jQuery模拟实现的select点击选择效果【附demo源码下载】
2016/11/09 Javascript
jquery中绑定事件的异同
2017/02/28 Javascript
令按钮悬浮在(手机)页面底部的实现方法
2017/05/02 Javascript
AngularJS中使用ngModal模态框实例
2017/05/27 Javascript
详解windows下vue-cli及webpack 构建网站(二)导入bootstrap样式
2017/06/17 Javascript
Bootstrap datepicker日期选择器插件使用详解
2017/07/26 Javascript
弱类型语言javascript开发中的一些坑实例小结【变量、函数、数组、对象、作用域等】
2019/08/07 Javascript
layer iframe 设置关闭按钮的方法
2019/09/12 Javascript
Python实现多行注释的另类方法
2014/08/22 Python
python逐行读写txt文件的实例讲解
2018/04/03 Python
使用python画个小猪佩奇的示例代码
2018/06/06 Python
Python完全识别验证码自动登录实例详解
2019/11/24 Python
浅谈python 中的 type(), dtype(), astype()的区别
2020/04/09 Python
Python 程序员必须掌握的日志记录
2020/08/17 Python
详解使用Python写一个向数据库填充数据的小工具(推荐)
2020/09/11 Python
html5时钟实现代码
2010/10/22 HTML / CSS
Farfetch中文官网:奢侈品牌时尚购物平台
2020/03/15 全球购物
Kipling澳洲官网:购买凯浦林包包
2020/12/17 全球购物
护理专业个人求职简历的自我评价
2013/10/13 职场文书
区域总监的岗位职责
2013/11/21 职场文书
个人实用的自我评价范文
2013/11/23 职场文书
玩手机检讨书1000字
2014/10/20 职场文书
高校自主招生教师推荐信
2015/03/23 职场文书
开学第一天的感想
2015/08/10 职场文书
幼儿园国培研修日志
2015/11/13 职场文书
音乐课《小猫钓鱼》教学反思
2016/02/18 职场文书
Python中Numpy和Matplotlib的基本使用指南
2021/11/02 Python
分享很少见很有用的SQL功能CORRESPONDING
2022/08/05 MySQL