上一篇我们已经创建好了决策树。
代码语言:javascript复制dataset, featnames = createDataset()
myTree = createTree(dataset,featnames)
createPlot(myTree)
接着利用pickle库,我们可以把该决策树--嵌套的字典--永久存储到磁盘:
代码语言:javascript复制import pickle
#pickle.dump函数可以将python对象存储到磁盘
with open("fish.tree", "wb") as file:
pickle.dump(myTree, file)
下次要用到的时候,可以从磁盘直接加载,避免每次都要重新计算生成。
代码语言:javascript复制with open("fish.tree", "rb") as file:
tree = pickle.load(file)#pickle.load函数可以从文件导入存好的python对象
print(tree)
createPlot(tree)#绘图
有了决策树,我们就可以根据样本的特征值来执行分类。遇到判断节点则递归调用,遇到叶子节点则终止,返回叶子节点的分类标签:
代码语言:javascript复制def classfy(inputTree, featNames, testVec):
firstStr = list(inputTree.keys())[0]
secondDict = inputTree[firstStr]
featIndex =featNames.index(firstStr) # 标签字符串转成索引
for key in secondDict.keys():
if testVec[featIndex] == key:
if type(secondDict[key]).__name__ == "dict": #数据类型为字典(还有子树)
classLabel = classfy(secondDict[key], featNames, testVec) #递归调用
else: #叶子节点
classLabel = secondDict[key]
return classLabel
最后我们来测试分类效果:
代码语言:javascript复制featnames =["no surfacing", "flippers"]#特征 名
#两个测试样本
s1 = ["yes", "yes"]
s2 = ["yes", "no"]
print(classfy(tree, featnames, s1))
print(classfy(tree, featnames, s2))
完全正确!
下面的例子讲解决策树如何预测近视患者需要佩戴的隐形眼镜类型。隐形眼镜数据集包含很多患者眼部状况的观察情况以及医生推荐的隐形眼镜类型分类结果。分类结果包括硬材质、软材质以及不适合佩戴隐形眼镜。本例使用隐形眼镜数据集的简化版,数据存储在文本文件中:
我们只需修改创建数据集的函数,其它函数保持不变,就可以创建、绘制并保存决策树:
代码语言:javascript复制def createDataset():
with open("lenses.txt") as fr:
lenses = [ line.strip().split('t') for line in fr.readlines()]
featnames =["age", "prescript","astigmatic","tearRate"]#特征 名
return lenses, featnames
最后测试:
代码语言:javascript复制with open("lenses.tree", "rb") as file:
tree = pickle.load(file)
print(tree)
createPlot(tree)
featnames =["age", "prescript","astigmatic","tearRate"]#特征 名
#测试样本
s1 = ["presbyopic", "myope", "no", "reduced"]
print(classfy(tree, featnames, s1))
上篇和本篇使用的决策树算法称为ID3。ID3无法直接处理数值型数据,尽管我们可以将数值型数据转化为标称型数据,但如果存在太多的特征划分,会产生overfitting的问题。为了解决overfitting的问题,我们需要剪枝,将只带来少许信息增益的叶子节点删除,将它们并入到其它叶子节点中。