本文主要详细介绍了ID3决策树算法的python实现,具有一定的参考价值。感兴趣的朋友可以参考一下。
决策树的ID3算法及其Python实现,具体如下
主要内容
决策树的背景知识
一般决策树构造过程
ID算法拆分属性的选择
ID3算法流程及其优缺点分析
ID3算法的Python代码实现
1. 决策树背景知识
决策树是数据挖掘中最重要和最常用的方法之一,主要用于数据挖掘中的分类和预测。决策树是知识的表示,从顶点到决策树中每个节点的路径是一个分类规则。决策树算法最初是基于信息论开发的。经过几十年的发展,常用的算法有ID3、C4.5、CART等。
2. 决策树一般构建过程
构建决策树是一个自上而下的过程。树的生长过程是一个不断分割和细分数据的过程,每一次分割都会产生一个节点对应一个数据子集。从包含所有数据的根节点开始,根据所选分裂属性的属性值将训练集划分为不同的数据子集,并生成与每个训练数据子集对应的新的非叶节点。对生成的非叶子节点重复上述过程,直到满足特定的终止条件,停止划分数据子集,生成数据子集对应的叶子节点,即所需的类别。测试集验证决策树构造后的性能。如果性能不达标,就需要改进决策树算法,直到达到预期的性能指标。
注:拆分属性的选取是决策树产生过程中的关键,决定了生成的决策树的性能和结构。分裂属性选择的标准是决策树算法之间的根本区别。
3.ID3算法3354信息增益分裂属性的选择
属性的选择是决策树算法的核心。它对决策树的结构和性能起着决定性的作用。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算法是一种基于信息增益属性选择的决策树学习方法。其核心思想是通过计算属性的信息增益来选择决策树各层的分裂属性,使得在测试每个非叶节点时,可以获得关于被测样本的最大类别信息。基本方法是:计算所有属性,选择信息增益最大的属性进行拆分生成决策树节点,根据属性的不同属性值建立分支,然后对每个分支的子集递归调用此方法建立子节点的分支,直到所有子集只包含同一类别或者没有可分属性。得到一个决策树,可以用来对新的样本数据进行分类。
3d算法流程:
(1)创建一个初始节点。如果该节点中的样本都在同一类别中,则算法终止,并且该节点被标记为叶节点并标记有该类别。
(2)否则,根据算法选择信息增益最大的属性,作为节点的分裂属性。
(3)对于split属性的每个值,扩展一个对应的分支,根据属性值划分样本。
(4)用同样的过程,自上而下递归,直到满足以下三个条件之一,停止递归。
A.要分割的节点的所有样本属于同一类别。
B.对训练样本集中的所有样本进行分类。
c,所有属性都作为拆分属性执行一次。此时,如果叶节点中仍有属于不同类别的样本,则选择叶节点中样本最多的类别作为叶节点的分类。
ID3算法的优缺点
优点:建立决策树的速度比较快,算法简单,生成的规则容易理解。
缺点:在选择属性时,那些具有多个属性值的属性往往会被选为拆分属性,但这些属性不一定是最佳拆分属性;无法处理具有连续属性值的属性;没有剪枝过程,决策树无法优化,生成的决策树可能会过拟合。
5.ID3算法的Python代码实现
# -*-编码:utf-8 -*-
__author__='zhihua_oba '
进口经营者
来自numpy import *
从数学导入日志
文件读取次数
DEF2Matrix(文件名,属性数量):#传入参数:文件名,属性数量
fr=打开(文件名)
arrayOLines=fr.readlines()
行数=len (ArrayLines) # Count数据集行数(样本数)
dataMat=zeros((numberOfLines,attribute_num))
ClassLabelVector=[] #分类标签
指数=0
对于数组行中的行:
Line=line.strip() #strip()删除字符串中的' \n '
ListFromLine=line.split() #将一个字符串拆分为多个字符串的列表。当没有参数时,它被一个空格分开。有电流参数时,除以该参数。
Mat [index,=list from line[0:attribute _ num]#读取数据对象属性值。
class label vector . append(list from line[-1])#读取分类信息
指数=1
DataSet=[] #数组被转换成一个列表
指数=0
对于范围内的索引(0,numberOfLines):
temp=list(dataMat[index,])
temp . append(class label vector[index])
dataSet.append(临时)
返回数据集
#分区数据集
def splitDataSet(数据集,轴,值):
retDataSet=[]
对于数据集中的featvec每行
If featvec[axis]==value: #每行中的axis元素等于值#删除相应的元素,并将此行添加到rerDataSet。
reducedFeatVec=featvec[:axis]
reducedfeatvec . extend(featvec[轴1:])
ret dataset . append(reducedFeatVec)
返回retDataSet
#计算香农熵#计算数据集的香农熵==计算数据集标签的香农熵。
def calcShannonEnt(数据集):
NumEntries=len(dataSet) #数据集的样本点数
LabelCounts={} # Class label
对于数据集中的featVec:# Count数据集类标签的数量,字典形式
currentLabel=featVec[-1]
如果当前标签不在labelCounts.keys()中:
label counts[当前标签]=0
label counts[当前标签]=1
shannonEnt=0.0
对于标签帐户中的密钥:
prob=float(label counts[key])/numEntries
shannonEnt -=prob * log(prob,2)
返回shannonEnt
#根据香农熵,选择最佳划分方法#根据某个属性划分后,类标签的香农熵越低,效果越好。
def chooseBestFeatureToSplit(数据集):
base entropy=calcshannonent(dataset)#计算数据集的香农熵。
numFeatures=len(dataSet[0])-1
BestInfoGain=0.0 #最大信息增益
最佳功能=0 #最佳功能
对于范围内的I(0,numFeatures):
feat list=[example[I]for example in dataset]#所有子列表(每行)的第I个元素,形成一个新的列表。
uniqueVals=set(featList)
newEntorpy=0.0
对于uniqueVals中的value根据第I个属性对数据集进行划分,并计算划分后的数据集的香农熵。
subDataSet=splitDataSet(数据集,I,值)
prob=len(子数据集)/float(len(数据集))
newEntorpy=prob * calcShannonEnt(子数据集)
信息增益=基本熵-新熵#划分后的数据集,香农熵越小越好,即信息增益越大越好
if(infoGain bestInfoGain):
bestInfoGain=信息增益
bestFeature=i
返回最佳功能
#如果数据集已经处理了所有属性,但叶子结点中类标签依然不是唯一的,此时需要决定如何定义该叶子结点。这种情况下,采用多数表决方法,对该叶子结点进行分类
def majorityCnt(classList): #传入参数:叶子结点中的类标签
classCount={}
对于类别列表中的投票:
如果投票不在classCount.keys()中:
classCount[vote]=0
classCount[vote]=1
sortedClassCount=sorted(类计数。ITER项(),key=operator.itemgetter(1),reverse=True)
返回sortedClassCount[0][0]
#创建树
定义创建树(数据集,标签):#传入参数:数据集,属性标签(属性标签作用:在输出结果时,决策树的构建更加清晰)
class list=[示例[-1]例如在数据集中] #数据集样本的类标签
如果类列表。count(类列表[0])==len(类列表):#如果数据集样本属于同一类,说明该叶子结点划分完毕
返回类列表[0]
if len(dataSet[0])==1: #如果数据集样本只有一列(该列是类标签),说明所有属性都划分完毕,则根据多数表决方法,对该叶子结点进行分类
返回majorityCnt(类别列表)
best feature=chooseBestFeatureToSplit(dataSet)#根据香农熵,选择最优的划分方式
bestFeatLabel=labels[bestFeat]#记录该属性标签
myTree={bestFeatLabel:{}} #树
del(labels[bestFeat]) #在属性标签中删除该属性
#根据最优属性构建树
featValues=[example[bestFeat]数据集中的示例]
唯一值=集合(特征值)
对于唯一值:
子标签=标签[:]
subDataSet=splitDataSet(数据集,最佳特征,值)
myTree[bestFeatLabel][value]=创建树(子数据集,子标签)
返回我的树
#测试算法:使用决策树,对待分类样本进行分类
定义分类(输入树,特征标签,测试向量):#传入参数:决策树,属性标签,待分类样本
firstStr=inputTree.keys()[0] #树根代表的属性
secondDict=inputTree[firstStr]
专长索引=专长标签。索引(第一个字符串)#树根代表的属性,所在属性标签中的位置,即第几个属性
对于secondDict.keys()中的关键:
if testVec[featIndex]==key:
如果类型(secondDict[key]).__name__=='dict ':
class label=classify(第二个字典[key],featLabels,testVec)
否则:
classLabel=secondDict[key]
返回类别标签
def main():
数据集=文件2矩阵(' test _ sample。txt ',4)
标签=['属性01 ','属性02 ','属性03 ','属性04']
labelsForCreateTree=labels[:]
Tree=createTree(dataSet,labelsForCreateTree)
testvec=[2,3,2,3]
打印分类(树、标签、测试向量)
if __name__=='__main__ ':
主()
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。