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内置函数OCT详解
Nov 09 Python
Python图片裁剪实例代码(如头像裁剪)
Jun 21 Python
python队列通信:rabbitMQ的使用(实例讲解)
Dec 22 Python
Python中将变量按行写入txt文本中的方法
Apr 03 Python
python读取文本绘制动态速度曲线
Jun 21 Python
20行python代码的入门级小游戏的详解
May 05 Python
python实现月食效果实例代码
Jun 18 Python
python中文分词库jieba使用方法详解
Feb 11 Python
Python轻量级web框架bottle使用方法解析
Jun 13 Python
virtualenv介绍及简明教程
Jun 23 Python
Python如何实现感知器的逻辑电路
Dec 25 Python
python程序实现BTC(比特币)挖矿的完整代码
Jan 20 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 header下载函数
2014/01/31 PHP
linux使用crontab实现PHP执行计划定时任务
2014/05/10 PHP
php blowfish加密解密算法
2016/07/02 PHP
Yii2配置Nginx伪静态的方法
2017/05/05 PHP
php微信公众号开发之图片回复
2018/10/20 PHP
js宝典学习笔记(上)
2007/01/10 Javascript
JS input 数字验证代码
2009/07/30 Javascript
基于jQuery的模仿新浪微博时间的组件
2011/10/04 Javascript
用JS做的简单的可折叠的两级树形菜单
2013/09/21 Javascript
jQuery获取Radio,CheckBox选择的Value值(示例代码)
2013/12/12 Javascript
jQuery拖拽div实现思路
2014/02/19 Javascript
jQuery实现鼠标可拖动调整表格列宽度
2014/05/26 Javascript
javascript同步服务器时间和同步倒计时小技巧
2015/09/24 Javascript
js判断移动端是否安装某款app的多种方法
2015/12/18 Javascript
原生JS轮播图插件
2017/02/09 Javascript
基于js 本地存储(详解)
2017/08/16 Javascript
vue组件挂载到全局方法的示例代码
2018/08/02 Javascript
解决vue项目中遇到 Cannot find module ‘chalk‘ 报错的问题
2020/11/05 Javascript
Python入门篇之正则表达式
2014/10/20 Python
整理Python中的赋值运算符
2015/05/13 Python
python在不同层级目录import模块的方法
2016/01/31 Python
python并发2之使用asyncio处理并发
2017/12/21 Python
python binascii 进制转换实例
2019/06/12 Python
python如何制作英文字典
2019/06/25 Python
Python代码实现http/https代理服务器的脚本
2019/08/12 Python
python有序查找算法 二分法实例解析
2020/02/18 Python
Python接口开发实现步骤详解
2020/04/26 Python
Pycharm中安装wordcloud等库失败问题及终端通过pip安装的Python库如何添加到Pycharm解释器中(推荐)
2020/05/10 Python
如何把外网python虚拟环境迁移到内网
2020/05/18 Python
毕业寄语大全
2014/04/09 职场文书
网站推广策划方案
2014/06/04 职场文书
营销总经理岗位职责范本
2014/09/02 职场文书
工作感想范文
2015/08/07 职场文书
交通安全教育主题班会
2015/08/12 职场文书
Java图书管理系统,课程设计必用(源码+文档)
2021/06/30 Java/Android
Java中Quartz高可用定时任务快速入门
2022/04/03 Java/Android