本文主要是介绍Quo的随手笔记之决策树,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
决策树算法
- 算法的介绍
- 决策树思想阐述
算法的介绍
决策树是一种监督学习算法,之前大火的小爱同学猜人名就是用这样的算法实现,通过不停的询问,即不停的分类,最终到无法进行分类的时候就锁定了结果。现实中有诸多应用,比如植物、动物的分类,本博客中的决策树分类方法叫做ID3,除此之外主流决策树算法还有CART和C4.5等
参考文献:《Machine Learning in Action》,知乎百科
决策树思想阐述
用官方的话来说,决策树是一个预测模型;他代表的是对象属性与对象值之间的一种映射关系。树中每个节点表示某个对象,而每个分叉路径则代表的某个可能的属性值,而每个叶结点则对应从根节点到该叶节点所经历的路径所表示的对象的值。
要想了解决策树的意义,首先要了解什么是熵,
香农熵,
对于任意一个随机变量 X,它的熵定义如下:
变量的不确定性越大,熵也就越大,把它搞清楚所需要的信息量也就越大。
具体定义请参考:https://blog.csdn.net/theonegis/article/details/79890407
目标:
为了分辨一种物种是否为鱼类,实验人员收集了一组数据,希望能够从中找出分类的依据,帮忙判断新的物种是否能被认为是鱼类。
数据集如下
鳞片 | 鳍 | 是否是鱼类 |
---|---|---|
有 | 有 | 是 |
有 | 有 | 是 |
无 | 有 | 否 |
有 | 无 | 否 |
无 | 有 | 否 |
1计算熵,代码如下
// By Quo &Peter Harrington
from math import log
import operator
#计算熵
def calculateEntropy(dataSet) :numEntries=len(dataSet)labelCounts={}#对于结构性数据进行分类的数目统计for featVec in dataSet :#对于每一行的最后一列数据进行类别的统计currentLabel=featVec[-1]if currentLabel not in labelCounts:labelCounts[currentLabel]=0labelCounts[currentLabel]+=1Entropy=0for key in labelCounts:#本选项被选择的概率prob=float(labelCounts[key])/numEntries#对于每一项不重复的key进行熵的求和(因为分数进行对数运算之后是负数,所以就是求减)Entropy= Entropy-prob*log(prob,2)return Entropydef createDateSet():#构建初始数据dataSet=[[1,1,'yes'],[1,1,'yes'],[1,0,'no'],[0,1,'no'],[0,1,'no']]labels =['no surfacing','flippers']return dataSet,labels
2.选取最优熵
因为不同维度的分类的熵是不一样的,所以我们需要选出熵最大的进行优先筛选,代码如下
#选择最好的分类方式
def chooseBestFeature2Split(dataSet):numFeatures=len(dataSet[0])-1baseEntropy=calculateEntropy(dataSet)bestInfoGain=0bestFeature=0for i in range(numFeatures):#分别对每一列进行分类操作之后求信息期望值,featList=[example[i] for example in dataSet]#取得第i列的数据变成一个listuniqueValues=set(featList)#去重 得到值域newEntropy=0for value in uniqueValues:subdataSet=splitDataSet(dataSet,i,value)prob=len(subdataSet)/float(len(dataSet))newEntropy=newEntropy+prob*calculateEntropy(subdataSet)#以上为计算信息期望值的公式,即每一个选项被选中的概率乘以熵的总和infoGain=baseEntropy-newEntropyif(infoGain >bestInfoGain):baseEntropy=infoGainbestFeature=i#以上为判断大小,信息期望值越大,就代表是更好的数据集的划分方式return bestFeature#返回的为列的标号
- 对单条件进行分类
即得到最优解的标号之后,拿出此列作为分类依据并在数据集中去除此列,以便于下次分类
#用以去除每一行中特定列符合要求的值
def splitDataSet(dataSet,axis,value):result=[]for featVec in dataSet:if featVec[axis] ==value:reducedFeatVec=featVec[:axis]reducedFeatVec.extend(featVec[axis+1:])result.append(reducedFeatVec)return result
- 当分类到最后一个分支之后,还不能够将数据进行统一的分类,则返回剩下数据的频率比表示其可能性。
#用来对List中元素出现的频率进行排序
def majorityCnt(classList):classCount={}for 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]
- 构造树,核心思想为,首先计算传入矩阵的不同维度的熵,取熵最大的一列数据并进行树结构的构造,根据取值来决定分支个数,然后去除本列数据,将剩余的矩阵进行递归处理,直至得到一个不可再分的矩阵并返回其树结构。
python代码如下:
// By Quo&Peter Harrington
from math import log
import operator# 决策树代码实例
def createTree(dataSet,labels):classList=[example[-1] for example in dataSet]#取最后一列为Listif classList.count(classList[0])==len(classList):#如果第一行在数据中一直反复出现(即没有进行再次分类的必要了),则返回第一行return classList[0]if len(dataSet[0])==1:#用来标识遍历结束时返回最多出现的类别return majorityCnt(classList)bestFeature=chooseBestFeature2Split(dataSet)bestFeatLabel=labels[bestFeature]# 获取最高信息期望值的分类位置,和对应的标签myTree={bestFeatLabel:{}}#得到标签之后构建树del(labels[bestFeature])#删除已使用的标签featValues=[example[bestFeature] for example in dataSet]#提出最合适的分类列uniqueVals=set(featValues)#去重,提取值域for value in uniqueVals:subLabels=labels[:]myTree[bestFeatLabel][value]=createTree(splitDataSet(dataSet,bestFeature,value),subLabels)#对于每一个值域中的值,树结构中新建结构# 即对于和value匹配的数据,删除已用作分类的bestFeatLabel之后的结构return myTree
myData,label=createDateSet()
print(createTree(myData,label))
这篇关于Quo的随手笔记之决策树的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!