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 相关文章推荐
在Django中创建URLconf相关的通用视图的方法
Jul 20 Python
pandas数据清洗,排序,索引设置,数据选取方法
May 18 Python
python Flask 装饰器顺序问题解决
Aug 08 Python
python 快速把超大txt文件转存为csv的实例
Oct 26 Python
python消除序列的重复值并保持顺序不变的实例
Nov 08 Python
Python语言进阶知识点总结
May 28 Python
Python获取时间范围内日期列表和周列表的函数
Aug 05 Python
Python中IP地址处理IPy模块的方法
Aug 16 Python
Python 元组操作总结
Sep 18 Python
Django中提示消息messages的设置方式
Nov 15 Python
Python中Flask-RESTful编写API接口(小白入门)
Dec 11 Python
pandas提升计算效率的一些方法汇总
May 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
mantis安装、配置和使用中的问题小结
2014/07/14 PHP
Javascript 通过json自动生成Dom的代码
2010/04/01 Javascript
基于Jquery的文字滚动跑马灯插件(一个页面多个滚动区)
2010/07/26 Javascript
js中一维数组和二位数组中的几个问题示例说明
2014/07/17 Javascript
无限树Jquery插件zTree的常用功能特性总结
2014/09/11 Javascript
js获取UserControl内容为拼html时提供方便
2014/11/02 Javascript
thinkphp实现无限分类(使用递归)
2015/12/19 Javascript
AngularJS入门教程之模块化操作用法示例
2016/11/02 Javascript
使用Ajax与服务器(JSON)通信实例
2016/11/04 Javascript
jQuery中的select操作详解
2016/11/29 Javascript
vue.js指令v-model使用方法
2017/03/20 Javascript
荐书|您有一份JavaScript书单待签收
2017/07/21 Javascript
vue实现通讯录功能
2018/07/14 Javascript
IntelliJ IDEA编辑器配置vue高亮显示
2019/09/26 Javascript
jQuery实现滑动星星评分效果(每日分享)
2019/11/13 jQuery
微信小程序pinker组件使用实现自动相减日期
2020/05/07 Javascript
[50:02]完美世界DOTA2联赛循环赛 Magma vs IO BO2第一场 11.01
2020/11/02 DOTA
Python实现类继承实例
2014/07/04 Python
Python多进程分块读取超大文件的方法
2016/04/13 Python
python实现用户答题功能
2018/01/17 Python
Python+AutoIt实现界面工具开发过程详解
2019/08/07 Python
Django模板获取field的verbose_name实例
2020/05/19 Python
pyCharm 实现关闭代码检查
2020/06/09 Python
python map比for循环快在哪
2020/09/21 Python
英国演唱会订票网站:Ticket Selection
2018/03/27 全球购物
Foot Locker德国官方网站:美国运动服和鞋类零售商
2018/11/01 全球购物
日本最佳原创设计品牌:Felissimo(芬理希梦)
2019/03/19 全球购物
linux面试题参考答案(9)
2016/01/29 面试题
技校生自我鉴定范文
2013/09/26 职场文书
舞蹈教育学专业推荐信
2013/11/27 职场文书
给老婆的检讨书1000字
2015/01/01 职场文书
担保书格式
2015/01/20 职场文书
2015年市场部工作总结
2015/04/30 职场文书
合同纠纷调解书
2015/05/20 职场文书
PYTHON InceptionV3模型的复现详解
2022/05/06 Python
MutationObserver在页面水印实现起到的作用详解
2022/07/07 Javascript