介绍
依靠训练数据构造了决策树之后,我们可以将它用于实际数据的分类。在执行数据分类时,需要决策树以及用于构造树的标签向量。然后,程序比较测试数据与决策树上的数值,递归执行该过程直到进人叶子节点;最后将测试数据定义为叶子节点所属的类型。
通俗点讲,就是你的数据集现在假如有两个特征 一个分类标签。然后一个未知的样本数据,给你两个特征的属性值 让你来预测该样本。
代码部分
决策树:样本预测
代码中只有第一个是新加入的函数 后几个就作说明 然后重点理解部分是 特征在数据集中的位置对应。(其实就是在找样本集中你给每一阶段的第一特征点的属性值是哪一个,知道了才好一步一步的进行判断呀)
"""
函数说明:
对决策树进行分类
Parameters:
inputTree:决策树
featLabels:数据集中label顺序列表
testVec:两个特征的属性值[特征一,特征二]
Rertun:
classLabel:预测结果
根据两个特征的属性值来预测分类
"""
def classify(inputTree, featLabels, testVec):
firstStr = list(inputTree.keys())[0] # 得到首key值
secondDict = inputTree[firstStr] # 首key的value--->下一个分支
featIndex = featLabels.index(firstStr) # 确定根节点是标签向量中的哪一个(索引)
key = testVec[featIndex] # 确定一个条件后的类别或进入下一个分支有待继续判别
# 这里要注意 我们并不知道目前的这个结点(也就是特征)在数据集中的具体位置 [0,1,no]
# 是第一个 还是第二个 所以需要用具体值再找索引的方式
# 找到了索引之后 我们就可以确定他是数据集中的哪一个值
# (这里再强调一下 数据集中特征的属性值的顺序 与 标签向量label中特征的顺序是一致的)
# dataSet = [[1, 1, 'yes']]
# labels = ['no surfacing', 'flippers']
# 这样一来计算机就知道了该在你放入的测试数据集寻找哪一个作为当前节点的预测值了
# 我们又用该索引去查找测试列表处该结点给的预测值是0还是1
# 是0相当于找了no预测值 是1 证明还需要判断或者是yes预测值
valueOfFeat = secondDict[key]
if isinstance(valueOfFeat, dict): # 判断实例函数 和 type函数类似 但是这个更好一点
classLabel = classify(valueOfFeat, featLabels, testVec)
else:
classLabel = valueOfFeat
return classLabel
def retrieveTree(i):
listOfTrees = [{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}},
{'no surfacing': {0: 'no', 1: {'flippers': {0: {'head': {0: 'no', 1: 'yes'}}, 1: 'no'}}}}
]
return listOfTrees[i]
def createDataSet():
dataSet = [[1, 1, 'yes'],
[1, 1, 'yes'],
[1, 0, 'no'],
[0, 1, 'no'],
[0, 1, 'no']]
labels = ['no surfacing', 'flippers']
# [是否可以浮出水面,是否有脚蹼]
return dataSet, labels
执行
if __name__ == '__main__':
data, label = createDataSet()
myTree = retrieveTree(0)
result = classify(myTree, label,[1,1])
if result == 'yes':
print("该样本预测是鱼")
else:
print("该样本预测不是鱼")
# >>>该样本预测是鱼
然后结合决策树本身我们发现预测结果是对的 大家可以更改一下未知数据 自行测试
决策树:成树储存
可以储存可以作为决策树的一个优点了,比较之前学习k-近邻的时候,分类器只能每次去创建再去预测数据。
"""
函数说明:
储存树
Parameters:
inputTree:决策树
fiename:完整的文件名 要加后缀
Rertun:
None
"""
def storeTree(inputTree, filename):
# fw = open(filename,'w')
# pickle.dump(inputTree, fw)
# TypeError: write() argument must be str, not bytes
# 原因:python3更新以后open函数添加了名为encoding的新参数,而这个新参数的默认值却是‘utf-8’。
# 这样在文件句柄上进行read和write操作时,系统就要求开发者必须传入包含Unicode字符的实例
# 而不接受包含二进制数据的bytes实例。
# 解决方法:
# 使用二进制写入模式(‘wb’)来开启待操作文件,而不能像原来那样,采用字符写入模式(‘w’)。
# 另外下面这种方式比较新
with open(filename, 'wb')as fw:
pickle.dump(inputTree, fw)
"""
函数说明:
加载树
Parameters:
fiename:文件名
Rertun:
取出的决策树
"""
def grabTree(filename):
# 文件读取数据的时候也有类似的问题。
# 解决这种问题的办法也相似:用'rb'模式(二进制模式)打开文件,而不要使用'r'模式。
with open(filename, "rb") as fr:
return pickle.load(fr)
执行
if __name__ == '__main__':
data, label = createDataSet()
myTree = retrieveTree(0)
storeTree(myTree, 'myTree.txt')
myTree = grabTree('myTree.txt')
print(myTree) # {'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}
总结
到这里就这样简单的结束啦,本节重点在于对未知样本特征属性值的确立,还不理解的小伙伴可以把数据集写出来对着看,记住标签向量和数据集中属性值的对应顺序是一致的,再捋一遍逻辑就可以了。下节我们将综合前面学过的内容进行一个新的案例实战,在此之前,建议再将之前的内容总的传一遍加深印象。