python编写分类决策树的代码


Posted in Python onDecember 21, 2017

决策树通常在机器学习中用于分类。

优点:计算复杂度不高,输出结果易于理解,对中间值缺失不敏感,可以处理不相关特征数据。
缺点:可能会产生过度匹配问题。
适用数据类型:数值型和标称型。

1.信息增益

划分数据集的目的是:将无序的数据变得更加有序。组织杂乱无章数据的一种方法就是使用信息论度量信息。通常采用信息增益,信息增益是指数据划分前后信息熵的减少值。信息越无序信息熵越大,获得信息增益最高的特征就是最好的选择。
熵定义为信息的期望,符号xi的信息定义为:

python编写分类决策树的代码

其中p(xi)为该分类的概率。
熵,即信息的期望值为:

python编写分类决策树的代码

计算信息熵的代码如下:

def calcShannonEnt(dataSet):
  numEntries = len(dataSet)
  labelCounts = {}
  for featVec in dataSet:
    currentLabel = featVec[-1]
    if currentLabel not in labelCounts:
      labelCounts[currentLabel] = 0
    labelCounts[currentLabel] += 1
  shannonEnt = 0
  for key in labelCounts:
    shannonEnt = shannonEnt - (labelCounts[key]/numEntries)*math.log2(labelCounts[key]/numEntries)
  return shannonEnt

可以根据信息熵,按照获取最大信息增益的方法划分数据集。

2.划分数据集

划分数据集就是将所有符合要求的元素抽出来。

def splitDataSet(dataSet,axis,value):
  retDataset = []
  for featVec in dataSet:
    if featVec[axis] == value:
      newVec = featVec[:axis]
      newVec.extend(featVec[axis+1:])
      retDataset.append(newVec)
  return retDataset

3.选择最好的数据集划分方式

信息增益是熵的减少或者是信息无序度的减少。

def chooseBestFeatureToSplit(dataSet):
  numFeatures = len(dataSet[0]) - 1
  bestInfoGain = 0
  bestFeature = -1
  baseEntropy = calcShannonEnt(dataSet)
  for i in range(numFeatures):
    allValue = [example[i] for example in dataSet]#列表推倒,创建新的列表
    allValue = set(allValue)#最快得到列表中唯一元素值的方法
    newEntropy = 0
    for value in allValue:
      splitset = splitDataSet(dataSet,i,value)
      newEntropy = newEntropy + len(splitset)/len(dataSet)*calcShannonEnt(splitset)
    infoGain = baseEntropy - newEntropy
    if infoGain > bestInfoGain:
      bestInfoGain = infoGain
      bestFeature = i
  return bestFeature

4.递归创建决策树

结束条件为:程序遍历完所有划分数据集的属性,或每个分支下的所有实例都具有相同的分类。
当数据集已经处理了所有属性,但是类标签还不唯一时,采用多数表决的方式决定叶子节点的类型。

def majorityCnt(classList):
 classCount = {}
 for value in classList:
  if value not in classCount: classCount[value] = 0
  classCount[value] += 1
 classCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
 return classCount[0][0]

生成决策树:

def createTree(dataSet,labels):
 classList = [example[-1] for example in dataSet]
 labelsCopy = labels[:]
 if classList.count(classList[0]) == len(classList):
  return classList[0]
 if len(dataSet[0]) == 1:
  return majorityCnt(classList)
 bestFeature = chooseBestFeatureToSplit(dataSet)
 bestLabel = labelsCopy[bestFeature]
 myTree = {bestLabel:{}}
 featureValues = [example[bestFeature] for example in dataSet]
 featureValues = set(featureValues)
 del(labelsCopy[bestFeature])
 for value in featureValues:
  subLabels = labelsCopy[:]
  myTree[bestLabel][value] = createTree(splitDataSet(dataSet,bestFeature,value),subLabels)
 return myTree

5.测试算法——使用决策树分类

同样采用递归的方式得到分类结果。

def classify(inputTree,featLabels,testVec):
 currentFeat = list(inputTree.keys())[0]
 secondTree = inputTree[currentFeat]
 try:
  featureIndex = featLabels.index(currentFeat)
 except ValueError as err:
  print('yes')
 try:
  for value in secondTree.keys():
   if value == testVec[featureIndex]:
    if type(secondTree[value]).__name__ == 'dict':
     classLabel = classify(secondTree[value],featLabels,testVec)
    else:
     classLabel = secondTree[value]
  return classLabel
 except AttributeError:
  print(secondTree)

6.完整代码如下

import numpy as np
import math
import operator
def createDataSet():
 dataSet = [[1,1,'yes'],
    [1,1,'yes'],
    [1,0,'no'],
    [0,1,'no'],
    [0,1,'no'],]
 label = ['no surfacing','flippers']
 return dataSet,label

def calcShannonEnt(dataSet):
 numEntries = len(dataSet)
 labelCounts = {}
 for featVec in dataSet:
  currentLabel = featVec[-1]
  if currentLabel not in labelCounts:
   labelCounts[currentLabel] = 0
  labelCounts[currentLabel] += 1
 shannonEnt = 0
 for key in labelCounts:
  shannonEnt = shannonEnt - (labelCounts[key]/numEntries)*math.log2(labelCounts[key]/numEntries)
 return shannonEnt


def splitDataSet(dataSet,axis,value):
 retDataset = []
 for featVec in dataSet:
  if featVec[axis] == value:
   newVec = featVec[:axis]
   newVec.extend(featVec[axis+1:])
   retDataset.append(newVec)
 return retDataset

def chooseBestFeatureToSplit(dataSet):
 numFeatures = len(dataSet[0]) - 1
 bestInfoGain = 0
 bestFeature = -1
 baseEntropy = calcShannonEnt(dataSet)
 for i in range(numFeatures):
  allValue = [example[i] for example in dataSet]
  allValue = set(allValue)
  newEntropy = 0
  for value in allValue:
   splitset = splitDataSet(dataSet,i,value)
   newEntropy = newEntropy + len(splitset)/len(dataSet)*calcShannonEnt(splitset)
  infoGain = baseEntropy - newEntropy
  if infoGain > bestInfoGain:
   bestInfoGain = infoGain
   bestFeature = i
 return bestFeature

def majorityCnt(classList):
 classCount = {}
 for value in classList:
  if value not in classCount: classCount[value] = 0
  classCount[value] += 1
 classCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
 return classCount[0][0]   

def createTree(dataSet,labels):
 classList = [example[-1] for example in dataSet]
 labelsCopy = labels[:]
 if classList.count(classList[0]) == len(classList):
  return classList[0]
 if len(dataSet[0]) == 1:
  return majorityCnt(classList)
 bestFeature = chooseBestFeatureToSplit(dataSet)
 bestLabel = labelsCopy[bestFeature]
 myTree = {bestLabel:{}}
 featureValues = [example[bestFeature] for example in dataSet]
 featureValues = set(featureValues)
 del(labelsCopy[bestFeature])
 for value in featureValues:
  subLabels = labelsCopy[:]
  myTree[bestLabel][value] = createTree(splitDataSet(dataSet,bestFeature,value),subLabels)
 return myTree


def classify(inputTree,featLabels,testVec):
 currentFeat = list(inputTree.keys())[0]
 secondTree = inputTree[currentFeat]
 try:
  featureIndex = featLabels.index(currentFeat)
 except ValueError as err:
  print('yes')
 try:
  for value in secondTree.keys():
   if value == testVec[featureIndex]:
    if type(secondTree[value]).__name__ == 'dict':
     classLabel = classify(secondTree[value],featLabels,testVec)
    else:
     classLabel = secondTree[value]
  return classLabel
 except AttributeError:
  print(secondTree)

if __name__ == "__main__":
 dataset,label = createDataSet()
 myTree = createTree(dataset,label)
 a = [1,1]
 print(classify(myTree,label,a))

7.编程技巧

extend与append的区别

newVec.extend(featVec[axis+1:])
 retDataset.append(newVec)

extend([]),是将列表中的每个元素依次加入新列表中
append()是将括号中的内容当做一项加入到新列表中

列表推到

创建新列表的方式

allValue = [example[i] for example in dataSet]

提取列表中唯一的元素

allValue = set(allValue)

列表/元组排序,sorted()函数

classCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)

列表的复制

labelsCopy = labels[:]

代码及数据集下载:决策树

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
使用Python获取Linux系统的各种信息
Jul 10 Python
用Python登录Gmail并发送Gmail邮件的教程
Apr 17 Python
Django中的CACHE_BACKEND参数和站点级Cache设置
Jul 23 Python
python实现识别相似图片小结
Feb 22 Python
Python遍历目录中的所有文件的方法
Jul 08 Python
python strip() 函数和 split() 函数的详解及实例
Feb 03 Python
pandas.DataFrame 根据条件新建列并赋值的方法
Apr 08 Python
Python 给某个文件名添加时间戳的方法
Oct 16 Python
python实现桌面壁纸切换功能
Jan 21 Python
PyQt5基本控件使用之消息弹出、用户输入、文件对话框的使用方法
Aug 06 Python
Keras设定GPU使用内存大小方式(Tensorflow backend)
May 22 Python
Python接口自动化测试框架运行原理及流程
Nov 30 Python
Python基于PyGraphics包实现图片截取功能的方法
Dec 21 #Python
用Python写王者荣耀刷金币脚本
Dec 21 #Python
python使用Apriori算法进行关联性解析
Dec 21 #Python
python实现kMeans算法
Dec 21 #Python
利用Tkinter(python3.6)实现一个简单计算器
Dec 21 #Python
python编写朴素贝叶斯用于文本分类
Dec 21 #Python
python并发2之使用asyncio处理并发
Dec 21 #Python
You might like
详解如何在云服务器上部署Laravel
2017/06/30 PHP
ExtJS 学习专题(一) 如何应用ExtJS(附实例)
2010/03/11 Javascript
jquery 学习之二 属性相关
2010/11/23 Javascript
js实现在页面上弹出蒙板技巧简单实用
2013/04/16 Javascript
jQuery右侧选项卡焦点图片轮播特效代码分享
2015/09/05 Javascript
JavaScript深度复制(deep clone)的实现方法
2016/02/19 Javascript
你不知道的 javascript【推荐】
2017/01/08 Javascript
微信小程序 setData的使用方法详解
2017/04/20 Javascript
jQuery导航条固定定位效果实例代码
2017/05/26 jQuery
Nodejs回调加超时限制两种实现方法
2017/06/09 NodeJs
vue 不使用select实现下拉框功能(推荐)
2018/05/17 Javascript
iview同时验证多个表单问题总结
2018/09/29 Javascript
微信小程序实现预览图片功能
2020/10/22 Javascript
微信小程序云开发(数据库)详解
2019/05/17 Javascript
Python中用Descriptor实现类级属性(Property)详解
2014/09/18 Python
python操作ssh实现服务器日志下载的方法
2015/06/03 Python
python正则表达式re之compile函数解析
2017/10/25 Python
浅析Python 3 字符串中的 STR 和 Bytes 有什么区别
2018/10/14 Python
通过pycharm使用git的步骤(图文详解)
2019/06/13 Python
pandas基于时间序列的固定时间间隔求均值的方法
2019/07/04 Python
Django REST Framework序列化外键获取外键的值方法
2019/07/26 Python
python requests更换代理适用于IP频率限制的方法
2019/08/21 Python
python反转列表的三种方式解析
2019/11/08 Python
Python Lambda函数使用总结详解
2019/12/11 Python
将pymysql获取到的数据类型是tuple转化为pandas方式
2020/05/15 Python
Python函数参数分类原理详解
2020/05/28 Python
详解python方法之绑定方法与非绑定方法
2020/08/17 Python
输入一行文字,找出其中大写字母、小写字母、空格、数字、及其他字符各有多少
2016/04/15 面试题
英语自荐信范文
2013/12/11 职场文书
会计工作决心书
2014/03/11 职场文书
婚礼主持词
2014/03/13 职场文书
节水标语大全
2014/06/11 职场文书
商场营业员岗位职责
2015/04/14 职场文书
质检员工作总结2015
2015/04/25 职场文书
小平小道观后感
2015/06/09 职场文书
结婚喜宴祝酒词
2015/08/10 职场文书