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实现zencart产品数据导入到magento(python导入数据)
Apr 03 Python
编写Python脚本批量下载DesktopNexus壁纸的教程
May 06 Python
python+requests+unittest API接口测试实例(详解)
Jun 10 Python
Python竟能画这么漂亮的花,帅呆了(代码分享)
Nov 15 Python
Python subprocess模块功能与常见用法实例详解
Jun 28 Python
Python实现通过继承覆盖方法示例
Jul 02 Python
python实现字符串中字符分类及个数统计
Sep 28 Python
python 判断参数为Nonetype类型或空的实例
Oct 30 Python
python绘制中国大陆人口热力图
Nov 07 Python
python实现任意位置文件分割的实例
Dec 14 Python
Python实现微信自动好友验证,自动回复,发送群聊链接方法
Feb 21 Python
Python多线程爬取豆瓣影评API接口
Oct 22 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
自编函数解决pathinfo()函数处理中文问题
2014/11/03 PHP
Linux平台php命令行程序处理管道数据的方法
2016/11/10 PHP
List Information About the Binary Files Used by an Application
2007/06/18 Javascript
网页中CDATA标记的说明
2010/09/12 Javascript
javascript写的日历类(基于pj)
2010/12/28 Javascript
js获取json元素数量的方法
2015/01/27 Javascript
浅谈轻量级js模板引擎simplite
2015/02/13 Javascript
JavaScript电子时钟倒计时
2016/01/09 Javascript
基于HTML+CSS+JS实现增加删除修改tab导航特效代码
2016/08/05 Javascript
javascript实现瀑布流动态加载图片原理
2016/08/12 Javascript
node.js平台下利用cookie实现记住密码登陆(Express+Ejs+Mysql)
2017/04/26 Javascript
vue组件生命周期详解
2017/11/07 Javascript
vue计算属性和监听器实例解析
2018/05/10 Javascript
详解Vue SSR( Vue2 + Koa2 + Webpack4)配置指南
2018/11/13 Javascript
vue请求服务器数据后绑定不上的解决方法
2019/10/30 Javascript
Vue2.x和Vue3.x的双向绑定原理详解
2020/11/05 Javascript
在Vue中使用Echarts可视化库的完整步骤记录
2020/11/18 Vue.js
利用QT写一个极简单的图形化Python闹钟程序
2015/04/07 Python
Python爬虫之模拟知乎登录的方法教程
2017/05/25 Python
python扫描proxy并获取可用代理ip的实例
2017/08/07 Python
python利用微信公众号实现报警功能
2018/06/10 Python
Python解决pip install时出现的Could not fetch URL问题
2019/08/01 Python
在django中,关于session的通用设置方法
2019/08/06 Python
python单例设计模式实现解析
2020/01/07 Python
使用PyTorch训练一个图像分类器实例
2020/01/08 Python
Flask中sqlalchemy模块的实例用法
2020/08/02 Python
基于zepto的插件之移动端无缝向上滚动并上下触摸滑动实例代码
2016/12/20 HTML / CSS
德国运动鞋网上商店:Afew Store
2018/01/05 全球购物
孤独星球出版物:Lonely Planet Publications
2018/03/17 全球购物
见习期自我鉴定
2013/11/07 职场文书
英文自我鉴定
2013/12/10 职场文书
元旦晚会邀请函
2014/01/27 职场文书
个人求职信范例
2014/01/29 职场文书
活动倡议书范文
2014/05/13 职场文书
水利专业大学生职业生涯规划书范文
2014/09/17 职场文书
雷锋的故事观后感
2015/06/10 职场文书