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处理文本文件实现生成指定格式文件的方法
Jul 31 Python
在Python中使用全局日志时需要注意的问题
May 06 Python
Python函数式编程指南(四):生成器详解
Jun 24 Python
使用Python解析JSON数据的基本方法
Oct 15 Python
Python进阶_关于命名空间与作用域(详解)
May 29 Python
go和python变量赋值遇到的一个问题
Aug 31 Python
pytorch 数据集图片显示方法
Jul 26 Python
python tkinter图形界面代码统计工具(更新)
Sep 18 Python
简单了解Python读取大文件代码实例
Dec 18 Python
python代码如何实现余弦相似性计算
Feb 09 Python
Python yield的用法实例分析
Mar 06 Python
地图可视化神器kepler.gl python接口的使用方法
Dec 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
PHP类的静态(static)方法和静态(static)变量使用介绍
2012/02/19 PHP
分享一段PHP制作的中文拼音首字母工具类
2014/12/11 PHP
PHP判断FORM表单或URL参数来的数据是否为整数的方法
2016/03/25 PHP
用Laravel轻松处理千万级数据的方法实现
2020/12/25 PHP
仿谷歌主页js动画效果实现代码
2013/07/14 Javascript
父页面显示遮罩层弹出半透明状态的dialog
2014/03/04 Javascript
JavaScript中奇葩的假值示例应用
2014/03/11 Javascript
IE6已终止操作问题的2种情况及解决
2014/04/23 Javascript
jquery 实现input输入什么div图层显示什么
2014/06/15 Javascript
判断浏览器的内核及版本号方法汇总
2015/01/05 Javascript
Jquery结合HTML5实现文件上传
2015/06/25 Javascript
JS实现回到页面顶部动画效果的简单实例
2016/05/24 Javascript
jquery实现上传文件大小类型的验证例子(推荐)
2016/06/25 Javascript
浅析jQuery操作select控件的取值和设值
2016/12/07 Javascript
微信小程序 网络请求(post请求,get请求)
2017/01/17 Javascript
Nodejs实现短信验证码功能
2017/02/09 NodeJs
js 去掉字符串前后空格实现代码集合
2017/03/25 Javascript
基于vue.js中事件修饰符.self的用法(详解)
2018/02/23 Javascript
解决Layui 表单提交数据为空的问题
2018/08/15 Javascript
Node4-5静态资源服务器实战以及优化压缩文件实例内容
2019/08/29 Javascript
Element-Ui组件 NavMenu 导航菜单的具体使用
2019/10/24 Javascript
JS实现旋转木马轮播图
2020/01/01 Javascript
python+opencv识别图片中的圆形
2020/03/25 Python
python3下使用cv2.imwrite存储带有中文路径图片的方法
2018/05/10 Python
Python用61行代码实现图片像素化的示例代码
2018/12/10 Python
opencv 阈值分割的具体使用
2020/07/08 Python
诗狄娜化妆品官方网站:Stila Cosmetics
2016/12/21 全球购物
华为消费者德国官方网站:HUAWEI德国
2020/11/03 全球购物
酒店司机岗位职责
2013/12/14 职场文书
工作自我评价怎么写
2014/01/29 职场文书
房屋继承公证书
2014/04/10 职场文书
优秀会计求职信
2014/07/04 职场文书
传承焦裕禄精神思想汇报2014
2014/09/10 职场文书
公证委托书格式
2014/09/13 职场文书
病人写给医生的感谢信
2015/01/23 职场文书
民事调解书范文
2015/05/20 职场文书