决策树02——决策树的构建
来源:互联网 发布:淘宝店主进货渠道 编辑:程序博客网 时间:2024/05/29 15:58
《 machine learning in action》之决策树
计算给定数据集的香农熵
创建文件trees.py
# -*- coding=utf-8 -*-#计算给定数据集的熵from math import logdef calcShannonEnt(dataSet): numEntries = len(dataSet) labelCounts = {} #实例总数 for featVec in dataSet: #为所有可能分类创建字典 currentLabel = featVec[-1] #将最后一列,即分类结果存入currentLabel if currentLabel not in labelCounts.keys(): #若分类结果已经在labelCounts这个字典中 labelCounts[currentLabel] = 0 #若当前label不存在,则扩展字典,加入此键值 labelCounts[currentLabel] += 1 #字典中的每个键值都记录了当前类别的数量 #print 'labelCounts,currentLabel:',labelCounts,currentLabel #print 'labelCounts.keys()',labelCounts.keys() #print 'labelCounts.values()',labelCounts.values() shannonEnt = 0.0 for key in labelCounts: prob = float(labelCounts[key])/numEntries shannonEnt -= prob*log(prob,2) #求以2为底的对数,其和即为熵 #print 'labelCounts[key]',labelCounts[key] return shannonEnt
创建或导入dataSet
#鱼类数据集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
在命令提示符下输入:
In[9]: import treesIn[10]: myDat,labels = trees.createDataSet()In[11]: myDatOut[11]: [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]In[12]: labelsOut[12]: ['no surfacing', 'flippers']In[13]: trees.calcShannonEnt(myDat)#混合的数据越多,熵越高,测试:In[18]: myDat[0][-1] = 'maybe'In[19]: myDatOut[19]: [[1, 1, 'maybe'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]In[20]: trees.calcShannonEnt(myDat)Out[20]: 1.3709505944546687
划分数据集
取出符合要求某个特征属性值的样本,并将其此特征从数据集中去除。
#按照给定特征划分数据集def splitDataSet(dataSet,axis,value): #待划分的数据集,划分数据集的特征(第几列),需要返回的特征的值,(axis-->a,value-->v) #为了不修改原始数据集,创建新的list对象 retDataSet = [] for featVec in dataSet: #将符合特征的数据抽取出来 if featVec[axis] == value: #Python中的数据.即featVec中的数据从第0列开始,[0,1,2,3,4,5,……] reducedFeatVec = featVec[:axis] #[:axis]表示前axis行,若axis为3,则表示取festVec的前3列,即第[0,1,2]列 reducedFeatVec.extend(featVec[axis+1:]) #[axis+1:] 表示跳过axis+1列,从下一列数据取到最后一列的数据,即跳过第[3]列,从第[4]列到最后一列 retDataSet.append(reducedFeatVec) return retDataSet
在Python命令行中输入:
In[16]: reload(trees)Out[16]: <module 'trees' from '/home/vickyleexy/PycharmProjects/Classification of contact lenses/trees.py'>In[17]: myDat,labels = trees.createDataSet()In[18]: myDatOut[18]: [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]In[19]: trees.splitDataSet(myDat,0,1) #抽取出数据集中第0列中数据值为1的样本,并将此列剔除,组成新的样本集Out[19]: [[1, 'yes'], [1, 'yes'], [0, 'no']]In[20]: trees.splitDataSet(myDat,0,0) #抽取出数据集中第0列中数据值为0的样本,并将此列剔除,组成新的样本集Out[20]: [[1, 'no'], [1, 'no']]In[21]: trees.splitDataSet(myDat,1,0) #抽取出数据集中第1列中数据值为0的样本,并将此列剔除,组成新的样本集Out[21]: [[1, 'no']]
选取最好的数据集划分方式
即选取取出信息增益最大的特征。信息增益是熵减少或者说信息无序度的减少,信息增益越大,信息无序度减少越大,信息的可确定性越强。
#选择最好的数据集划分数据,即计算每种特征信息熵 Gain(D,a)def chooseBestFeatureToSplit(dataSet): numFeatures = len(dataSet[0]) - 1 #可选特征的个数 baseEntropy = calcShannonEnt(dataSet) # 计算总体信息熵Ent(D) bestInfoGain = 0.0; #初始化最好的信息增益 bestFeature = -1; #初始化选取的最好的特征 #创建唯一的分类标签列表 for i in range(numFeatures): #遍历各个特征 featList = [example[i] for example in dataSet] #将第i列特征的值选取出来,并存入featList uniqueVals = set(featList) #将featList存为集合的格式,即去除featList中重复的元素,因此uniqueVals中为每个特征的中不同的属性 newEntropy = 0.0 #计算每种划分方式的信息熵 for value in uniqueVals: #遍历每个特征中的各个属性 subDataSet = splitDataSet(dataSet,i,value) #选取符合条件的特征,并将此特征从样本中去除,以便进行下面的进一步计算 prob = len(subDataSet)/float(len(dataSet)) #符合此特征中此属性的个数占总体样本的比例,即|D^v|/|D| newEntropy += prob * calcShannonEnt(subDataSet) #计算各个特征中每个属性的加权信息熵的和 infoGain = baseEntropy - newEntropy #计算信息增益,即Gain(D,a) #计算最好额信息增益 if (infoGain > bestInfoGain): bestInfoGain = infoGain bestFeature = i print '最好的特征,最好的信息增益:',bestFeature,bestInfoGain return bestFeature
在Python命令行下输入以下代码进行测试:
In[9]: reload(trees)Out[9]: <module 'trees' from '/home/vickyleexy/PycharmProjects/Classification of contact lenses/trees.py'>In[10]: myDat,labels = trees.createDataSet()In[11]: myDatOut[11]: [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]In[12]: trees.chooseBestFeatureToSplit(myDat)最好的特征,最好的信息增益: 0 , 0.419973094022Out[12]: 0
递归构建决策树
递归结束的条件:
- 程序遍历完所有划分数据集的属性
- 每个分支下的所有实例都具有相同的分类
若已经处理了所有的属性,但类标签依然不是唯一的,此时采用多数表决的方法决定叶子节点的分类。
在trees.py文件的顶部添加operator库
import operator
统计剩余样本中属于哪一类别最多的数量最多:
def majorityCnt(classList): #classList类别列表 classCount = {} #新建立一个字典 for vote in classList: #遍历所有的类别 #统计各类别剩余样本的数量 if vote not in classCount.keys(): #如果此类别不在classCount的key中 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): #若classList中第一个类别的数量等于样本的总数量,即样本类别完全相同 return classList[0] #遍历完所有特征时返回出现次数最多的 if len(dataSet[0]) == 1: return majorityCnt(classList) bestFeat = chooseBestFeatureToSplit(dataSet) bestFeatLabel = labels[bestFeat] myTree = {bestFeatLabel:{}} del(labels[bestFeat]) #去掉已经使用的(bestFeat)类标签 #得到最好的特征这一列,包含其所有属性值的列表 featValues = [example[bestFeat] for example in dataSet] uniqueVals = set(featValues) #去掉featValues列表中重复的属性 for value in uniqueVals: #遍历最好的特征中所有的属性 subLabels = labels[:] #复制del(labels[bestFeat])后的结果,并将其存在新列表变量subLabels中 myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet,bestFeat,value),subLabels) return myTree
命令行中输入:
In[66]: reload(trees)Out[66]: <module 'trees' from '/home/vickyleexy/PycharmProjects/Classification of contact lenses/trees.py'>In[67]: myDat,labels = trees.createDataSet()In[68]: myTree = trees.createTree(myDat,labels)最好的特征,最好的信息增益: 0 , 0.419973094022最好的特征,最好的信息增益: 0 , 0.918295834054In[69]: myTreeOut[69]: {'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}
阅读全文
0 0
- 决策树02——决策树的构建
- 决策树——ID3构建决策树
- 决策树01——决策树的原理
- 决策树算法(六)——构建决策树
- 决策树构建算法之—C4.5
- 决策树系列算法总结——决策树
- 决策树算法(二)——构建数据集
- 机器学习——基于基尼指数构建决策树
- 机器学习实战——决策树:树的构建及分类
- 决策树——理论
- 决策树——实践
- MachineLearning——决策树
- 决策树——中文版
- 人工智能算法—决策树
- 人工智能算法—决策树
- 人工智能算法—决策树
- 人工智能算法—决策树
- Machine Learning—决策树
- Android 之自定义 item 的 ListView
- java数组、集合使用及相互转换
- VS2005 开发ArcGIS Add-in时报“ValidateAddInXMLTask任务意外失败错误”解决办法-附Visual Studio 2013 Shell (Isolat)
- CentOS7安装SVN
- Android
- 决策树02——决策树的构建
- linux tcp dump使用方法
- Spark Q&A : Task/Object not serializable 任务不能序列化
- 99 C语言空指针NULL以及void指针
- springMvc最简单配置
- HTTP应用层与TCP/IP传输层的区别
- 异常:Unknown features (Run Configuration[AndroidRunConfigurationType], Facet[android, android-gradle])
- 分布式锁1 Java常用技术方案
- java8之list和map集合转换