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脚本内运行linux命令的方法
Jul 02 Python
发布你的Python模块详解
Sep 15 Python
Windows下安装python MySQLdb遇到的问题及解决方法
Mar 16 Python
Windows和Linux下Python输出彩色文字的方法教程
May 02 Python
python利用urllib实现爬取京东网站商品图片的爬虫实例
Aug 24 Python
flask中使用蓝图将路由分开写在不同文件实例解析
Jan 19 Python
python绘图模块matplotlib示例详解
Jul 26 Python
Django框架 Pagination分页实现代码实例
Sep 04 Python
用python画一只可爱的皮卡丘实例
Nov 21 Python
Python文字截图识别OCR工具实例解析
Mar 05 Python
python使用for...else跳出双层嵌套循环的方法实例
May 17 Python
python判断正负数方式
Jun 03 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
六酷社区论坛HOME页清新格调免费版 下载
2007/03/07 PHP
php 删除cookie和浏览器重定向
2009/03/16 PHP
PHP如何抛出异常处理错误
2011/03/02 PHP
PHP常用的文件操作函数经典收藏
2013/04/02 PHP
使用YUI+Ant 实现JS CSS压缩
2014/09/02 PHP
解决表单中第一个非隐藏的元素获得焦点的一个方案
2009/10/26 Javascript
网站页面自动跳转实现方法PHP、JSP(上)
2010/08/01 Javascript
在Ajax中使用Flash实现跨域数据读取的实现方法
2010/12/02 Javascript
JS处理json日期格式化问题
2015/10/01 Javascript
jQuery移动web开发之页面跳转和加载外部页面的实现
2015/12/04 Javascript
ES6概念 ymbol.for()方法
2016/12/25 Javascript
BootStrap TreeView使用实例详解
2017/11/01 Javascript
解决使用Vue.js显示数据的时,页面闪现原始代码的问题
2018/02/11 Javascript
浅谈Vue.js路由管理器 Vue Router
2018/08/16 Javascript
小程序云开发部署攻略(图文教程)
2018/10/30 Javascript
使用Easyui实现查询条件的后端传递并自动刷新表格的两种方法
2019/09/09 Javascript
基于node+websocket+html实现腾讯课堂聊天室聊天功能
2020/03/04 Javascript
浅谈vue中$event理解和框架中在包含默认值外传参
2020/08/07 Javascript
OpenLayers3实现对地图的基本操作
2020/09/28 Javascript
vue 项目@change多个参数传值多个事件的操作
2021/01/29 Vue.js
[06:43]DAC2018 4.5 SOLO赛 Maybe vs Paparazi
2018/04/06 DOTA
Ubuntu安装Jupyter Notebook教程
2017/10/18 Python
Python中使用Counter进行字典创建以及key数量统计的方法
2018/07/06 Python
Django中的用户身份验证示例详解
2019/08/07 Python
python基于FTP实现文件传输相关功能代码实例
2019/09/28 Python
python list的index()和find()的实现
2020/11/16 Python
使用Python爬取小姐姐图片(beautifulsoup法)
2021/02/11 Python
BSTN意大利:德国街头和运动文化高品质商店
2020/12/22 全球购物
适用于所有创业者的创业计划书
2014/02/05 职场文书
打架检讨书2000字
2014/02/22 职场文书
副职竞争上岗演讲稿
2014/05/12 职场文书
学校先进集体事迹材料
2014/05/31 职场文书
中国梦读书活动总结
2014/07/10 职场文书
家访教师心得体会
2016/01/23 职场文书
二年级数学教学反思
2016/02/16 职场文书
Python下opencv使用hough变换检测直线与圆
2021/06/18 Python