【十八】机器学习之路——决策树Python实现(4)

[本文内容参考Peter Harrington《机器学习实战》]
最近工作有点忙,感觉自己有点懈怠了,要坚持!

  前面几篇博客介绍了决策树的理论知识机器学习之路——决策树(1),机器学习之路——决策树算法(2),机器学习之路——决策树剪枝(3) ,学习理论的目的最终为了解决实际问题,今天来一起看看如何用Python来实现决策树算法。话不多说,直接上代码。

  首先,实现计算信息增益的部分代码。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
from math import log
def calcShannonEnt(dataSet):
    numEntries = len(dataSet)#计算数据集总个数,以便计算权重
    labelCounts = {}
    for featVec in dataSet: #将dataset中类别及出现的次数用字典来保存
        currentLabel = featVec[-1]#默认数据集中最后一列为Label类别标签
        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)
    return shannonEnt

  然后,完成数据集划分部分代码。

def splitDataSet(dataSet,axis,value):
retDataSet = []
for featVec in dataSet:#for in函数参考文末链接
    if featVec[axis] == value:
        reducedFeatVec = featVec[:axis]
        reducedFeatVec.extend(featVec[axis+1:])
        retDataSet.append(reduceFeatVec)
        #append()extend()函数参考文末链接
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)#每个属性的取值
        for value in uniqueVals:#遍历完所有取值后得到利用该属性划分数据集的信息增益
            subDataSet = splitDataSet(dataSet,i,value)
            pro = len(subDataSet)/float(len(dataSet))
            newEntroy += prob * calcShannonEnt(subDataSet)
        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]


  最后终于到最重要的部分了,创建树的代码,在创建树的代码前,先看这段数据集,代码里我们利用该数据集进行测试。

不浮出水面是否可以生存(no surfacing)是否有脚蹼(flippers)属于鱼类
是(1)是(1)yes
是(1)是(1)yes
是(1)否(0)no
否(0)是(1)no
否(0)是(1)no

在Python里我们用下面一段代码来生成该数据:

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


  最后,生成决策树的代码如下所示:

def createTree(dataSet,labels):
    #将数据集最后一列赋值给classList
    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)
    #选择最优划分属性的列数i
    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[:]       #copy all of labels, so trees don't mess up existing labels
        myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels)
    return myTree 

最终运行代码输出的结果:

{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}

该决策树是用字典保存,看起来比较费劲,下一篇博客讲一下如何用matplot来显示该决策树。

代码中涉及到的部分Python函数,参考如下链接学习。
Python中for in函数
Python中extend和append区别

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值