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

来源:互联网 发布:哈尔滨飞扬软件 编辑:程序博客网 时间:2024/06/05 17:15

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

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

from math import logdef 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.0for key in labelCounts:                                             prob=float(labelCounts[key])/numEntries                     #每个类别除以总数,是该类别的概率,也就是上面式子中的pkshannonEnt-=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=-1for i in range(numFeatures):featList=[example[i] for example in dataSet]         #创建数据集中的分类标签列表uniqueVals=set(featList)                             #这里的set是一个无序不重复的集合newEntropy=0.0for 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=infoGainbestFeature=ireturn 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()
产生的效果如下;



阅读全文
0 0
原创粉丝点击