决策树算法代码实现及注释(代码来自于机器学习实战)

来源:互联网 发布:高级人体建模软件 编辑:程序博客网 时间:2024/06/16 14:43

决策树算法思想如下:

1.决策树就是一个树形结构,每一个非叶子节点可以在某一个特征属性上的判断,基于不同的判断条件,对数据进行划分为各个分支,每个分支代表这个特征属性在某个之于上的输出,每个叶子节点存放一个标签或者类别。

2.决策树算法利用熵来判断如果选择每次需要划分的特征属性;信息增益=划分前信息熵-按照此属性划分后的信息熵,或信息增益大于0,则说明划分后的不确定性减小了。划分是有效的。而信息增益最大的对应特征属性,即可作为此次划分的特征属性.

3.递归实现熵的计算和判断。从而完成整个决策树的划分。


代码实现如下:

#! /usr/bin/python#coding=utf-8from math import logimport operator#假设决策树应用为海洋动物是否为鱼类的分类。def  createDataSet():dataSet = [[1,1,'yes'],[1,1,'yes'],[1,0,'no'],[0,1,'no'],[0,1,'no']] #每一行的每一列含义依次为(不浮出水面是否可以生存的值,是否有脚蹼的值,属于鱼类的值)labels = ['no surfacing','flippers']#两个特征项(不能浮出水面是否可以生存,脚蹼)return dataSet,labels'''dataSet:样本集合'''def calcShannonEnt(dataSet):numEntries = len(dataSet) #获取整个数据集的行数,即数据的个数labelCounts = {} #标签计数器,初始化为空字典for featVec in dataSet:#对于数据集的每一行,即每一个数据特征项currentLabel = featVec[-1] #最后一列为当前标签(即是否是鱼类)if currentLabel not in labelCounts.keys(): #如果当前标签第一次出现labelCounts[currentLabel]=0#创建一个当前标签对应的字典值labelCounts[currentLabel] +=1#当前标签每出现一次,则当前标签对应的计数器+1shannonEnt = 0.0 #初始熵为0for key in labelCounts:#对于标签计数器的每个标签prob = float(labelCounts[key]) / numEntries #出现的概率=当前的标签计数/总的数据个数shannonEnt -= prob*log(prob,2)#根据熵的计算公式,当前熵=负的(所有的概率*log概率)之和,这里的log以2为底return shannonEnt #返回信息熵'''dataSet:样本集合axis:特征项value: 特征值'''def splitDataSet(dataSet, axis, value):retDataSet = []#初始化返回的子样本集合for featVec in dataSet:#对于数据集的每一行,即每一个数据特征项if featVec[axis] == value: #如果指定的特征项数值=给定的数值reducedFeatVec = featVec[:] #复制当前数据点的特征值reducedFeatVec.remove(reducedFeatVec[axis]) # 去除指定的特征项retDataSet.append(reducedFeatVec) #添加到返回的样本集合中去return retDataSet #返回的子样本集合'''dataSet:样本集合'''def chooseBestFeatureToSplit(dataSet):numFeatures = len(dataSet[0]) - 1#获取样本的特征项个数baseEntropy = calcShannonEnt(dataSet)#计算总的样本集合的熵bestInfoGain = 0.0; #初始化最大信息增益值为0.0bestFeature = -1#初始化最优划分特征为不划分for i in range(numFeatures):#对于每个特征项featList = [example[i] for example in dataSet]#获取每个样本在该特征项上面的值uniqueVals = set(featList)#去重newEntropy = 0.0#for value in uniqueVals: #对于该特征项上每个不同的值subDataSet = splitDataSet(dataSet,i,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] = 0classCount[vote] += 1sortedClassCount = sorted(classCount.iteritems(),key = operator.itemgetter(1),reverse=True)return sortedClassCount[0][0]'''dataSet:样本集合labels: 特征项'''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])#删除list中此特征项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#返回决策树,决策树的key为最优划分特征,值为key为特征值,value为对应的子样本决策树。
myDat,labels=createDataSet()myTree = createTree(myDat,labels)print myTree




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