1.决策树的构造
首先我们讨论数学上如何使用信息论划分数据集,然后编写代码将理论应用到具体的数据集上,最后编写代码构建决策树。
创建分支的伪代码函数createBranch()如下所示:
检测数据集中的每个子项是否属于同一个分类:
if so return 类标签;
else
寻找划分数据集的最好特征
划分数据集
创建分支节点
for每个划分的子集
调用函数createBranch并增加返回结果到分支节点中
return 分支节点
1.1信息增益
在划分数据集之前之后信息发生的变化成为信息增益,知道如何计算信息增益,我们就可以计算每个特征值划分数据集获得的信息增益,获得信息增益最高的特征就是最好的选择。
信息熵公式
from math import log
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
shannonEnt=0.0
for key in labelCounts:
prob=float(labelCounts[key])/numEntries
shannonEnt-=prob*log(prob,2) #以2为底求对数
return shannonEnt
1.2划分数据集
def splitDataSet(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
def chooseBestFeatureToSplit(dataSet): #选择最后的数据集划分方式
numFeatures=len(dataSet[0])-1
baseEntropy=calcShannonEnt(dataSet)
bestInfoGain=0.0;bestFeature=-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
1.3递归构建决策树
import operator
def majorityCnt(classList):
classCount={}
for vote in classList:
if vote not in classCount.keys():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): #类别完全相同则停止继续划分
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:
subLables=labels[:]
myTree[bestFeatLabel][value]=createTree(splitDataSet(dataSet,bestFeat,value),subLables)
return myTree