决策树模型
分类决策树模型是一种描述对实例进行分类的树形结构,由节点和有向边构成。其中节点包括内部节点和叶节点,内部节点表示一个特征,而叶节点表示一个分类。比如下图:
从根节点开始,对实例的某一特征进行测试,根据测试结果,将实例分配到下一节点,迭代这一过程,知道叶子节点,该节点表示的类标签就是该对象的实例。
构造决策树
对于给定的训练集:我们每次选择一个特征属性将数据集分为几个子集,每个子集表示该特征的一个子树节点,直到数据集被完全分类或者达到我们预先设定的阈值就停止构造决策树。在构造决策树的过程中,关键的一步就是在每一次构造树的时候,该如何选择特征属性或者该选择哪个特征属性进行分类。
信息增益:
有如下数据:
该数据集中有四个特征属性:年龄,工作,房子,信贷等,我们在构造决策树时,每次选择特征属性时该选择哪一个?这时就涉及到一个概念,信息增益,而信息增益和熵有关。
熵:表示随机变量不确定性的度量,设X是一个去有限个值的离散随机变量,
其概率分布为:,
则随机变量X的熵定义为:
设有随机变量(X,Y),其联合概率分布为:
条件熵H(Y|X)表示在已知随机变量X的情况下随机变量Y的不确定性,表示为
则信息增益为,
根据该公式,我们每次选择信息增益最大的特征属性进行决策树的构造。
上图中的数据集我们在选择特征属性时的步骤为:
最后选择信息增益最大的特征为最优特征进行分类。
代码
下面是构造决策树以及用决策树进行决策的代码段。
import math
import numpy as np
import operator
def loadDataSet(filename):
fr=open(filename)
dataSet=[]
for line in fr.readlines():
dataSet.append(line.strip().split('\t'))
return dataSet
#求香农shang
def xiangNongShang(dataSet):
classLabels=[x[-1] for x in dataSet]
m=len(classLabels)
classCount={}
info=0.0
for i in range(m):
if classLabels[i] not in classCount:
classCount[classLabels[i]]=0
classCount[classLabels[i]]+=1
for i in classCount:
info-=float(classCount[i])/m*math.log(float(classCount[i])/m,2)
return info
#求第i个特征,属性值为value的数据子集
def splitt(dataSet,i,value):
returnMat=[]
for data in dataSet:
if data[i]==value:
inarr=[]
inarr[:i]=data[:i]
inarr.extend(data[i+1:])
returnMat.append(inarr)
return returnMat
#求最佳分类特征
def bestF(dataSet):
baseInfo=xiangNongShang(dataSet)
bestInfo=0.0
bestFeature=-1
m=np.shape(dataSet)[1]-1
for i in range(m):
inarr=[x[i] for x in dataSet]
inarrSet=set(inarr)
newInfo=0.0
for j in inarrSet:
returnMat=splitt(dataSet, i, j)
n=len(returnMat)
newInfo+=float(n)/len(dataSet)*xiangNongShang(returnMat)
if baseInfo-newInfo>bestInfo:
bestInfo=baseInfo-newInfo
bestFeature=i
return bestFeature
#如果没有特征可选,则选择数据集中的多数类作为该数据集的类别
def maxC(classList):
classCount={}
for c in classList:
if c not in classCount:
classCount[c]=0
classCount[c]+=1
return (sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True))[0][0]
#创建决策树
def createTree(dataSet,labels):
classList=[x[-1] for x in dataSet]
if classList.count(classList[0])==len(classList):
return classList[0]
if len(dataSet[0])==1:
return maxC(classList)
bestFeature=bestF(dataSet)
bestLabel=labels[bestFeature]
del (labels[bestFeature])
myTree={bestLabel:{}}
bestValues=set([x[bestFeature] for x in dataSet])
for value in bestValues:
newLabels=labels[:]
myTree[bestLabel][value]=createTree(splitt(dataSet, bestFeature, value), newLabels)
return myTree
#用决策树对输入实例进行决策
def classify(myTree,featLabels,inputx):
first=myTree.keys()[0]
second=myTree[first]
featIndex=featLabels.index(first)
for key in second:
if inputx[featIndex]==key:
if type(second[key]).__name__=='dict':
classLabel=classify(second[key],featLabels,inputx)
else:classLabel=second[key]
return classLabel