根据某种海洋动物在不浮出水面的情况下是否可以生存、是否有脚蹼两种特征将其分为鱼类和非鱼类。
no surface | flipper | ffish |
1 | 1 | yes |
1 | 1 | yes |
1 | 0 | no |
0 | 1 | no |
0 | 0 | no |
输入原始数据集
计算原始数据集的Shannon熵
输出数据集的熵
def creatShannonEnt(dataset):
numEntries=len(dataset)#numEntries表示数据集的大小,在这里是5
labelCount={}#创建标签
for feature in dataset:
currentLabel=feature[-1]#features:[1,1,'yes'] feature[-1]表示最后一列的类别标签
if currentLabel not in labelCount.keys():#计算类别的个数
labelCount[currentLabel]=0
labelCount[currentLabel]+=1
shannonEnt=0.0
for key in labelCount:
prob=float(labelCount[key])/numEntries
shannonEnt-=prob*log(prob,2)#0.6*log2(0.6)+0.4*log2(0.4)
return shannonEnt
创建数据集
def createDataSet():
dataset=[[1,1,'yes'],[1,1,'yes'],[1,0,'no'],[0,1,'no'],[0,0,'no']]
labels=['no surfacing','flippers']#特征标签
return dataset,labels
输入数据集,数据集中某一特征的可能取值(0、1)
得到改特征值下的子数据集
def splitDataSet(dataset,axis,value):
retDataSet=[]
for feature in dataset:
if feature[axis]==value:
reduceFeature=feature[:axis]
reduceFeature.extend(feature[axis+1:])
retDataSet.append(reduceFeature)
print(retDataSet)
return retDataSet
输入数据集
选择最优特征,得到最优子数据集,即得到特征在决策树中的先后顺序
输出最优特征在数据集中的列索引
def chooseBestFeatureToSplit(dataset):
numFeatures=len(dataset[0])-1#dataset[0]=[1,1,'yes'],得到特征标签的个数,此处为2
baseEntropy=creatShannonEnt(dataset)#计算原始数据集的熵
bestInfoGain=0.0
bestFeature=-1
for i in range(numFeatures):#i表示该函数传入的数据集中每个特征
featList=[example[i] for example in dataset]#得到i在数据集中的所有取值
uniqueVals=set(featList)
newEntropy=0.0
for value in uniqueVals:
subDataset=splitDataSet(dataset,i,value)#得到四个子数据集
prob=len(subDataset)/float(len(dataset))
newEntropy+=prob*creatShannonEnt(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.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):#判断传入的dataset中是否只有一种类别,是,返回该类别
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[:]#取出在该最好特征的value取值下的子数据集和子标签列表
myTree[bestFeatLabel[value]=createTree(splitDataSet(datasett,bestFeat,value),subLabels) #递归创建子树
return myTree
测试数据
def classify(inputTree,featLabels,testVec):
firstStr=inputTree.key()[0]
secondDict=inputTree[firstStr]
featIndex=featLabels.index(firstStr)
for key in secondDict.keys():
if testVec[featIndex]==key:
if type(secondDict[key])._name_=='dict':
classLabel=classify(secondDict[key],featLabels,testVec)
else:
classLabel=secondDict[key]
return classLabel