python实现ID3决策树算法


Posted in Python onDecember 20, 2017

决策树之ID3算法及其Python实现,具体内容如下

主要内容

决策树背景知识
决策树一般构建过程
ID3算法分裂属性的选择
ID3算法流程及其优缺点分析
ID3算法Python代码实现

1. 决策树背景知识

  决策树是数据挖掘中最重要且最常用的方法之一,主要应用于数据挖掘中的分类和预测。决策树是知识的一种呈现方式,决策树中从顶点到每个结点的路径都是一条分类规则。决策树算法最先基于信息论发展起来,经过几十年发展,目前常用的算法有:ID3、C4.5、CART算法等。

2. 决策树一般构建过程

  构建决策树是一个自顶向下的过程。树的生长过程是一个不断把数据进行切分细分的过程,每一次切分都会产生一个数据子集对应的节点。从包含所有数据的根节点开始,根据选取分裂属性的属性值把训练集划分成不同的数据子集,生成由每个训练数据子集对应新的非叶子节点。对生成的非叶子节点再重复以上过程,直到满足特定的终止条件,停止对数据子集划分,生成数据子集对应的叶子节点,即所需类别。测试集在决策树构建完成后检验其性能。如果性能不达标,我们需要对决策树算法进行改善,直到达到预期的性能指标。
  注:分裂属性的选取是决策树生产过程中的关键,它决定了生成的决策树的性能、结构。分裂属性选择的评判标准是决策树算法之间的根本区别。

3. ID3算法分裂属性的选择——信息增益

  属性的选择是决策树算法中的核心。是对决策树的结构、性能起到决定性的作用。ID3算法基于信息增益的分裂属性选择。基于信息增益的属性选择是指以信息熵的下降速度作为选择属性的方法。它以的信息论为基础,选择具有最高信息增益的属性作为当前节点的分裂属性。选择该属性作为分裂属性后,使得分裂后的样本的信息量最大,不确定性最小,即熵最小。
  信息增益的定义为变化前后熵的差值,而熵的定义为信息的期望值,因此在了解熵和信息增益之前,我们需要了解信息的定义。
  信息:分类标签xi 在样本集 S 中出现的频率记为 p(xi),则 xi 的信息定义为:−log2p(xi) 。
  分裂之前样本集的熵:E(S)=−∑Ni=1p(xi)log2p(xi),其中 N 为分类标签的个数。
  通过属性A分裂之后样本集的熵:EA(S)=−∑mj=1|Sj||S|E(Sj),其中 m 代表原始样本集通过属性A的属性值划分为 m 个子样本集,|Sj| 表示第j个子样本集中样本数量,|S| 表示分裂之前数据集中样本总数量。
  通过属性A分裂之后样本集的信息增益:InfoGain(S,A)=E(S)−EA(S)
  注:分裂属性的选择标准为:分裂前后信息增益越大越好,即分裂后的熵越小越好。

4. ID3算法

  ID3算法是一种基于信息增益属性选择的决策树学习方法。核心思想是:通过计算属性的信息增益来选择决策树各级节点上的分裂属性,使得在每一个非叶子节点进行测试时,获得关于被测试样本最大的类别信息。基本方法是:计算所有的属性,选择信息增益最大的属性分裂产生决策树节点,基于该属性的不同属性值建立各分支,再对各分支的子集递归调用该方法建立子节点的分支,直到所有子集仅包括同一类别或没有可分裂的属性为止。由此得到一棵决策树,可用来对新样本数据进行分类。

ID3算法流程:

(1) 创建一个初始节点。如果该节点中的样本都在同一类别,则算法终止,把该节点标记为叶节点,并用该类别标记。
(2) 否则,依据算法选取信息增益最大的属性,该属性作为该节点的分裂属性。
(3) 对该分裂属性中的每一个值,延伸相应的一个分支,并依据属性值划分样本。
(4) 使用同样的过程,自顶向下的递归,直到满足下面三个条件中的一个时就停止递归。
  A、待分裂节点的所有样本同属于一类。
  B、训练样本集中所有样本均完成分类。
  C、所有属性均被作为分裂属性执行一次。若此时,叶子结点中仍有属于不同类别的样本时,选取叶子结点中包含样本最多的类别,作为该叶子结点的分类。

ID3算法优缺点分析

优点:构建决策树的速度比较快,算法实现简单,生成的规则容易理解。
缺点:在属性选择时,倾向于选择那些拥有多个属性值的属性作为分裂属性,而这些属性不一定是最佳分裂属性;不能处理属性值连续的属性;无修剪过程,无法对决策树进行优化,生成的决策树可能存在过度拟合的情况。

5. ID3算法Python代码实现

# -*- coding: utf-8 -*-
__author__ = 'zhihua_oba'

import operator
from numpy import *
from math import log

#文件读取
def file2matrix(filename, attribute_num): #传入参数:文件名,属性个数
 fr = open(filename)
 arrayOLines = fr.readlines()
 numberOfLines = len(arrayOLines) #统计数据集行数(样本个数)
 dataMat = zeros((numberOfLines, attribute_num))
 classLabelVector = [] #分类标签
 index = 0
 for line in arrayOLines:
  line = line.strip() #strip() 删除字符串中的'\n'
  listFromLine = line.split() #将一个字符串分裂成多个字符串组成的列表,不带参数时以空格进行分割,当代参数时,以该参数进行分割
  dataMat[index, : ] = listFromLine[0:attribute_num] #读取数据对象属性值
  classLabelVector.append(listFromLine[-1]) #读取分类信息
  index += 1
 dataSet = [] #数组转化成列表
 index = 0
 for index in range(0, numberOfLines):
  temp = list(dataMat[index, :])
  temp.append(classLabelVector[index])
  dataSet.append(temp)
 return dataSet

#划分数据集
def splitDataSet(dataSet, axis, value):
 retDataSet = []
 for featvec in dataSet: #每行
  if featvec[axis] == value: #每行中第axis个元素和value相等 #删除对应的元素,并将此行,加入到rerDataSet
   reducedFeatVec = featvec[:axis]
   reducedFeatVec.extend(featvec[axis+1:])
   retDataSet.append(reducedFeatVec)
 return retDataSet

#计算香农熵 #计算数据集的香农熵 == 计算数据集类标签的香农熵
def calcShannonEnt(dataSet):
 numEntries = len(dataSet) #数据集样本点个数
 labelCounts = {} #类标签
 for featVec in dataSet: #统计数据集类标签的个数,字典形式
  currentLabel = featVec[-1]
  if currentLabel not in labelCounts.keys():
   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 chooseBestFeatureToSplit(dataSet):
 baseEntropy = calcShannonEnt(dataSet) #计算数据集的香农熵
 numFeatures = len(dataSet[0])-1
 bestInfoGain = 0.0 #最大信息增益
 bestFeature = 0 #最优特征
 for i in range(0, numFeatures):
  featList = [example[i] for example in dataSet] #所有子列表(每行)的第i个元素,组成一个新的列表
  uniqueVals = set(featList)
  newEntorpy = 0.0
  for value in uniqueVals: #数据集根据第i个属性进行划分,计算划分后数据集的香农熵
   subDataSet = splitDataSet(dataSet, i, value)
   prob = len(subDataSet)/float(len(dataSet))
   newEntorpy += prob*calcShannonEnt(subDataSet)
  infoGain = baseEntropy-newEntorpy #划分后的数据集,香农熵越小越好,即信息增益越大越好
  if(infoGain > bestInfoGain):
   bestInfoGain = infoGain
   bestFeature = i
 return bestFeature

#如果数据集已经处理了所有属性,但叶子结点中类标签依然不是唯一的,此时需要决定如何定义该叶子结点。这种情况下,采用多数表决方法,对该叶子结点进行分类
def majorityCnt(classList): #传入参数:叶子结点中的类标签
 classCount = {}
 for vote in classList:
  if vote not in classCount.keys():
   classCount[vote] = 0
   classCount[vote] += 1
 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
 return sortedClassCount[0][0]

#创建树
def createTree(dataSet, labels): #传入参数:数据集,属性标签(属性标签作用:在输出结果时,决策树的构建更加清晰)
 classList = [example[-1] for example in dataSet] #数据集样本的类标签
 if classList.count(classList[0]) == len(classList): #如果数据集样本属于同一类,说明该叶子结点划分完毕
  return classList[0]
 if len(dataSet[0]) == 1: #如果数据集样本只有一列(该列是类标签),说明所有属性都划分完毕,则根据多数表决方法,对该叶子结点进行分类
  return majorityCnt(classList)
 bestFeat = chooseBestFeatureToSplit(dataSet) #根据香农熵,选择最优的划分方式
 bestFeatLabel = labels[bestFeat] #记录该属性标签
 myTree = {bestFeatLabel:{}} #树
 del(labels[bestFeat]) #在属性标签中删除该属性
 #根据最优属性构建树
 featValues = [example[bestFeat] for example in dataSet]
 uniqueVals = set(featValues)
 for value in uniqueVals:
  subLabels = labels[:]
  subDataSet = splitDataSet(dataSet, bestFeat, value)
  myTree[bestFeatLabel][value] = createTree(subDataSet, subLabels)
 return myTree

#测试算法:使用决策树,对待分类样本进行分类
def classify(inputTree, featLabels, testVec): #传入参数:决策树,属性标签,待分类样本
 firstStr = inputTree.keys()[0] #树根代表的属性
 secondDict = inputTree[firstStr]
 featIndex = featLabels.index(firstStr) #树根代表的属性,所在属性标签中的位置,即第几个属性
 for key in secondDict.keys():
  if testVec[featIndex] == key:
   if type(secondDict[key]).__name__ == 'dict':
    classLabel = classify(secondDict[key], featLabels, testVec)
   else:
    classLabel = secondDict[key]
 return classLabel

def main():
 dataSet = file2matrix('test_sample.txt', 4)
 labels = ['attr01', 'attr02', 'attr03', 'attr04']
 labelsForCreateTree = labels[:]
 Tree = createTree(dataSet, labelsForCreateTree )
 testvec = [2, 3, 2, 3]
 print classify(Tree, labels, testvec)
if __name__ == '__main__':
  main()

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

Python 相关文章推荐
Python中多线程及程序锁浅析
Jan 21 Python
Python中使用dom模块生成XML文件示例
Apr 05 Python
Python的socket模块源码中的一些实现要点分析
Jun 06 Python
Python 12306抢火车票脚本
Feb 07 Python
使用pandas中的DataFrame数据绘制柱状图的方法
Apr 10 Python
使用Python获取并处理IP的类型及格式方法
Nov 01 Python
如何利用Python分析出微信朋友男女统计图
Jan 25 Python
Python之pymysql的使用小结
Jul 01 Python
python pptx复制指定页的ppt教程
Feb 14 Python
python连接mysql数据库并读取数据的实现
Sep 25 Python
python 读取、写入txt文件的示例
Sep 27 Python
[原创]赚疯了!转手立赚800+?大佬的python「抢茅台脚本」使用教程
Jan 12 Python
理解python中生成器用法
Dec 20 #Python
Python利用turtle库绘制彩虹代码示例
Dec 20 #Python
浅谈Python中range和xrange的区别
Dec 20 #Python
python机器学习实战之树回归详解
Dec 20 #Python
使用python 和 lint 删除项目无用资源的方法
Dec 20 #Python
python机器学习实战之K均值聚类
Dec 20 #Python
Python绘制3d螺旋曲线图实例代码
Dec 20 #Python
You might like
PHP session会话的安全性分析
2011/09/08 PHP
PHP判断一个gif图片是否为动态图片的方法
2014/11/19 PHP
php基于curl实现的股票信息查询类实例
2016/11/11 PHP
SOSO地图JS画出标注和中心点以html形式运行
2013/08/09 Javascript
js保留小数点后几位的写法
2014/01/03 Javascript
jquery对元素拖动排序示例
2014/01/16 Javascript
JavaScript中的ajax功能的概念和示例详解
2016/10/17 Javascript
基于Vuejs框架实现翻页组件
2020/06/29 Javascript
JS实现页面进入和返回定位到具体位置
2016/12/08 Javascript
Vue.js系列之项目搭建(1)
2017/01/03 Javascript
javascript 封装Date日期类实例详解
2017/05/28 Javascript
解决vue.js 数据渲染成功仍报错的问题
2018/08/25 Javascript
jQuery使用$.extend(true,object1, object2);实现深拷贝对象的方法分析
2019/03/06 jQuery
Vue scoped及deep使用方法解析
2020/08/01 Javascript
在Python中操作时间之strptime()方法的使用
2020/12/30 Python
Python编程中归并排序算法的实现步骤详解
2016/05/04 Python
深入理解python中的闭包和装饰器
2016/06/12 Python
Python爬虫常用小技巧之设置代理IP
2018/09/13 Python
python使用folium库绘制地图点击框
2018/09/21 Python
Python批处理更改文件名os.rename的方法
2018/10/26 Python
使用Filter过滤python中的日志输出的实现方法
2019/07/17 Python
Python Numpy数组扩展repeat和tile使用实例解析
2019/12/09 Python
5行Python代码实现图像分割的步骤详解
2020/05/25 Python
在keras 中获取张量 tensor 的维度大小实例
2020/06/10 Python
欧洲最大的高尔夫零售商:American Golf
2019/09/02 全球购物
酒店出纳岗位职责
2013/12/29 职场文书
团购业务员岗位职责
2014/03/15 职场文书
党员干部群众路线个人整改措施
2014/09/18 职场文书
四风问题自我剖析材料
2014/10/07 职场文书
公司租房协议书范本
2014/10/08 职场文书
2014年语文教师工作总结
2014/12/18 职场文书
全国爱眼日活动总结
2015/02/27 职场文书
大专护理专业自荐信
2015/03/25 职场文书
《确定位置》教学反思
2016/02/18 职场文书
如何做好工作总结!
2019/04/10 职场文书
2019大学竞选班长发言稿
2019/06/27 职场文书