在上一篇博文中,我写了如何依靠训练数据构造决策树,这一节让我们来验证一下算法的实际效果,本节所有代码与上一篇博文代码均在chosetree.py文件中
测试算法:使用决策树进行分类
#首先声明下,这里的inputTree,就是上节中的mytree,mytree=
{'no sufacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}
def classify(inputTree,featLabels,testVec):
firstStr = inputTree.keys()[0] #获得树的根节点'no sufacing'
secondDict = inputTree[firstStr] #获得key='no sufacing'的value,value={0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}
featIndex = featLabels.index(firstStr) #获得'no sufacing'在labels中的位置
for key in secondDict.keys():
if testVec[featIndex] == key: #判断需要验证的testVec是否等于secondDict的键值集
if type(secondDict[key]).__name__=='dict': #当value为字典时,在递归函数判断验证列表的第二个属性
classLabel = classify(secondDict[key],featLabels,testVec)
else:
classLabel = secondDict[key]
return classLabel
classify函数事实上是一个递归函数。测试函数最需要解决的一个问题是:如何判断特征在数据集中的位置,例如mytree中第一个用于划分数据集的特征是‘no sufacing'属性,但是在实际数据集中该属性存储在什么位置呢?函数前三行代码可以帮助我们解决这个问题,其中使用index方法查找位置是一个好方法。然后代码递归遍历整棵树,比较testVec变量中的值与树节点的值,如果到达叶子节点,则返回当前节点的分类标签。现在让我们来测试一下代码是否正确?
>>> import chosetree as ct
>>> dataset,label = ct.createDataSet()
>>> mytree = ct.createTree(dataset,label)
>>> mytree
{'no sufacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}
>>> classlabel = ct.classify(mytree,label,[1,0])
>>> classlabel
'no'
>>> ct.classify(mytree,label,[1,1])
'yes'
现在我们已经创建了决策树的分类器,我们发现每次使用时都需要重新构造决策树,这会耗费很多的计算时间。为了节省时间我们最好能够在每次执行分类时调用已经构造好的决策树。为了解决这个问题,需要使用python模块的pickle序列化对象。
使用算法:决策树的存储
def storeTree(inputTree,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)
验证:
>>> ct.storeTree(mytree,'mytree.txt')
>>> ct.grabTree('mytree.txt')
{'no sufacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}