机器学习实战学习记录--决策树

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mansir123/article/details/79398136

决策树中算法采用的ID3.划分数据集基于 特征。其中采用分类依据为信息论中的信息增益和信息熵(香农熵)。
机器学习中香农熵计算公式为:这里写图片描述
其中xi表示分类,p(xi)表示xi分类的概率。

首先,创建数据集及计算香农熵

from math import log
def calcShannonEnt(dataset): #香农熵计算函数
    numEnts=len(dataset)
    labelCounts={}  #记录标签及对应的个数
    for featVec in dataset:
        currentLabel=featVec[-1] #取出数组中最后一项‘n’或者‘y’的作为标签
        if currentLabel not in labelCounts.keys(): #如果当前标签在labelCounts中无记录,则添加
            labelCounts[currentLabel]=0
        labelCounts[currentLabel]+=1 #标签对应数量计数
    shannonEnt=0.0
    print(labelCounts)#输出标签及对应个数
    for key in labelCounts:
        prob=float(labelCounts[key])/numEnts #同标签出现的概率,即p(xi)
        shannonEnt-=prob*log(prob,2)  #计算香农熵  -p(xi)*log2(p(xi))的加和
    return shannonEnt

def createDataset(): #数据集创建函数
    dataset=[
       [1,1,'y'],
        [1,1,'y'],
        [1,0,'n'],
        [0,1,'n'],
        [0,1,'n']
    ]
    labels=["no serfacing","flippers"]
    return dataset,labels
myData,labels=createDataset()
myData[0][-1]='maybe'#修改数据集中第一个的标签为 maybe
print(myData)

print(calcShannonEnt(myData))

输出结果为

[[1, 1, 'maybe'], [1, 1, 'y'], [1, 0, 'n'], [0, 1, 'n'], [0, 1, 'n']]
{'maybe': 1, 'y': 1, 'n': 3}
1.3709505944546687

得到熵,下一步按照最大信息增益的方法划分数据集。
原理是取各属性进行熵的计算。取最高信息增益的属性为最佳属性。

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] #遍历获取该列所有值
        print("featList:",featList)
        uniqueVals=set(featList) #从列表中创建集合,得到不重复的所有可能取值 
        print("uniquevals",uniqueVals)
        newEntropy=0.0
        for value in uniqueVals:
            subDataset=splitDataSet(dataset,i,value)
            print("subDataset:",subDataset)
            prob=len(subDataset)/float(len(dataset))
            newEntropy+=prob*calcShannonEnt(subDataset)

        print("%d 列属性的熵为:"%i,newEntropy)
        infoGain=baseEntropy-newEntropy #计算每一个属性值对应的熵值并求和。结果与原始熵值的差即为信息增益。增益越大说明所占决策权越大  
        print("inforgain:",infoGain)
        if(infoGain>bestInfoGain):
            bestInfoGain=infoGain
            bestFeature=i
    return  bestFeature

print("bestFeature:",chooseBestFeatureToSplit(myData))

输出结果为:

featList: [1, 1, 1, 0, 0]
uniquevals {0, 1}
subDataset: [[1, 'n'], [1, 'n']]
{'n': 2}
subDataset: [[1, 'y'], [1, 'y'], [0, 'n']]
{'y': 2, 'n': 1}
0 列属性的熵为: 0.5509775004326937
inforgain: 0.4199730940219749
featList: [1, 1, 0, 1, 1]
uniquevals {0, 1}
subDataset: [[1, 'n']]
{'n': 1}
subDataset: [[1, 'y'], [1, 'y'], [0, 'n'], [0, 'n']]
{'y': 2, 'n': 2}
1 列属性的熵为: 0.8
inforgain: 0.17095059445466854
bestFeature: 0

下面构建决策树

代码如下:

def majorityCnt(classList): #返回出现次数最多的分类名称
    classCount={}
    for vote in classList:
        if vote not in classCount.keys():classCount[vote]=0 #创建分类(即字典)并计数
        classCount[vote]+=1
    sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) #排序,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:
        subLabels=labels[:]
        myTree[bestFeatLabel][value]=createTree(splitDataSet(dataSet,bestFeat,value),subLabels) #递归
    return  myTree

print("createtree:",createTree(myData,labels))

最终输出结果:

createtree: {'no serfacing': {0: 'n', 1: {'flippers': {0: 'n', 1: 'y'}}}}

结果为多层嵌套的叶节点

猜你喜欢

转载自blog.csdn.net/mansir123/article/details/79398136
今日推荐