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求素数示例分享
Feb 16 Python
Python实现的爬取网易动态评论操作示例
Jun 06 Python
python 读取文件并替换字段的实例
Jul 12 Python
python 提取tuple类型值中json格式的key值方法
Dec 31 Python
python实现在遍历列表时,直接对dict元素增加字段的方法
Jan 15 Python
django的settings中设置中文支持的实现
Apr 28 Python
Django处理多用户类型的方法介绍
May 18 Python
Django框架HttpResponse对象用法实例分析
Nov 01 Python
Python itertools.product方法代码实例
Mar 27 Python
python获取百度热榜链接的实例方法
Aug 25 Python
python入门教程之基本算术运算符
Nov 13 Python
python 进制转换 int、bin、oct、hex的原理
Jan 13 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
PHP4之真OO
2006/10/09 PHP
兼容PHP和Java的des加密解密代码分享
2014/06/26 PHP
浅谈PHP中其他类型转化为Bool类型
2016/03/28 PHP
PHP 绘制网站登录首页图片验证码
2016/04/12 PHP
PHP实现生成推广海报的方法详解
2018/03/14 PHP
php实现微信原生支付(扫码支付)功能
2018/05/30 PHP
学习YUI.Ext基础第一天
2007/03/10 Javascript
jquery 与NVelocity 产生冲突的解决方法
2011/06/13 Javascript
JQuery入门——事件切换之toggle()方法应用介绍
2013/02/05 Javascript
js单向链表的具体实现实例
2013/06/21 Javascript
基于jquery的网站幻灯片切换效果焦点图代码
2013/09/15 Javascript
探讨jQuery的ajax使用场景(c#)
2013/12/03 Javascript
jQuery控制文本框只能输入数字和字母及使用方法
2016/05/26 Javascript
浅谈js多维数组和hash数组定义和使用
2016/07/27 Javascript
Vue.js实现表格动态增加删除的方法(附源码下载)
2017/01/20 Javascript
用js实现before和after伪类的样式修改的示例代码
2017/09/07 Javascript
解决layer 动态加载select 失效的问题
2019/09/18 Javascript
vue2路由基本用法实例分析
2020/03/06 Javascript
JS操作JSON常用方法(10w阅读)
2020/12/06 Javascript
JS获取一个字符串中指定字符串第n次出现的位置
2021/02/10 Javascript
python回调函数的使用方法
2014/01/23 Python
python多线程用法实例详解
2015/01/15 Python
浅析Python装饰器以及装饰器模式
2018/05/28 Python
浅析python表达式4+0.5值的数据类型
2020/02/26 Python
Python实现读取并写入Excel文件过程解析
2020/05/27 Python
一些关于python 装饰器的个人理解
2020/08/31 Python
Python tkinter制作单机五子棋游戏
2020/09/14 Python
Html5大文件断点续传实现方法
2015/12/05 HTML / CSS
斯凯奇美国官网:SKECHERS美国
2016/08/20 全球购物
运动会入场解说词300字
2014/01/25 职场文书
技术岗位竞聘演讲稿
2014/05/16 职场文书
三方股东合作协议书范本
2014/09/28 职场文书
区长工作作风个人整改措施
2014/10/01 职场文书
新员工入职感言范文!
2019/07/04 职场文书
Pytorch中Softmax与LogSigmoid的对比分析
2021/06/05 Python
Python使用Opencv打开笔记本电脑摄像头报错解问题及解决
2022/06/21 Python