3.3 测试和存储分类器

本书第一部分主要讲解机器学习的分类算法,然而到目前为止,本章学习的主要内容是如何从原始数据集中创建决策树,并使用Python函数库绘制树形图,方便我们了解数据的真实含义,下面我们将把重点转移到如何利用决策树执行数据分类上。

本节我们将使用决策树构建分类器,以及实际应用中如何存储分类器。下一节我们将在真实数据上使用决策树分类算法,验证它是否可以正确预测出患者应该使用的隐形眼镜类型。

3.3.1 测试算法:使用决策树执行分类

依靠训练数据构造了决策树之后,我们可以将它用于实际数据的分类。在执行数据分类时,需要决策树以及用于构造树的标签向量。然后,程序比较测试数据与决策树上的数值,递归执行该过程直到进入叶子节点;最后将测试数据定义为叶子节点所属的类型。

为了验证算法的实际效果,打开文本编辑器,将程序清单3-8包含的代码添加到文件trees.py中。

程序清单3-8 使用决策树的分类函数

def classify(inputTree,featLabels,testVec):
    firstStr = inputTree.keys[0]
    secondDict = inputTree[firstStr]
    #❶将标签字符串转换为索引
    featIndex = featLabels.index(firstStr)
    for key in secondDict.keys:
        if testVec[featIndex] == key:
            if type(secondDict[key]).__name__==\'dict\':
                classLabel = classify(secondDict[key],featLabels,testVec)
            else: classLabel = secondDict[key]
    return classLabel
  

程序清单3-8定义的函数也是一个递归函数,在存储带有特征的数据会面临一个问题:程序无法确定特征在数据集中的位置,例如前面例子的第一个用于划分数据集的特征是no surfacing属性,但是在实际数据集中该属性存储在哪个位置?是第一个属性还是第二个属性?特征标签列表将帮助程序处理这个问题。使用index方法查找当前列表中第一个匹配firstStr变量的元素❶。然后代码递归遍历整棵树,比较testVec变量中的值与树节点的值,如果到达叶子节点,则返回当前节点的分类标签。

将程序清单3-8包含的代码添加到文件trees.py之后,打开Python命令提示符,输入下列命令:

>>> myDat,labels=trees.createDataSet
>>> labels
[\'no surfacing\', \'flippers\']
>>> myTree=treePlotter.retrieveTree (0)
>>> myTree
{\'no surfacing\': {0: \'no\', 1: {\'flippers\': {0: \'no\', 1: \'yes\'}}}}
>>> trees.classify(myTree,labels,[1,0])
\'no\'
>>> trees.classify(myTree,labels,[1,1])
\'yes\'   
  

与图3-6比较上述输出结果。第一节点名为no surfacing,它有两个子节点:一个是名字为0的叶子节点,类标签为no;另一个是名为flippers的判断节点,此处进入递归调用,flippers节点有两个子节点。以前绘制的树形图和此处代表树的数据结构完全相同。

现在我们已经创建了使用决策树的分类器,但是每次使用分类器时,必须重新构造决策树,下一节我们将介绍如何在硬盘上存储决策树分类器。

3.3.2 使用算法:决策树的存储

构造决策树是很耗时的任务,即使处理很小的数据集,如前面的样本数据,也要花费几秒的时间,如果数据集很大,将会耗费很多计算时间。然而用创建好的决策树解决分类问题,则可以很快完成。因此,为了节省计算时间,最好能够在每次执行分类时调用已经构造好的决策树。为了解决这个问题,需要使用Python模块pickle序列化对象,参见程序清单3-9。序列化对象可以在磁盘上保存对象,并在需要的时候读取出来。任何对象都可以执行序列化操作,字典对象也不例外。

程序清单3-9 使用pickle模块存储决策树

def storeTree(in
    putTree,filename):
    import pickle
    fw = open(filename,\'w\')
    pickle.dump(inputTree,fw)
    fw.close

def grabTree(filename):
    import pickle
    fr = open(filename)
    return pickle.load(fr)   
  

在Python命令提示符中输入下列命令验证上述代码的效果:

>>> trees.storeTree(myTree,\'classifierStorage.txt\')
>>> trees.grabTree(\'classifierStorage.txt\')
{\'no surfacing\': {0: \'no\', 1: {\'flippers\': {0: \'no\', 1: \'yes\'}}}}
  

通过上面的代码,我们可以将分类器存储在硬盘上,而不用每次对数据分类时重新学习一遍,这也是决策树的优点之一,像第2章介绍了k-近邻算法就无法持久化分类器。我们可以预先提炼并存储数据集中包含的知识信息,在需要对事物进行分类时再使用这些知识。下节我们将使用这些工具处理隐形眼镜数据集。

《机器学习实战》