Python实现决策树C4.5算法的示例


Posted in Python onMay 30, 2018

为什么要改进成C4.5算法

原理

C4.5算法是在ID3算法上的一种改进,它与ID3算法最大的区别就是特征选择上有所不同,一个是基于信息增益比,一个是基于信息增益。

之所以这样做是因为信息增益倾向于选择取值比较多的特征(特征越多,条件熵(特征划分后的类别变量的熵)越小,信息增益就越大);因此在信息增益下面加一个分母,该分母是当前所选特征的熵,注意:这里而不是类别变量的熵了。

这样就构成了新的特征选择准则,叫做信息增益比。为什么加了这样一个分母就会消除ID3算法倾向于选择取值较多的特征呢?

因为特征取值越多,该特征的熵就越大,分母也就越大,所以信息增益比就会减小,而不是像信息增益那样增大了,一定程度消除了算法对特征取值范围的影响。

实现

在算法实现上,C4.5算法只是修改了信息增益计算的函数calcShannonEntOfFeature和最优特征选择函数chooseBestFeatureToSplit。

calcShannonEntOfFeature在ID3的calcShannonEnt函数上加了个参数feat,ID3中该函数只用计算类别变量的熵,而calcShannonEntOfFeature可以计算指定特征或者类别变量的熵。

chooseBestFeatureToSplit函数在计算好信息增益后,同时计算了当前特征的熵IV,然后相除得到信息增益比,以最大信息增益比作为最优特征。

在划分数据的时候,有可能出现特征取同一个值,那么该特征的熵为0,同时信息增益也为0(类别变量划分前后一样,因为特征只有一个取值),0/0没有意义,可以跳过该特征。

Python实现决策树C4.5算法的示例

#coding=utf-8
import operator
from math import log
import time
import os, sys
import string

def createDataSet(trainDataFile):
 print trainDataFile
 dataSet = []
 try:
 fin = open(trainDataFile)
 for line in fin:
  line = line.strip()
  cols = line.split('\t')
  row = [cols[1], cols[2], cols[3], cols[4], cols[5], cols[6], cols[7], cols[8], cols[9], cols[10], cols[0]]
  dataSet.append(row)
  #print row
 except:
 print 'Usage xxx.py trainDataFilePath'
 sys.exit()
 labels = ['cip1', 'cip2', 'cip3', 'cip4', 'sip1', 'sip2', 'sip3', 'sip4', 'sport', 'domain']
 print 'dataSetlen', len(dataSet)
 return dataSet, labels

#calc shannon entropy of label or feature
def calcShannonEntOfFeature(dataSet, feat):
 numEntries = len(dataSet)
 labelCounts = {}
 for feaVec in dataSet:
 currentLabel = feaVec[feat]
 if currentLabel not in labelCounts:
  labelCounts[currentLabel] = 0
 labelCounts[currentLabel] += 1
 shannonEnt = 0.0
 for key in labelCounts:
 prob = float(labelCounts[key])/numEntries
 shannonEnt -= prob * log(prob, 2)
 return shannonEnt

def splitDataSet(dataSet, axis, value):
 retDataSet = []
 for featVec in dataSet:
 if featVec[axis] == value:
  reducedFeatVec = featVec[:axis]
  reducedFeatVec.extend(featVec[axis+1:])
  retDataSet.append(reducedFeatVec)
 return retDataSet
 
def chooseBestFeatureToSplit(dataSet):
 numFeatures = len(dataSet[0]) - 1 #last col is label
 baseEntropy = calcShannonEntOfFeature(dataSet, -1)
 bestInfoGainRate = 0.0
 bestFeature = -1
 for i in range(numFeatures):
 featList = [example[i] for example in dataSet]
 uniqueVals = set(featList)
 newEntropy = 0.0
 for value in uniqueVals:
  subDataSet = splitDataSet(dataSet, i, value)
  prob = len(subDataSet) / float(len(dataSet))
  newEntropy += prob *calcShannonEntOfFeature(subDataSet, -1) #calc conditional entropy
 infoGain = baseEntropy - newEntropy
  iv = calcShannonEntOfFeature(dataSet, i)
 if(iv == 0): #value of the feature is all same,infoGain and iv all equal 0, skip the feature
 continue
 
 infoGainRate = infoGain / iv
 if infoGainRate > bestInfoGainRate:
  bestInfoGainRate = infoGainRate
  bestFeature = i
 return bestFeature
  
#feature is exhaustive, reture what you want label
def majorityCnt(classList):
 classCount = {}
 for vote in classList:
 if vote not in classCount.keys():
  classCount[vote] = 0
 classCount[vote] += 1
 return max(classCount)  
 
def createTree(dataSet, labels):
 classList = [example[-1] for example in dataSet]
 if classList.count(classList[0]) ==len(classList): #all data is the same label
 return classList[0]
 if len(dataSet[0]) == 1: #all feature is exhaustive
 return majorityCnt(classList)
 bestFeat = chooseBestFeatureToSplit(dataSet)
 bestFeatLabel = labels[bestFeat]
 if(bestFeat == -1): #特征一样,但类别不一样,即类别与特征不相关,随机选第一个类别做分类结果
 return classList[0] 
 myTree = {bestFeatLabel:{}}
 del(labels[bestFeat])
 featValues = [example[bestFeat] for example in dataSet]
 uniqueVals = set(featValues)
 for value in uniqueVals:
 subLabels = labels[:]
 myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels)
 return myTree
 
def main():
 if(len(sys.argv) < 3):
 print 'Usage xxx.py trainSet outputTreeFile'
 sys.exit()
 data,label = createDataSet(sys.argv[1])
 t1 = time.clock()
 myTree = createTree(data,label)
 t2 = time.clock()
 fout = open(sys.argv[2], 'w')
 fout.write(str(myTree))
 fout.close()
 print 'execute for ',t2-t1
if __name__=='__main__':
 main()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中使用PIPE操作Linux管道
Feb 04 Python
python通过装饰器检查函数参数数据类型的方法
Mar 13 Python
整理Python 常用string函数(收藏)
May 30 Python
Python正则表达式教程之一:基础篇
Mar 02 Python
Python paramiko模块的使用示例
Apr 11 Python
Python 3 实现定义跨模块的全局变量和使用教程
Jul 07 Python
Python将列表中的元素转化为数字并排序的示例
Dec 25 Python
利用Pytorch实现简单的线性回归算法
Jan 15 Python
基于Numba提高python运行效率过程解析
Mar 02 Python
Django通过设置CORS解决跨域问题
Nov 26 Python
分享一个python的aes加密代码
Dec 22 Python
python使用matplotlib绘制图片时x轴的刻度处理
Aug 30 Python
python实现决策树ID3算法的示例代码
May 30 #Python
浅谈Django中的数据库模型类-models.py(一对一的关系)
May 30 #Python
Python实现的读取电脑硬件信息功能示例
May 30 #Python
Python应用库大全总结
May 30 #Python
Django中反向生成models.py的实例讲解
May 30 #Python
Python RabbitMQ消息队列实现rpc
May 30 #Python
python日期时间转为字符串或者格式化输出的实例
May 29 #Python
You might like
PHP生成excel时单元格内换行问题的解决方法
2010/08/26 PHP
PHP数组的交集array_intersect(),array_intersect_assoc(),array_inter_key()函数的小问题
2011/05/29 PHP
PHP json_encode中文乱码问题的解决办法
2013/09/09 PHP
PHP生成Gif图片验证码
2013/10/27 PHP
PHP读取CURL模拟登录时生成Cookie文件的方法
2014/11/04 PHP
php+ajax+json 详解及实例代码
2016/12/12 PHP
php计数排序算法的实现代码(附四个实例代码)
2020/03/31 PHP
ie支持function.bind()方法实现代码
2012/12/27 Javascript
jQuery源码解读之removeClass()方法分析
2015/02/20 Javascript
JS使用JSON作为参数实例分析
2016/06/23 Javascript
JavaScript面试开发常用的知识点总结
2016/08/08 Javascript
JS实现隐藏同级元素后只显示JS文件内容的方法
2016/09/04 Javascript
Bootstrap下拉菜单更改为悬停(hover)触发的方法
2017/05/24 Javascript
vue中echarts3.0自适应的方法
2018/02/26 Javascript
Taro集成Redux快速上手的方法示例
2018/06/21 Javascript
Node.js 在本地生成日志文件的方法
2020/02/07 Javascript
[03:18]【TI9纪实】社区大触GL与木木
2019/08/25 DOTA
Python3实现将文件树中所有文件和子目录归档到tar压缩文件的方法
2015/05/22 Python
python数据结构链表之单向链表(实例讲解)
2017/07/25 Python
docker django无法访问redis容器的解决方法
2019/08/21 Python
Python 实现日志同时输出到屏幕和文件
2020/02/19 Python
Python 将 QQ 好友头像生成祝福语的实现代码
2020/05/03 Python
Django中FilePathField字段的用法
2020/05/21 Python
python计算auc的方法
2020/09/09 Python
基于Python模拟浏览器发送http请求
2020/11/06 Python
澳大利亚潮流尖端的快时尚品牌:Cotton On
2016/09/26 全球购物
大韩航空官方网站:Korean Air
2017/10/25 全球购物
阿里健康官方海外旗舰店:阿里健康国际自营
2017/11/24 全球购物
敏捷开发的主要原则都有哪些
2015/04/26 面试题
《狮子和兔子》教学反思
2014/03/02 职场文书
精神文明建设标语
2014/06/16 职场文书
2014-2015学年工作总结
2014/11/27 职场文书
租赁协议书
2015/01/27 职场文书
大学生入党群众意见书
2015/06/02 职场文书
新郎父母婚礼致辞
2015/07/27 职场文书
PostgreSQL怎么创建分区表详解
2022/06/25 PostgreSQL