• 《机器学习实战》第三章:决策树(3)测试、存储、实例


    在讲了怎样构建决策树之后,作者本来还讲了如何用 Matplotlib 把决策树给画出来,噼里啪啦又是一堆代码。

    但我自认为学习这部分的意义不大,毕竟这棵树长什么样子是给人看的,计算机不用考虑,能进行构建和分类就可以了。而且如果树很宽很深的话,人眼也看不过来。

    所以就偷个懒,跳过这小节吧。

    这篇博客讲的是决策树的测试、存储,还会展示一个实例。

    ------------------------------------------------------------------------------------------------

    测试决策树

    这里的测试,指的就是建好了树之后,拿一条新的数据进行分类。

    大致过程:从决策书根节点开始,比较待分类数据的改节点特征,并根据特征值,沿着决策树的边进入下一个节点,直到进入叶节点,就能给这条数据分类了。

    [python] view plain copy
    1. def classify(inputTree,featNames,testVec):  
    2.     firstStr = inputTree.keys()[0]  #当前树的根节点的特征名称  
    3.     secondDict = inputTree[firstStr]  #根节点的所有子节点  
    4.     featIndex = featNames.index(firstStr)  #找到根节点特征对应的下标  
    5.     key = testVec[featIndex]  #找出待测数据的特征值  
    6.     valueOfFeat = secondDict[key]  #拿这个特征值在根节点的子节点中查找,看它是不是叶节点  
    7.     if isinstance(valueOfFeat, dict):  #如果不是叶节点  
    8.         classLabel = classify(valueOfFeat, featNames, testVec)  #递归地进入下一层节点  
    9.     else: classLabel = valueOfFeat  #如果是叶节点:确定待测数据的分类  
    10.     return classLabel  

    classify函数接收三个参数:

    (1)inputTree: 事先构建好的决策树。实际类型是一个dict,就像这样子(详情可以看上一篇博客):


    (2)featNames: 特征的名称。按顺序的。

    (3)testVec:一条待测数据的特征向量。

    第7行: 用isInstance方法判断valueOfFeat是不是dict类型,也就是判断要找的这个子节点是不是一棵树。

    例如上面这个例子,我们拿到一条待测数据,首先比较它的'no surfacing'特征值。

    如果是0的话,进入0这个子节点。此时valueOfFeat是'NO',不是dict类型,所以到达了叶节点,于是把它分类成'NO'。

    如果是1的话,进入1这个子节点。此时valueOfFeat是{'flippers': {0: 'NO', 1: 'YES'}}},是dict类型,所以还只是一个内部节点,必须进一步分类。然后就递归地调用classify函数,进入下一层节点...


    我们运行试试看:

    [python] view plain copy
    1. dataSet, feats = createDataSet()  
    2. feats_copy = feats[:]  #由于createTree函数会改变feats,所以先深复制一份feats  
    3. theTree = createTree(dataSet, feats)  
    4. print feats_copy, ' ', theTree  
    5. print classify(theTree, feats_copy, [1,0])  
    6. print classify(theTree, feats_copy, [1,1])  

    结果:


    待测数据 [1,0] 被分类成“NO”,[1,1]被分类成YES。

    ------------------------------------------------------------------------------------------------

    决策树的存储

    我们不希望每次拿新数据进行分类前,都构造一遍决策树。所以得想个办法把它存到硬盘上。

    作者用的是pickle这个模块,用来将对象持久化。

    [python] view plain copy
    1. def storeTree(inputTree, filename):  
    2.     import pickle  
    3.     fw = open(filename, 'w')  
    4.     pickle.dump(inputTree, fw)  
    5.     fw.close()  
    [python] view plain copy
    1. def grabTree(filename):  
    2.     import pickle  
    3.     fr = open(filename)  
    4.     return pickle.load(fr)  

    就是把建好的决策树(dict类型)存进文件,或者拿出来。

    运行一下试试看:

    [python] view plain copy
    1. storeTree(theTree, 'storage.txt')  
    2. print grabTree('storage.txt')  



    ------------------------------------------------------------------------------------------------

    实例:使用决策树预测隐形眼镜类型

    这是一个“隐形眼镜数据集”。完整的数据集(挺小的):

    4个特征,1个标签:

    特征1(age):有3种特征值(young, pre, presbyopic)

    特征2(prescript):有2种特征值(hyper, myope)

    特征3(astigmatic):有2种特征值(yes, no)

    特征4(tearRate):有2种特征值(reduced, normal)

    标签有3种: hard, soft, no lenses


    代码:

    [python] view plain copy
    1. fp = open('lenses.txt')  
    2. lensesDataSet = [line.strip().split(' ') for line in fp.readlines()]  
    3. lensesFeatNames = ['age','prescript', 'astigmatic', 'tearRate']  
    4. lensesTree = createTree(lensesDataSet, lensesFeatNames)  
    5. print lensesTree  

    结果:


    然后我们还是把它画出来看一眼吧:


    如果医生参考这棵决策树来给患者推荐隐形眼镜的话,那么他最多只用问4个问题就可以了。


    这棵决策树非常好地匹配了实验数据,但是我们发现这些匹配选项可能太多了。这个问题被称为“过度匹配(overfitting)”。我了减轻这个问题,我们可以裁剪决策树,去掉一些没必要的叶节点。如果叶节点只能增加少许信息,那么可以删除它,将它并入到其他叶节点中。

    作者说:这章使用的算法是ID3,它无法直接处理数值型(即连续性)数据。第9章就会讲另外一个决策树构造算法:CART,同时也会进一步讨论过度匹配的问题。

     

    转自:http://blog.csdn.net/charlielincy/article/details/69831446

     

  • 相关阅读:
    Lumen源码分析之 一步一步带你实现Lumen容器(一)
    php 注册器模式 工厂模式
    理解 PHP 依赖注入 和 控制反转
    composer使用git作为仓储
    monolog记录日志
    Jupyter Notebook快捷键
    图像灰度化
    一道算法题:拼数字
    [转]Vue生态系统中的库
    window.postMessage实现网页间通信
  • 原文地址:https://www.cnblogs.com/wyuzl/p/7700872.html
Copyright © 2020-2023  润新知