900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 自己尝试使用简单数据集实现决策树 代码——《机器学习实战》

自己尝试使用简单数据集实现决策树 代码——《机器学习实战》

时间:2021-07-23 10:31:25

相关推荐

自己尝试使用简单数据集实现决策树 代码——《机器学习实战》

记录学习过程,每天学会一点点,早日玩转机器学习......(手动呵呵微笑)。

一.核心代码

1.数据集部分

上图为所给的海洋生物数据,则以1代表可以付出水面、有脚蹼;0代表无法浮出水面、无脚蹼;yes为属于鱼类、no为不属于鱼类

则创建数据集的代码可以表示为:

from math import log"""加载得到简单的鉴定鱼的数据集"""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

实例化测试一下结果:

myData,labels = createDataSet()print(myData)

打印为:

2.计算香农熵的部分

前面几篇博客已经讲过香农熵的计算公式,下面用代码实现一下计算过程,其实无非就是用代码实现一下计算公式,仔细看就能看得懂,相关部分我也做了注释。记住,每一个键值都是记录当前类别在数据集中出现的次数,那一个if语句的意思就是:在遍历的过程中,如果这个键值不存在,就从这一步开始扩展它,记下来,如果存在,则把计数的参数更新一下,即做加一处理,留作下面计算概率。后面就接着计算每一个类别出现的概率,并使用这个概率去计算香农熵:

"""计算香农熵"""def calShannonEnt(dataSet):numEntries = len(dataSet)#长度labelCounts = {}#为所有可能类别创建字典,它的键值是最后一列的数值,如果当前键值不存在,则扩展字典并将当前键值加入字典。#!!!每一个键值都是记录当前类别在数据集中出现的次数for featVec in dataSet:currentLabel = featVec[-1]if currentLabel not in labelCounts.keys():labelCounts[currentLabel] = 0labelCounts[currentLabel] += 1shannonEnt = 0.0for key in labelCounts:#使用所有类别标签的发生频率计算类别出现的概率prob = float(labelCounts[key])/numEntries#用这个概率结合香农熵公式来计算香农熵shannonEnt -= prob*log(prob,2)return shannonEnt

可以用该方法来计算一下上面数据集的香农熵:

输出香农熵:

3.划分数据集

分类算法不仅要测量信息熵,还需要划分数据集,度量花费数据集的熵,以便判断当前是否正确划分了数据集。将对每个特征划分数据集的结果计算一次信息熵,然后判断按照哪个特征进行划分数据集是最好的划分方式。

在函数的开始声明一个新列表对象,因为该函数代码在同一数据及上被调用多次,为了不修改原始数据集,应创建一个新的列表对象。

数据集这个列表中的各个元素也是列表,我们要遍历数据集中的每个元素,一旦发现符合条件的值,就将其添加到新创建的列表中。简单理解为:当我们按照某个特征划分数据集时,就需要将所有符合要求的元素抽取出来。代码中使用了extend()和append()方法,两者结果大有不同:

append()方法:

extend()方法:

"""3.划分数据集的部分"""def splitDataSet(dataSet,axis,value):#在这三个参数中,首先dataSet是待划分的数据集、axis是划分数据集的特征、value是特征的返回值retDataSet = []#创建新的list对象for featVec in dataSet:if featVec[axis] == value:reducedFeatVec = featVec[:axis]reducedFeatVec.extend(featVec[axis+1:])retDataSet.append(reducedFeatVec)return retDataSet

测试一下这个划分的方法:

#(myData,0,1)中,myData是要划分的数据集,0是第一次划分数据集,要找的是第一列为1的数据列的后两个值,也可以从上面的表里面看出是啥#print(splitDataSet(myData,0,1))#(myData,0,0)中,myData是要划分的数据集,要找的是第一列为0的数据列的后面两个值#print(splitDataSet(myData,0,0))

输出划分结果为:

4.选择最好的划分方式来划分数据集

计算出条件熵,然后求出信息增益,并找到最大的信息增益,最大的信息增益就是找到最好的划分数据集的特征

第一个for循环用于循环遍历数据集中的所有特征;

使用列表推导来创建新的列表,将数据集中所有可能存在的值写在新的列表之中;

使用Python语言原生的集合(set)数据类型,集合数据类型与列表类型相似,

不同之处在于集合数据类型中的每个值都互不相同,从列表中创建集合是Python语言得到列表

中唯一元素值得最快方式;

遍历当前特征中的所有唯一属性值,对每个特征划分一次数据集,然后计算数据集中的新香农熵值,并对所有唯一特征值得到的熵求和。最后比较所有特征中的信息增益,返回最好特征划分的索引值。

"""4.选择最好的划分方式来划分数据集:计算出条件熵,然后求出信息增益,并找到最大的信息增益,最大的信息增益就是找到最好的划分数据集的特征"""def chooseBestFeatureToSplit(dataSet):numFeatures = len(dataSet[0]) - 1baseEntropy = calcShannonEnt(dataSet)#计算出原始的香农熵bestInfoGain = 0.0;bestFeature =-1for i in range(numFeatures):#创建唯一的分类标签列表featList = [example[i] for example in dataSet]#使用Python语言原生的集合(set)数据类型,集合数据类型与列表类型相似,#不同之处在于集合数据类型中的每个值都互不相同,从列表中创建集合是Python语言得到列表# 中唯一元素值得最快方式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 - newEntropyprint("第%d个特征的信息增益为%.3f"%(i,infoGain))#计算最好的信息增益if(infoGain > bestInfoGain):bestInfoGain = infoGain#找出最好的划分数据集的特征bestFeature = ireturn bestFeature

测试一下:

mydata,labels = createDataSet()print(mydata)print("最优特征索引值:"+str(chooseBestFeatureToSplit(mydata)))

输出最好的划分方式为以特征0划分:

运行结果告诉我们,第0个特征是最好的用于划分数据集的特征。

5.统计classList中出现此处最多的元素(类标签)

该函数使用分类名称的列表,创建键值为classList中唯一值得数据字典,字典对象存储了classList中每一个类标签出现的频率,最后利用Operator操作键值排序字典,并返回出现次数最多的分类名称。

"""5.统计classList中出现此处最多的元素(类标签)"""def majorityCnt(classList):classCount = {}#统计classLisfor vote in classList:if vote not in classCount.keys():classCount[vote] = 0classCount[vote] += 1sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)return sortedClassCount[0][0]

6.建树

"""6.开始建树"""def createTree(dataSet,labels,featLabels):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]#最优特征的标签featLabels.append(bestFeatLabel)myTree = {bestFeatLabel:{}}del(labels[bestFeat])#删除已经使用特征标签featValues = [example[bestFeat] for example in dataSet]#得到训练集中所有最优特征的属性值uniqueVals = set(featValues)#去掉重复的属性值for value in uniqueVals:#遍历特征,创建决策树。myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet,bestFeat,value),labels,featLabels)return myTreeif __name__ == '__main__':dataSet,labels = createDataSet()featLabels = []myTree = createTree(dataSet,labels,featLabels)print(myTree)

运行结果:

二.决策树的可视化

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。