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操作SQLite简明教程
Jul 10 Python
Python中用psycopg2模块操作PostgreSQL方法
Nov 28 Python
利用Python如何批量更新服务器文件
Jul 29 Python
python web自制框架之接受url传递过来的参数实例
Dec 17 Python
Python批量生成特定尺寸图片及图画任意文字的实例
Jan 30 Python
python变量的存储原理详解
Jul 10 Python
python3实现的zip格式压缩文件夹操作示例
Aug 17 Python
python manage.py runserver流程解析
Nov 08 Python
python 实现提取log文件中的关键句子,并进行统计分析
Dec 24 Python
基于Python执行dos命令并获取输出的结果
Dec 30 Python
全网最全python库selenium自动化使用详细教程
Jan 12 Python
Python 可迭代对象 iterable的具体使用
Aug 07 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实现选择排序的解决方法
2013/05/04 PHP
php常用的url处理函数总结
2014/11/19 PHP
php字符串按照单词进行反转的方法
2015/03/14 PHP
PHP读取大文件的多种方法介绍
2016/04/04 PHP
Javascript YUI 读码日记之 YAHOO.util.Dom - Part.3
2008/03/22 Javascript
Javascript 面向对象 命名空间
2010/05/13 Javascript
JS字符串处理实例代码
2013/08/05 Javascript
纯js代码制作的网页时钟特效【附实例】
2016/03/30 Javascript
js弹出框、对话框、提示框、弹窗实现方法总结(推荐)
2016/05/31 Javascript
JQuery实现DIV其他动画效果的简单实例
2016/09/18 Javascript
React实现双向绑定示例代码
2016/09/19 Javascript
微信小程序 获取设备信息 API实例详解
2016/10/02 Javascript
基于vue2.0实现简单轮播图
2017/11/27 Javascript
bing Map 在vue项目中的使用详解
2018/04/09 Javascript
react-native使用leanclound消息推送的方法
2018/08/06 Javascript
vscode调试node.js的实现方法
2020/03/22 Javascript
浅谈vue权限管理实现及流程
2020/04/23 Javascript
[02:51]DOTA2 2015国际邀请赛中国区预选赛第一日战报
2015/05/27 DOTA
[02:11]DOTA2上海特级锦标赛主赛事第二日RECAP
2016/03/04 DOTA
利用Python演示数型数据结构的教程
2015/04/03 Python
详解python分布式进程
2018/10/08 Python
python小程序实现刷票功能详解
2019/07/17 Python
PyTorch中Tensor的维度变换实现
2019/08/18 Python
python中selenium库的基本使用详解
2020/07/31 Python
Melissa香港官网:MDreams
2016/07/01 全球购物
Jar包的作用是什么
2014/03/30 面试题
网上常见的一份Linux面试题(多项选择部分)
2014/09/09 面试题
食品业务员岗位职责
2014/03/18 职场文书
2015年敬老院工作总结
2015/05/18 职场文书
严以修身专题学习研讨会发言材料
2015/11/09 职场文书
党风廉政教育心得体会2016
2016/01/22 职场文书
个人职业生涯规划之自我评估篇
2019/09/03 职场文书
导游词之千岛湖
2019/09/23 职场文书
开学季:喜迎新生,迎新标语少不了
2019/11/07 职场文书
eclipse创建项目没有dynamic web的解决方法
2021/06/24 Java/Android
Mysql中常用的join连接方式
2022/05/11 MySQL