python实现C4.5决策树算法


Posted in Python onAugust 29, 2018

C4.5算法使用信息增益率来代替ID3的信息增益进行特征的选择,克服了信息增益选择特征时偏向于特征值个数较多的不足。信息增益率的定义如下:

python实现C4.5决策树算法

# -*- coding: utf-8 -*-


from numpy import *
import math
import copy
import cPickle as pickle


class C45DTree(object):
 def __init__(self): # 构造方法
  self.tree = {} # 生成树
  self.dataSet = [] # 数据集
  self.labels = [] # 标签集


 # 数据导入函数
 def loadDataSet(self, path, labels):
  recordList = []
  fp = open(path, "rb") # 读取文件内容
  content = fp.read()
  fp.close()
  rowList = content.splitlines() # 按行转换为一维表
  recordList = [row.split("\t") for row in rowList if row.strip()] # strip()函数删除空格、Tab等
  self.dataSet = recordList
  self.labels = labels


 # 执行决策树函数
 def train(self):
  labels = copy.deepcopy(self.labels)
  self.tree = self.buildTree(self.dataSet, labels)


 # 构件决策树:穿件决策树主程序
 def buildTree(self, dataSet, lables):
  cateList = [data[-1] for data in dataSet] # 抽取源数据集中的决策标签列
  # 程序终止条件1:如果classList只有一种决策标签,停止划分,返回这个决策标签
  if cateList.count(cateList[0]) == len(cateList):
   return cateList[0]
  # 程序终止条件2:如果数据集的第一个决策标签只有一个,返回这个标签
  if len(dataSet[0]) == 1:
   return self.maxCate(cateList)
  # 核心部分
  bestFeat, featValueList= self.getBestFeat(dataSet) # 返回数据集的最优特征轴
  bestFeatLabel = lables[bestFeat]
  tree = {bestFeatLabel: {}}
  del (lables[bestFeat])
  for value in featValueList: # 决策树递归生长
   subLables = lables[:] # 将删除后的特征类别集建立子类别集
   # 按最优特征列和值分隔数据集
   splitDataset = self.splitDataSet(dataSet, bestFeat, value)
   subTree = self.buildTree(splitDataset, subLables) # 构建子树
   tree[bestFeatLabel][value] = subTree
  return tree


 # 计算出现次数最多的类别标签
 def maxCate(self, cateList):
  items = dict([(cateList.count(i), i) for i in cateList])
  return items[max(items.keys())]


 # 计算最优特征
 def getBestFeat(self, dataSet):
  Num_Feats = len(dataSet[0][:-1])
  totality = len(dataSet)
  BaseEntropy = self.computeEntropy(dataSet)
  ConditionEntropy = []  # 初始化条件熵
  slpitInfo = [] # for C4.5,caculate gain ratio
  allFeatVList = []
  for f in xrange(Num_Feats):
   featList = [example[f] for example in dataSet]
   [splitI, featureValueList] = self.computeSplitInfo(featList)
   allFeatVList.append(featureValueList)
   slpitInfo.append(splitI)
   resultGain = 0.0
   for value in featureValueList:
    subSet = self.splitDataSet(dataSet, f, value)
    appearNum = float(len(subSet))
    subEntropy = self.computeEntropy(subSet)
    resultGain += (appearNum/totality)*subEntropy
   ConditionEntropy.append(resultGain) # 总条件熵
  infoGainArray = BaseEntropy*ones(Num_Feats)-array(ConditionEntropy)
  infoGainRatio = infoGainArray/array(slpitInfo) # C4.5信息增益的计算
  bestFeatureIndex = argsort(-infoGainRatio)[0]
  return bestFeatureIndex, allFeatVList[bestFeatureIndex]

 # 计算划分信息
 def computeSplitInfo(self, featureVList):
  numEntries = len(featureVList)
  featureVauleSetList = list(set(featureVList))
  valueCounts = [featureVList.count(featVec) for featVec in featureVauleSetList]
  pList = [float(item)/numEntries for item in valueCounts]
  lList = [item*math.log(item, 2) for item in pList]
  splitInfo = -sum(lList)
  return splitInfo, featureVauleSetList


 # 计算信息熵
 # @staticmethod
 def computeEntropy(self, dataSet):
  dataLen = float(len(dataSet))
  cateList = [data[-1] for data in dataSet] # 从数据集中得到类别标签
  # 得到类别为key、 出现次数value的字典
  items = dict([(i, cateList.count(i)) for i in cateList])
  infoEntropy = 0.0
  for key in items: # 香农熵: = -p*log2(p) --infoEntropy = -prob * log(prob, 2)
   prob = float(items[key]) / dataLen
   infoEntropy -= prob * math.log(prob, 2)
  return infoEntropy


 # 划分数据集: 分割数据集; 删除特征轴所在的数据列,返回剩余的数据集
 # dataSet : 数据集; axis: 特征轴; value: 特征轴的取值
 def splitDataSet(self, dataSet, axis, value):
  rtnList = []
  for featVec in dataSet:
   if featVec[axis] == value:
    rFeatVec = featVec[:axis] # list操作:提取0~(axis-1)的元素
    rFeatVec.extend(featVec[axis + 1:]) # 将特征轴之后的元素加回
    rtnList.append(rFeatVec)
  return rtnList

 # 存取树到文件
 def storetree(self, inputTree, filename):
  fw = open(filename,'w')
  pickle.dump(inputTree, fw)
  fw.close()

 # 从文件抓取树
 def grabTree(self, filename):
  fr = open(filename)
  return pickle.load(fr)

调用代码

# -*- coding: utf-8 -*-

from numpy import *
from C45DTree import *

dtree = C45DTree()
dtree.loadDataSet("dataset.dat",["age", "revenue", "student", "credit"])
dtree.train()

dtree.storetree(dtree.tree, "data.tree")
mytree = dtree.grabTree("data.tree")
print mytree

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

Python 相关文章推荐
Python中exit、return、sys.exit()等使用实例和区别
May 28 Python
python实现搜索指定目录下文件及文件内搜索指定关键词的方法
Jun 28 Python
Python实现字典的key和values的交换
Aug 04 Python
pandas进行数据的交集与并集方式的数据合并方法
Jun 27 Python
详解python算法之冒泡排序
Mar 05 Python
pytz格式化北京时间多出6分钟问题的解决方法
Jun 21 Python
Python中的正则表达式与JSON数据交换格式
Jul 03 Python
使用Python串口实时显示数据并绘图的例子
Dec 26 Python
Python TestSuite生成测试报告过程解析
Jul 23 Python
Python如何定义有默认参数的函数
Aug 10 Python
python将下载到本地m3u8视频合成MP4的代码详解
Nov 24 Python
pytorch 如何使用batch训练lstm网络
May 28 Python
python机器学习之KNN分类算法
Aug 29 #Python
深入理解python中sort()与sorted()的区别
Aug 29 #Python
Python实现拷贝/删除文件夹的方法详解
Aug 29 #Python
Python读写zip压缩文件的方法
Aug 29 #Python
使用python生成杨辉三角形的示例代码
Aug 29 #Python
Python实现查询某个目录下修改时间最新的文件示例
Aug 29 #Python
有关Python的22个编程技巧
Aug 29 #Python
You might like
Ajax PHP简单入门教程代码
2008/04/25 PHP
php根据身份证号码计算年龄的实例代码
2014/01/18 PHP
在Ubuntu 14.04上部署 PHP 环境及 WordPress
2014/09/02 PHP
PHP时间戳格式全部汇总 (获取时间、时间戳)
2016/06/13 PHP
php多进程模拟并发事务产生的问题小结
2018/12/07 PHP
一个XML格式数据转换为图表的例子
2010/02/09 Javascript
JavaScript 面向对象的 私有成员和公开成员
2010/05/13 Javascript
JS获取图片实际宽高及根据图片大小进行自适应
2013/08/11 Javascript
利用js实现在浏览器状态栏显示访问者在本页停留的时间
2013/12/29 Javascript
JS实现FLASH幻灯片图片切换效果的方法
2015/03/04 Javascript
JS中的Replace方法使用经验分享
2015/05/20 Javascript
JS实现图片平面旋转的方法
2016/03/01 Javascript
举例说明JavaScript中的实例对象与原型对象
2016/03/11 Javascript
JS仿京东移动端手指拨动切换轮播图效果
2020/04/10 Javascript
jQuery的中 is(':visible') 解析及用法(必看)
2017/02/12 Javascript
nodejs动态创建二维码的方法
2017/08/12 NodeJs
微信小程序基于canvas渐变实现的彩虹效果示例
2019/05/03 Javascript
JS实现水平移动与垂直移动动画
2019/12/19 Javascript
js实现随机点名器精简版
2020/06/29 Javascript
如何在vue中使用百度地图添加自定义覆盖物(水波纹)
2020/11/03 Javascript
jQuery实现可以扩展的日历
2020/12/01 jQuery
centos系统升级python 2.7.3
2014/07/03 Python
Python通过递归遍历出集合中所有元素的方法
2015/02/25 Python
详解Python验证码识别
2016/01/25 Python
使用C#配合ArcGIS Engine进行地理信息系统开发
2016/02/19 Python
Python random模块用法解析及简单示例
2017/12/18 Python
Python实现的NN神经网络算法完整示例
2018/06/19 Python
python自动化办公操作PPT的实现
2021/02/05 Python
草莓网化妆品澳大利亚站:Strawberrynet AU
2017/12/18 全球购物
CSS代码检查工具stylelint的使用方法详解
2021/03/27 HTML / CSS
门卫工作岗位职责
2013/12/17 职场文书
大学军训感言400字
2014/03/11 职场文书
党员国庆节演讲稿范文2014
2014/09/21 职场文书
大学班干部竞选稿
2015/11/20 职场文书
《所见》教学反思
2016/02/23 职场文书
mysql自增长id用完了该怎么办
2022/02/12 MySQL