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检测手机QQ在线状态的脚本代码
Feb 10 Python
Python的Bottle框架的一些使用技巧介绍
Apr 08 Python
详细讲解用Python发送SMTP邮件的教程
Apr 29 Python
Python随机生成带特殊字符的密码
Mar 02 Python
详解Django+Uwsgi+Nginx 实现生产环境部署
Nov 06 Python
Python实现网站表单提交和模板
Jan 15 Python
Python之lambda匿名函数及map和filter的用法
Mar 05 Python
Django的用户模块与权限系统的示例代码
Jul 24 Python
Python 用三行代码提取PDF表格数据
Oct 13 Python
PyCharm 在Windows的有用快捷键详解
Apr 07 Python
在Ubuntu 20.04中安装Pycharm 2020.1的图文教程
Apr 30 Python
Python入门基础之数字字符串与列表
Feb 01 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的memcached客户端memcached
2011/06/14 PHP
php加速器eAccelerator的配置参数、API详解
2014/05/05 PHP
php实现微信公众号创建自定义菜单功能的实例代码
2019/06/11 PHP
PHP加MySQL消息队列深入理解
2021/02/27 PHP
JavaScript类和继承 constructor属性
2010/03/04 Javascript
JavaScript实现把rgb颜色转换成16进制颜色的方法
2015/06/01 Javascript
详解js的延迟对象、跨域、模板引擎、弹出层、AJAX【附实例下载】
2016/12/19 Javascript
Vue2学习笔记之请求数据交互vue-resource
2017/02/23 Javascript
Vue.js实现一个漂亮、灵活、可复用的提示组件示例
2017/03/17 Javascript
实例详解display:none与visible:hidden的区别
2017/03/30 Javascript
js构建二叉树进行数值数组的去重与优化详解
2018/03/26 Javascript
关于vue v-for循环解决img标签的src动态绑定问题
2018/09/18 Javascript
vue中axios请求的封装实例代码
2019/03/23 Javascript
小程序实现上下移动切换位置
2019/09/23 Javascript
详解如何在Javascript中使用Object.freeze()
2020/10/18 Javascript
8个非常实用的Vue自定义指令
2020/12/15 Vue.js
Sanic框架异常处理与中间件操作实例分析
2018/07/16 Python
python json load json 数据后出现乱序的解决方案
2020/02/27 Python
学会python自动收发邮件 代替你问候女友
2020/05/20 Python
瑞典快乐袜子:Happy Socks
2018/02/16 全球购物
Bluebella美国官网:英国性感内衣品牌
2018/10/04 全球购物
如何设定的weblogic的热启动模式(开发模式)与产品发布模式
2012/09/08 面试题
公司活动邀请函
2014/01/24 职场文书
黄金搭档广告词
2014/03/21 职场文书
省文明单位申报材料
2014/05/08 职场文书
解除聘用合同证明书范本
2014/09/11 职场文书
党旗在我心中演讲稿
2014/09/15 职场文书
写给导师的自荐信
2015/03/06 职场文书
2016国培学习心得体会
2016/01/08 职场文书
python执行js代码的方法
2021/05/13 Python
利用Pycharm连接服务器的全过程记录
2021/07/01 Python
十大动画制作软件,Adobe产品上榜两款,第一是行业标准软件
2022/03/18 杂记
Nginx实现负载均衡的项目实践
2022/03/18 Servers
Vue3中toRef与toRefs的区别
2022/03/24 Vue.js
golang操作rocketmq的示例代码
2022/04/06 Golang
Win10加载疑难解答时出错发生意外错误的解决方法
2022/07/07 数码科技