,,决策树剪枝算法的python实现方法详解

,,决策树剪枝算法的python实现方法详解

本文主要介绍了决策树剪枝算法的python实现方法,结合实例详细分析了决策树剪枝算法的概念和原理,并结合实例分析了Python的相关实现技巧。有需要的可以参考一下。

本文结合实例描述了决策树剪枝算法的python实现方法。分享给你,供你参考,如下:

决策树是一种决策建立的树。在机器学习中,决策树是一种预测模型,表示对象属性和对象值之间的映射关系。每个节点代表一个对象,树中的每个分支路径代表一个可能的属性值,每个叶节点代表从根节点到叶节点的路径所代表的对象的值。决策树只有一个输出。如果有多个输出,可以建立独立的决策树来处理不同的输出。

ID3算法:ID3算法是决策树的一种,基于奥卡姆剃刀原理,即尽量少花钱多办事。ID3算法,即迭代二分器3,迭代二叉树生成3,是Ross Quinlan发明的决策树算法。这个算法是基于上面提到的奥卡姆剃刀原理。决策树越小,决策树越好。然而,它并不总是生成最小的树结构,但它是一种启发式算法。在信息论中,期望信息越小,信息增益越大,因而纯度越高。ID3算法的核心思想是用信息增益来衡量属性的选择,选择分裂后信息增益最大的属性进行分裂。该算法使用自顶向下的贪婪搜索来遍历可能的决策空间。

信息熵被定义为离散随机事件的概率。系统越有序,信息熵越低。相反,系统越混乱,其信息熵越高。因此,信息熵可以看作是系统有序程度的一种度量。

基尼指数:CART中的决策树除以基尼指数,基尼指数定义如下:Gini (t)=1sumnj=1p2j。其中(p_j)是类J在T中的相对频率,当类在T中倾斜时,gini(T)将最小。T分成两个子集T1(实例数为N1)和T2(实例数为N2)后,划分数据的Gini定义如下:Gini Split(T)=frac n1 ngini(T1)frac N2 ngini(T2),然后选取最小的一个(gini_{split}(T))作为节点划分决策树。

具体实现

首先,利用calcShanno函数计算数据集的Shannon熵,并为所有可能的分类建立字典。

def calcShannonEnt(数据集):

numEntries=len(数据集)

labelCounts={}

#为所有可能的分类创建字典

对于数据集中的featVec:

currentLabel=featVec[-1]

如果当前标签不在labelCounts.keys()中:

label counts[当前标签]=0

label counts[当前标签]=1

shannonEnt=0.0

#基于2计算香农熵

对于标签帐户中的密钥:

prob=float(label counts[key])/numEntries

shannonEnt -=prob * log(prob,2)

返回shannonEnt

#划分离散变量的数据集,取出所有具有该特征值的样本。

def splitDataSet(数据集,轴,值):

retDataSet=[]

对于数据集中的featVec:

if featVec[轴]==值:

reducedFeatVec=featVec[:axis]

reducedfeatvec . extend(featVec[轴1:])

ret dataset . append(reducedFeatVec)

返回retDataSet

对于连续变量划分数据集,direction指定划分的方向,决定是划分小于value的数据样本还是大于value的数据样本集。

numFeatures=len(dataSet[0]) - 1

baseEntropy=calcShannonEnt(数据集)

bestInfoGain=0.0

bestFeature=-1

bestSplitDict={ }

对于范围内的I(num features):

featList=[example[i]数据集中的示例]

#处理连续特征

if类型(featList[0])。__name__=='float '或type(featList[0])。__name__=='int ':

#生成n-1个候选分割点

sortfeatList=已排序(featList)

splitList=[]

对于范围内的j(len(sortfeatList)-1):

split list . append((sortfeatList[j]sortfeatList[j 1])/2.0)

bestSplitEntropy=10000

slen=len(拆分列表)

# 求用第j个候选划分点划分时,得到的信息熵,并记录最佳划分点

对于范围内的j(斯伦):

value=splitList[j]

新熵=0.0

子数据集0=splitContinuousDataSet(数据集,我,值,0)

子数据集1=splitContinuousDataSet(数据集,我,值,1)

prob0=len(子数据集0)/float(len(数据集))

new entropy=prob 0 * calcShannonEnt(子数据集0)

prob1=len(子数据集1)/float(镜头(数据集))

new entropy=pro B1 * calcShannonEnt(子数据集1)

如果新熵大于分裂熵:

bestSplitEntropy=newEntropy

最佳分割=j

# 用字典记录当前特征的最佳划分点

bessplitdict[labels[I]]=拆分列表[最佳拆分]

信息增益=基本熵-基本分裂熵

# 对离散型特征进行处理

否则:

uniqueVals=set(featList)

新熵=0.0

# 计算该特征下每种划分的信息熵

对于唯一值:

subDataSet=splitDataSet(数据集,我,值)

prob=len(子数据集)/float(len(数据集))

newEntropy=prob * calcShannonEnt(子数据集)

信息增益=基础熵-新熵

如果信息增益最佳信息增益:

bestInfoGain=信息增益

bestFeature=i

# 若当前节点的最佳划分特征为连续特征,则将其以之前记录的划分点为界进行二值化处理

# 即是否小于等于bestSplitValue

如果类型(数据集[0][最佳功能]).__name__=='float '或type(数据集[0][bestFeature]).__name__=='int ':

bessplitvalue=bessplitdict[labels[最佳功能]]

labels[最佳功能]=labels[最佳功能]'=' str(bessplitvalue)

对于范围内的我(形状(数据集)[0]):

如果数据集[I][最佳特征]=最佳分割值:

数据集[I][最佳特征]=1

否则:

数据集[I][最佳功能]=0

返回最佳功能

def chooseBestFeatureToSplit(数据集,标注):

numFeatures=len(dataSet[0]) - 1

baseEntropy=calcShannonEnt(数据集)

bestInfoGain=0.0

bestFeature=-1

bestSplitDict={ }

对于范围内的I(数字特征):

feat list=[示例[i]数据集中的示例]

# 对连续型特征进行处理

如果类型(featList[0]).__name__=='float '或类型(featList[0]).__name__=='int ':

# 产生n-1个候选划分点

sortfeatList=已排序(特征列表)

splitList=[]

对于范围内的j(len(sortfeatList)-1):

拆分列表。append((sortfeatList[j]sortfeatList[j 1])/2.0)

bestSplitEntropy=10000

slen=len(拆分列表)

# 求用第j个候选划分点划分时,得到的信息熵,并记录最佳划分点

对于范围内的j(斯伦):

value=splitList[j]

新熵=0.0

子数据集0=splitContinuousDataSet(数据集,我,值,0)

子数据集1=splitContinuousDataSet(数据集,我,值,1)

prob0=len(子数据集0)/float(len(数据集))

new entropy=prob 0 * calcShannonEnt(子数据集0)

prob1=len(子数据集1)/float(镜头(数据集))

new entropy=pro B1 * calcShannonEnt(子数据集1)

如果新熵大于分裂熵:

bestSplitEntropy=newEntropy

最佳分割=j

# 用字典记录当前特征的最佳划分点

bessplitdict[labels[I]]=拆分列表[最佳拆分]

信息增益=基本熵-基本分裂熵

# 对离散型特征进行处理

否则:

uniqueVals=set(featList)

新熵=0.0

# 计算该特征下每种划分的信息熵

对于唯一值:

subDataSet=splitDataSet(数据集,我,值)

prob=len(子数据集)/float(len(数据集))

newEntropy=prob * calcShannonEnt(子数据集)

信息增益=基础熵-新熵

如果信息增益最佳信息增益:

bestInfoGain=信息增益

bestFeature=i

# 若当前节点的最佳划分特征为连续特征,则将其以之前记录的划分点为界进行二值化处理

# 即是否小于等于bestSplitValue

如果类型(数据集[0][最佳功能]).__name__=='float '或type(数据集[0][bestFeature]).__name__=='int ':

bessplitvalue=bessplitdict[labels[最佳功能]]

labels[最佳功能]=labels[最佳功能]'=' str(bessplitvalue)

对于范围内的我(形状(数据集)[0]):

如果数据集[I][最佳特征]=最佳分割值:

数据集[I][最佳特征]=1

否则:

数据集[I][最佳功能]=0

返回最佳功能

" def classify(inputTree,featLabels,testVec):

firstStr=inputTree.keys()[0]

如果第一Str中有u'=':

featvalue=float(第一个字符串。split(u '=')[1])

专长键=第一串。split(u '=')[0]

secondDict=inputTree[firstStr]

专长索引=专长标签。索引(专长键)

如果testVec[featIndex]=特征值:

法官=1

否则:

法官=0

对于secondDict.keys()中的关键:

if judge==int(key):

如果类型(secondDict[key]).__name__=='dict ':

class label=classify(第二个字典[key],featLabels,testVec)

否则:

classLabel=secondDict[key]

否则:

secondDict=inputTree[firstStr]

专长索引=专长标签。索引(第一个字符串)

对于secondDict.keys()中的关键:

if testVec[featIndex]==key:

如果类型(secondDict[key]).__name__=='dict ':

class label=classify(第二个字典[key],featLabels,testVec)

否则:

classLabel=secondDict[key]

返回类别标签

大多数人(类别列表):

classCount={}

对于类别列表中的投票:

如果投票不在classCount.keys()中:

classCount[vote]=0

classCount[vote]=1

返回最大值(类计数)

极好的测试_feat(feat,train_data,test_data,标签):

class _ list=[示例[-1]例如在列车数据中]

bestFeatIndex=标签。索引(专长)

train _ data=[示例[bestFeatIndex]例如在列车数据中]

test_data=[(示例[bestFeatIndex],示例[-1])例如在测试数据中]

all_feat=set(train_data)

误差=0.0

对于all_feat的价值:

class _ feat=[class _ list[I]for I in range(len(class _ list))if train _ data[I]==value]

major=majorityCnt(class_feat)

对于测试数据中的数据:

如果数据[0]==值和数据[1]!=专业:

误差=1.0

# print 'myTree %d' %错误

返回误差

测试

误差=0.0

对于范围内的I(len(data _ test)):

如果分类(我的树,标签,data_test[i])!=data_test[i][-1]:

误差=1

# print 'myTree %d' %错误

返回浮动(错误)

def测试主(专业,数据_测试):

误差=0.0

对于范围内的I(len(data _ test)):

如果少校!=data_test[i][-1]:

误差=1

#打印“主要% d”%错误

返回浮动(错误)

**递归产生决策树**

` ` def创建树(数据集,标签,数据_完整,标签_完整,测试_数据,模式):

class list=[示例[-1]例如在数据集中]

如果类列表。count(类列表[0])==len(类列表):

返回类列表[0]

if len(dataSet[0])==1:

返回majorityCnt(类别列表)

labels_copy=copy.deepcopy(标签)

最佳壮举=chooseBestFeatureToSplit(数据集,标注)

bestFeatLabel=labels[bestFeat]

如果mode=='unpro '或mode=='post ':

myTree={bestFeatLabel: {}}

elif mode=='prev ':

如果testing_feat(bestFeatLabel,dataSet,test_data,labels _ copy)测试专业(majority CNT(class list),

测试数据):

myTree={bestFeatLabel: {}}

否则:

返回majorityCnt(类别列表)

featValues=[example[bestFeat]数据集中的示例]

唯一值=集合(特征值)

如果类型(数据集[0][最佳成绩]).__name__=='unicode ':

当前标签=标签_满。索引(标签[最佳专长])

featValuesFull=[示例[当前标签]例如在数据_完整中]

uniqueValsFull=set(featValuesFull)

德尔(标签[最佳成绩])

对于唯一值:

子标签=标签[:]

如果类型(数据集[0][最佳成绩]).__name__=='unicode ':

uniqueValsFull.remove(值)

myTree[bestFeatLabel][value]=创建树(拆分数据集\

(数据集,最佳特征,值),子标签,数据_完整,标签_完整,

splitDataSet \

(test_data,bestFeat,value),mode=mode)

如果类型(数据集[0][最佳成绩]).__name__=='unicode ':

对于唯一值完整:

myTree[bestFeatLabel][value]=多数CNT(类别列表)

if mode=='post ':

如果测试(myTree,test_data,labels _ copy)测试专业(majority CNT(class list),test_data):

返回majorityCnt(类别列表)

返回我的树

div class=' se-预览-部分-分隔符/div

```**读入数据**

` ` def load_data(文件名):

用打开(r'dd.csv ',' rb ')作为女:

df=pd.read_csv(f,sep=',')

打印(df)

train_data=df.values[:11,1:].tolist()

打印(列车数据)

test_data=df.values[11:1:].tolist()

labels=df.columns.values[1:-1].tolist()

返回训练数据、测试数据、标签

div class=' se-预览-部分-分隔符/div

```测试并绘制树图

将matplotlib.pyplot作为plt导入

decision node=dict(box style=' round 4 ',color='red') #定义判断结点形态

leafNode=dict(boxstyle='circle ',color='grey') #定义叶结点形态

arrow_args=dict(arrowstyle='-',color='blue') #定义箭头

# 计算树的叶子节点数量

def getNumLeafs(myTree):

numLeafs=0

firstSides=list(myTree.keys())

firstStr=firstSides[0]

secondDict=myTree[firstStr]

对于secondDict.keys()中的关键:

如果类型(secondDict[key]).__name__=='dict ':

numLeafs=getNumLeafs(第二个字典[key])

否则:

numLeafs=1

返回数字

# 计算树的最大深度

def gettredepth(我的树):

最大深度=0

firstSides=list(myTree.keys())

firstStr=firstSides[0]

secondDict=myTree[firstStr]

对于secondDict.keys()中的关键:

如果类型(secondDict[key]).__name__=='dict ':

this depth=1 getTreeDepth(第二个字典[key])

否则:

thisDepth=1

如果thisDepth maxDepth:

maxDepth=thisDepth

返回最大深度

# 画节点

def plotNode(nodeTxt,centerPt,parentPt,nodeType):

创造情节。ax1。annotate(node txt,xy=parentPt,xycoords='轴分数',\

xytext=centerPt,textcoords='轴分数,va='中心,哈='中心',\

bbox=nodeType,arrowprops=arrow_args)

# 画箭头上的文字

def plotMidText(cntrPt,parentPt,txtString):

lens=len(txtString)

xMid=(parent pt[0]cntrPt[0])/2.0-lens * 0.002

yMid=(父pt[1]cntrPt[1])/2.0

createPlot.ax1.text(xMid,yMid,txtString)

def plotTree(myTree,parentPt,nodeTxt):

numLeafs=getNumLeafs(myTree)

depth=getTreeDepth(myTree)

firstSides=list(myTree.keys())

firstStr=firstSides[0]

cntrPt=(plottree。x0ff(1.0 float(numLeafs))/2.0/plottree。totalw,plotTree.y0ff)

plotMidText(cntrPt,parentPt,nodeTxt)

plotNode(firstStr,cntrPt,parentPt,decisionNode)

secondDict=myTree[firstStr]

绘图树。y0ff=绘图树。y0ff-1.0/绘图树。总计

对于secondDict.keys()中的关键:

如果类型(secondDict[key]).__name__=='dict ':

plotTree(secondDict[key],cntrPt,str(key))

否则:

绘图树。x0ff=绘图树。x0ff 1.0/绘图树。总计w

plotNode(secondDict[key],(plotTree.x0ff,plotTree.y0ff),cntrPt,leafNode)

plotMidText((plotTree.x0ff,plotTree.y0ff),cntrPt,str(key))

绘图树。y0ff=绘图树。y0ff 1.0/绘图树。总计d

def createPlot(inTree):

fig=plt.figure(1,facecolor='white ')

图.clf()

axprops=dict(xticks=[],yticks=[])

createPlot.ax1=plt.subplot(111,frameon=False,**axprops)

plottree。total w=float(getNumLeafs(inTree))

plottree。totald=float(gettree depth(inTree))

绘图树。x0ff=-0.5/绘图树。总计w

plotTree.y0ff=1.0

plotTree(inTree,(0.5,1.0),'')

plt.show()

if __name__=='__main__ ':

train_data,test_data,labels=load_data('dd.csv ')

data_full=train_data[:]

标签_满=标签[:]

mode='post '

mode='prev '

mode='post '

myTree=createTree(train_data,labels,data_full,labels_full,test_data,mode=mode)

创建绘图(我的树)

print(json.dumps(myTree,确保_ascii=False,indent=4))

选择方式就可以分别得到三种树图

if __name__=='__main__ ':

train_data,test_data,labels=load_data('dd.csv ')

data_full=train_data[:]

标签_满=标签[:]

mode='post '

mode='prev '

mode='post '

myTree=createTree(train_data,labels,data_full,labels_full,test_data,mode=mode)

创建绘图(我的树)

print(json.dumps(myTree,确保_ascii=False,indent=4))

选择方式就可以分别得到三种树图

更多关于计算机编程语言相关内容感兴趣的读者可查看本站专题: 《Python数据结构与算法教程》 、 《Python加密解密算法与技巧总结》 、 《Python编码操作技巧总结》 、 《Python函数使用技巧总结》 、 《Python字符串操作技巧汇总》 及《Python入门与进阶经典教程》

希望本文所述对大家计算机编程语言程序设计有所帮助。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: