机器学习实战第三章——决策树,读书笔记

xiaoxiao2021-02-28  91

         决策树是一种常见的机器学习方法,也称作“判定树”。决策树是根据树结构来进行决策的,决策过程中提出的每一个判定都是对某个属性的“测试”,每个测试的结果或是导出最终结论,或者导出进一步的判定问题,在测评那种数据划分方式是做好的数据划分的时候,有多种测量方法,其中有一种计算信息增益的方法,叫作香农熵。“信息熵”是用来度量两种概率分布的差异,假设当前样本的集合D中第k类样本所占的比例为pk(k=1,2,...,|y|),则D的信息熵为:

    下面是计算给定数据集的香农熵:

from math import log def calcShannonEnt(dataSet): numEntries=len(dataSet) #numEntries得到的是数据集的大小,保存实例总数 labelCounts={} for featVec in dataSet: #为了所有数据创建一个字典,方便后面的求每种类的概率 currentLabel=featVec[-1] #创建一个数据字典,健值是最后一列的值,取该数据的特征标签 if currentLabel not in labelCounts.keys(): #如果该特征标签不存在 labelCounts[currentLabels]=0 #则扩展字典并将当前标签加入字典 labelCounts[currentLabels]+=1 #记录每个类别出现的次数 shannonEnt=0.0 for key in labelCounts: prob=float(labelCounts[key])/numEntries #每个类别除以总数,是该类别的概率,也就是上面式子中的pk shannonEnt-=prob*log(prob,2) *这一行就是上述pk乘以以2为底的对数 return shannonEnt 测试上面的代码的结果为:

下面开始划分数据集:

这个函数的作用是将第axis列中等于value的数据集划分出来

def splitDataSet(dataSet,axis,value): #可以看到这个函数有三个输入参数:待划分的数据集,划分数据集的特征以及需要返回的特征的值 retDataSet=[] #因为该函数在同一个数据集上调用了很多次,所以定义一个新的列表对象 for featVec in dataSet: #遍历数据集中的每个元素的特征 if featVec[axis]==value: #如果该数据的这个特征的值符合要求 reducedFeatVec=featVec[:axis] #axis前几行 reducedFeatVec.extend(featVec[axis+1:]) #跳过axis,添加之后的之后的 retDataSet.append(reducedFeatVec) return retDataSet

下面是选择最好的数据集划分方式的代码:

def chooseBestFeatureToSplit(dataSet): #计算出该数据集的最好的划分数据集的特征 numFeatures=len(dataSet[0])-1 #数据的最后一列为特征 baseEntropy=calcShannonEnt(dataSet) bestInfoGain=0.0;bestFeature=-1 for i in range(numFeatures): featList=[example[i] for example in dataSet] #创建数据集中的分类标签列表 uniqueVals=set(featList) #这里的set是一个无序不重复的集合 newEntropy=0.0 for value in uniqueVals: subDataSet=splitDataSet(dataSet,i,value) #用这个value值进行划分的数据集 prob=len(subDataSet)/float(len(dataSet)) #返回这个在所有中的比例 newEntropy+=prob*calcShannonEnt(subDataSet) infoGain=baseEntropy-newEntropy #这几行代码是在计算信息增益 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[:] myTree[bestFeatLabel][value]=createTree(splitDataSet\ (dataSet,bestFeat,value),subLabels) return myTree

下面是一个使用文本注解绘制树节点:

import matplotlib.pyplot as plt decisionNode=dict(boxstyle="sawtooth",fc="0.8") leafNode=dict(boxstyle="round4",fc="0.8") arrow_args=dict(arrowstyle="<-") def plotNode(nodeTxt,conterPt,parentPt,nodeType): createPlot.ax1.annotate(nodeTxt,xy=parentPt,\ xycoords='axes fraction',\ xytext=conterPt,textcoords='axes fraction',\ va="center",ha="center",bbox=nodeType,arrowprops=arrow_args) def createPlot(): fig=plt.figure(1,facecolor='white') fig.clf() createPlot.ax1=plt.subplot(111,frameon=False) plotNode(U'a',(0.5,0.1),(0.1,0.5),decisionNode) plotNode(U'a',(0.8,0.1),(0.3,0.8),leafNode) plt.show()产生的效果如下;

转载请注明原文地址: https://www.6miu.com/read-56148.html

最新回复(0)