美文网首页
机器学习实战-决策树

机器学习实战-决策树

作者: 又双叒叕苟了一天 | 来源:发表于2019-06-01 13:57 被阅读0次

假设有这么一组数据:

不浮出水面是否可以生存 是否有脚蹼 属于鱼类
1
2
3
4
5

特征包含:不浮出水面是否可以生存,是否有脚蹼。标签是属于鱼类。

我们通过构造这样一棵决策树对其进行分类,每个叶子节点代表对一个分类的判断:

decisiontree.png

相比knn,决策树具体考虑了样本的每一个特征。

那么,我们通过对哪些特征先后进行划分来构造这样一棵树呢?

首先,我们将数据集转化成符号表示:

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

dataSet中1表示是,0表示不是,yes表示属于鱼类,no表示不属于鱼类。

labels中分别表示两个特征的名称:不浮出水面是否可以生存、是否有脚蹼。

接着我们计算这个数据集的信息熵:

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)
    return shannonEnt

信息熵定义为:
shannonEnt = -p\log_2 p
p为这个类别的概率。

拿这个例子来说,样本有两类yes和no,yes占样本的2/5,no占样本的3/5。则这个样本的信息熵为:
-\frac25\log_2\frac25-\frac35\log\frac35\approx0.97
我们通过下面的代码测试下结果:

dataSet, labels = createDataSet()
print(calcShannonEnt(dataSet))  # 0.9709505944546686

信息熵代码了数据的规则程度,我们把第一个标签从yes改成maybe,再运行一下代码:

dataSet[0][-1] = 'maybe'
print(calcShannonEnt(dataSet))  # 1.3709505944546687

可以看到,信息熵从0.97上升到了1.37,代表信息熵越高则数据越混乱。

一个好的划分应该是划分过后每个数据集的信息熵之和要比划分前的数据集信息熵小的越多越好的,小的那部分叫做信息增益,即信息增益越大越好。

拿我们这个样本来说,假如通过第一个特征不浮出水面是否可以生存来划分,这个特征具备两个值,我们可以把数据集分成两个,然后计算这两个样本根据所占原先样本比重的信息熵的加权和,和划分之前的样本的信息熵计算信息增益。对于另一个特征也同样进行计算,最后选取信息增益最大的特征作为我们的划分。

写成代码如下:

def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1  # 特征的个数
    baseEntropy = calcShannonEnt(dataSet)  # 计算当前数据集的熵
    bestInfoGain, bestFeature = 0.0, -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
print(chooseBestFeatureToSplit(dataSet))  # 0

结果我们可以看到根据第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=lambda x: x[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]  # str
    # 如果已经没有特征可以划分了,就选择占多数的分类作为这个分类
    if len(dataSet[0]) == 1:
        return majorityCnt(classList)  # str
    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(dataSet, labels))  # {'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}

从结果中我们能够看出{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}},也就是开头那张图上的那棵树。

相关文章

  • python决策树(二叉树、树)的可视化

    问题描述 在我学习机器学习实战-决策树部分,欲可视化决策树结构。最终可视化结果: 解决方案 决策树由嵌套字典组成,...

  • 机器学习实战Py3.x填坑记—决策树

    在输入完程序清单3-5之后运行命令: 遇到问题搜索如下参考:[机器学习&数据挖掘]机器学习实战决策树plotTre...

  • 2018文章集合

    2018年公众号文章集合,过年在家系统学习下。 机器学习实战 该系列讲解了经典机器学习算法的原理(KNN,决策树,...

  • 《机器学习实战》决策树构建学习

    概要记录 Decision Tree基本学习,学习自《机器学习实战》P32 - P42 (基于信息增益的决策树构建...

  • 【机器学习】决策树(构造篇)

    下一篇为:【机器学习】决策树(Matplotlib可视化+项目实战) 最经常使用的机器学习算法k近邻法最大缺点是无...

  • 机器学习实战教程(三):决策树实战篇(a)

    一、前言 上篇文章机器学习实战教程(二):决策树基础篇[https://www.mlxs.top/portal.p...

  • 《机器学习实战》

    有道笔记原文 机器学习实战 Github代码 第一章 机器学习基础 2007年选出的十大数据挖掘算法C4.5决策树...

  • Python pickle模块踩坑

    跟着机器学习实战写代码,决策树这里有一段是保存决策树,使用pickle模块保存,原书是基于2.7的,在3.6上有坑...

  • 机器学习实战-决策树

    1、背景 以上就是之前见过的树状模型,但这里它代表着决策树直观的表达形式。其特殊意义在于,没个叶节点,代表着要划分...

  • 【机器学习实战】决策树

    算法思路 在构造决策树时,第一个需要解决的问题就是,如何确定出哪个特征在划分数据分类是起决定性作用,或者说使用哪个...

网友评论

      本文标题:机器学习实战-决策树

      本文链接:https://www.haomeiwen.com/subject/xizotctx.html