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的Flask框架中@app.route的用法教程
Mar 31 Python
Python编程生成随机用户名及密码的方法示例
May 05 Python
利用python实现xml与数据库读取转换的方法
Jun 17 Python
python OpenCV学习笔记实现二维直方图
Feb 08 Python
Python高级特性之闭包与装饰器实例详解
Nov 19 Python
python3 使用Opencv打开USB摄像头,配置1080P分辨率的操作
Dec 11 Python
Python调用钉钉自定义机器人的实现
Jan 03 Python
python根据完整路径获得盘名/路径名/文件名/文件扩展名的方法
Apr 22 Python
在python里创建一个任务(Task)实例
Apr 25 Python
Python 通过监听端口实现唯一脚本运行方式
May 05 Python
Python astype(np.float)函数使用方法解析
Jun 08 Python
Python txt文件常用读写操作代码实例
Aug 03 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 curl请求信息和返回信息设置代码实例
2015/04/27 PHP
详解JavaScript的Date对象(制作简易钟表)
2020/04/07 Javascript
JavaScript获取css行间样式,内连样式和外链样式的简单方法
2016/07/18 Javascript
JS版微信6.0分享接口用法分析
2016/10/13 Javascript
jQuery实现的购物车物品数量加减功能代码
2016/11/16 Javascript
微信小程序 slider的简单实例
2017/04/19 Javascript
浅谈React和Redux的连接react-redux
2017/12/04 Javascript
vue.extend实现alert模态框弹窗组件
2018/04/28 Javascript
JavaScript中 ES6变量的结构赋值
2018/07/10 Javascript
vue 实现websocket发送消息并实时接收消息
2019/12/09 Javascript
推荐几个不错的console调试技巧实现
2019/12/20 Javascript
关于小程序优化的一些建议(小结)
2020/12/10 Javascript
Python解析xml中dom元素的方法
2015/03/12 Python
快速入手Python字符编码
2016/08/03 Python
Python实现的选择排序算法原理与用法实例分析
2017/11/22 Python
python微信跳一跳系列之棋子定位颜色识别
2018/02/26 Python
python正则-re的用法详解
2019/07/28 Python
在PyTorch中使用标签平滑正则化的问题
2020/04/03 Python
Pycharm及python安装详细步骤及PyCharm配置整理(推荐)
2020/07/31 Python
Django微信小程序后台开发教程的实现
2020/06/03 Python
拥有超过850家商店的美国在线派对商店:Party City
2018/10/21 全球购物
英国领先的酒杯和水晶玻璃器皿制造商:Dartington Crystal
2019/06/23 全球购物
技术总监岗位职责
2013/12/05 职场文书
简历自我评价模版
2014/01/31 职场文书
面试后感谢信
2014/02/01 职场文书
考试违纪检讨书
2014/02/02 职场文书
幼儿园的门卫岗位职责
2014/04/10 职场文书
党课心得体会范文
2014/09/09 职场文书
离婚协议书怎样才有法律效力
2014/10/10 职场文书
社区综治工作汇报
2014/10/27 职场文书
车间主任岗位职责
2015/02/03 职场文书
2015年化妆品销售工作总结
2015/05/11 职场文书
公司与个人合作协议书
2016/03/19 职场文书
用Python进行栅格数据的分区统计和批量提取
2021/05/27 Python
解析在浏览器地址栏输入一个URL后发生了什么
2021/06/21 Servers
golang操作redis的客户端包有多个比如redigo、go-redis
2022/04/14 Golang