本文主要介绍了决策树剪枝算法的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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。