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列表推导式的使用方法
Nov 21 Python
Python获取文件ssdeep值的方法
Oct 05 Python
Python文件读取的3种方法及路径转义
Jun 21 Python
详解Python中的序列化与反序列化的使用
Jun 30 Python
Python使用Beautiful Soup包编写爬虫时的一些关键点
Jan 20 Python
python2.7实现FTP文件下载功能
Apr 15 Python
python读取.mat文件的数据及实例代码
Jul 12 Python
pytorch 图像预处理之减去均值,除以方差的实例
Jan 02 Python
Python在字符串中处理html和xml的方法
Jul 31 Python
实例代码讲解Python 线程池
Aug 24 Python
python的dict判断key是否存在的方法
Dec 09 Python
Python中的流程控制详解
Feb 18 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
php自动获取关键字的方法
2015/01/06 PHP
提高php编程效率技巧
2015/08/13 PHP
Laravel (Lumen) 解决JWT-Auth刷新token的问题
2019/10/24 PHP
PHP的imageTtfText()函数深入详解
2021/03/03 PHP
HTML颜色选择器实现代码
2010/11/23 Javascript
解决js正则匹配换行问题实现代码
2012/12/10 Javascript
javascript 分号总结及详细介绍
2016/09/24 Javascript
vue.js实现简单轮播图效果
2017/10/10 Javascript
JavaScript求一组数的最小公倍数和最大公约数常用算法详解【面向对象,回归迭代和循环】
2018/05/07 Javascript
layui表格内放置图片,并点击放大的实例
2019/09/10 Javascript
解决angular 使用原生拖拽页面卡顿及表单控件输入延迟问题
2020/04/21 Javascript
JavaScript Image对象实现原理实例解析
2020/08/26 Javascript
浅析JavaScript 函数柯里化
2020/09/08 Javascript
[36:52]DOTA2真视界:基辅特锦赛总决赛
2017/05/21 DOTA
python中enumerate的用法实例解析
2014/08/18 Python
Python中格式化format()方法详解
2017/04/01 Python
浅谈解除装饰器作用(python3新增)
2018/10/15 Python
python爬虫租房信息在地图上显示的方法
2019/05/13 Python
Django中Middleware中的函数详解
2019/07/18 Python
python3.7环境下安装Anaconda的教程图解
2019/09/10 Python
使用tensorboard可视化loss和acc的实例
2020/01/21 Python
python GUI库图形界面开发之PyQt5滑块条控件QSlider详细使用方法与实例
2020/02/28 Python
Python reques接口测试框架实现代码
2020/07/28 Python
美国专业级皮肤病和spa品质护肤品的高级零售网站:SkinCareRx
2017/02/06 全球购物
Prototype是怎么扩展DOM的
2014/10/01 面试题
办公室副主任岗位职责
2013/11/25 职场文书
领导党性分析材料
2014/02/15 职场文书
蓝颜请假条
2014/04/11 职场文书
好习惯伴我成长演讲稿
2014/05/21 职场文书
平安建设工作方案
2014/06/02 职场文书
中队活动总结
2014/08/27 职场文书
幼儿园园长个人总结
2015/03/02 职场文书
Java使用Unsafe类的示例详解
2021/09/25 Java/Android
关于Oracle12C默认用户名system密码不正确的解决方案
2021/10/16 Oracle
使用Redis实现点赞取消点赞的详细代码
2022/03/20 Redis
蓝牙耳机怎么连接电脑win11? Win11蓝牙耳机连接电脑的技巧
2023/01/09 数码科技