15.决策树的测试和存储分类器

《机器学习实战》花了6页半的篇幅,来表述如何用matplotlib画一棵决策树。虽然这件事也有意义,但当你已经较为充分的理解了代码后,其实意义不算大。所以,这一段就此跳过,只留一张范例图供大家参考:


我们来看一下,如何使用决策树做分类。

def classify(inputTree, featLabels, testVec):

    firstStr = list(inputTree)[0]

    secondDict = inputTree[firstStr]

    featIndex = featLabels.index(firstStr)

    key = testVec[featIndex]

    valueOfFeat = secondDict[key]

    if isinstance(valueOfFeat, dict):

        classLabel = classify(valueOfFeat, featLabels, testVec)

    else: classLabel = valueOfFeat

    return classLabel

代码一共是10行。

由于我没有用到画图的函数,而运行代码的时候书本里调用的是画图的函数生成的树,我就用之前的createTree()来生成树。但是这里引发了一个bug,忽然提示“no surfacing”不存在,查了一会儿后发现,其实是在运行createTree()的时候,改写了labels本身。因此就要在生成树后,再重置一下labels即可。

代码解释如下:

def classify(inputTree, featLabels, testVec):

#定义输入,为输入的树(这里就是之前create的树),标签列表以及测试数据

    firstStr = list(inputTree)[0]

#取第一个特征值

    secondDict = inputTree[firstStr]

#将这个节点的分支生成一棵树

    featIndex = featLabels.index(firstStr)

#获取这个特征描述对应的特征数组下标

    key = testVec[featIndex]

#通过下标,找到特征对应的值

    valueOfFeat = secondDict[key]

#根据值,查找子树,确认是在哪一个分支

    if isinstance(valueOfFeat, dict):

        classLabel = classify(valueOfFeat, featLabels, testVec)

#isinstance是判断变量类型,即确认valueOfFeat是否是一个字典,如果是,继续classify递归查找

    else: classLabel = valueOfFeat

#如果不是,即已经摸到了没有继续分叉的子节点,则终止并返回valueOfFeat,此时它是一个这个测试数据对应的标签

    return classLabel

#返回这个标签


总体还比较好理解,难点在于前几行的代码,要对比生成的树的结构,一个根节点或者还有分叉的子节点,我们用secondDict取到它的分叉数据,然后再通过查找到这是哪一个特征项并对应的是什么数值结果,去找到对应的分叉项,并进一步往下走。我也是依靠反复的打印信息,来确定每一行代码的走向,可以说逻辑不难,但代码实现上会有点绕(连书中也说到,涉及到字典的操作,会比较复杂)。

由于至此为止用到的决策树数据集很简单,运算也很快,我们可以每次都跑一遍createTree()生成树,但是如果树很复杂,这种方式肯定是不合适的。我们在深度学习中也会遇到同样的问题,即跑出来的模型,最好是把它存起来,不然每次都跑一遍,累死了(累死了电脑,除非你是顶配,但即便电脑是顶配,碰上复杂模型也是死路一条)。

保存和读取的代码比较简单,用到了pickle,我们看一下:

def storeTree(inputTree, filename):

    import pickle

    fw = open(filename, 'wb')

    pickle.dump(inputTree, fw)

    fw.close()


def grabTree(filename):

    import pickle

    fr = open(filename, 'rb')

    return pickle.load(fr)

这里就不解释了吧,确实挺简单的。生成的pickle文件,虽然你可以用后缀名.txt(书中也是这么干的)来保存,但是事实上它并不是一个utf-8的文本格式,而是一个二进制序列化格式。强行打开的话,你就会看到一堆乱码:


乱码当中还是能看到几个英文词的,哪个就是特征的描述,看来这个还没有被转换,其他的就已经看不出是什么了。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容