[机器学习实战]决策树 (3)

Q:上面的 newEntropy 为什么是根据子集计算的呢?
A :因为我们在根据一个特征计算香农熵的时候,该特征的分类值是相同,这个特征这个分类的香农熵为 0;
这就是为什么计算新的香农熵的时候使用的是子集。

(4)训练算法

构造树的数据结构

创建树的函数代码如下:

def createTree(dataSet, labels): classList = [example[-1] for example in dataSet] # 如果数据集的最后一列的第一个值出现的次数=整个集合的数量,也就说只有一个类别,就只直接返回结果就行 # 第一个停止条件:所有的类标签完全相同,则直接返回该类标签。 # count() 函数是统计括号中的值在list中出现的次数 if classList.count(classList[0]) == len(classList): return classList[0] # 如果数据集只有1列,那么最初出现label次数最多的一类,作为结果 # 第二个停止条件:使用完了所有特征,仍然不能将数据集划分成仅包含唯一类别的分组。 if len(dataSet[0]) == 1: return majorityCnt(classList) # 选择最优的列,得到最优列对应的label含义 bestFeat = chooseBestFeatureToSplit(dataSet) # 获取label的名称 bestFeatLabel = labels[bestFeat] # 初始化myTree myTree = {bestFeatLabel: {}} # 注:labels列表是可变对象,在PYTHON函数中作为参数时传址引用,能够被全局修改 # 所以这行代码导致函数外的同名变量被删除了元素,造成例句无法执行,提示'no surfacing' is not in list del(labels[bestFeat]) # 取出最优列,然后它的branch做分类 featValues = [example[bestFeat] for example in dataSet] uniqueVals = set(featValues) for value in uniqueVals: # 求出剩余的标签label subLabels = labels[:] # 遍历当前选择特征包含的所有属性值,在每个数据集划分上递归调用函数createTree() myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), subLabels) # print 'myTree', value, myTree return myTree (5)测试算法

使用决策树执行分类
代码如下:

def classify(inputTree, featLabels, testVec): """classify(给输入的节点,进行分类) Args: inputTree 决策树模型 featLabels Feature标签对应的名称 testVec 测试输入的数据 Returns: classLabel 分类的结果值,需要映射label才能知道名称 """ # 获取tree的根节点对于的key值 firstStr = inputTree.keys()[0] # 通过key得到根节点对应的value secondDict = inputTree[firstStr] # 判断根节点名称获取根节点在label中的先后顺序,这样就知道输入的testVec怎么开始对照树来做分类 featIndex = featLabels.index(firstStr) # 测试数据,找到根节点对应的label位置,也就知道从输入的数据的第几位来开始分类 key = testVec[featIndex] valueOfFeat = secondDict[key] print '+++', firstStr, 'xxx', secondDict, '---', key, '>>>', valueOfFeat # 判断分枝是否结束: 判断valueOfFeat是否是dict类型 if isinstance(valueOfFeat, dict): classLabel = classify(valueOfFeat, featLabels, testVec) else: classLabel = valueOfFeat return classLabel (6)使用算法

此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义。

构造决策树是很耗时的任务,即使很小的数据集也要花费几秒。如果用创建好的决策树解决分类问题就可以很快完成。

因此为了节省计算时间,最好能每次执行分类时调用已经构造好的决策树,为了解决这个问题,需要使用Python模块pickle序列化对象。序列化对象可以在磁盘上保存对象,并在需要的时候读取出来。任何对象都可以执行序列化,包括字典对象。

下面代码是使用pickle模块存储决策树:

def storeTree(inputTree, filename): impory pickle fw = open(filename, 'w') pickle.dump(inputTree, fw) fw.close() def grabTree(filename): import pickle fr = open(filename) return pickle.load(fr)

通过上面的代码我们可以把分类器存储在硬盘上,而不用每次对数据分类时重新学习一遍,这也是决策树的优点之一。++K-近邻算法就无法持久化分类器++。

[1] 决策树维基百科: https://zh.wikipedia.org/wiki/%E5%86%B3%E7%AD%96%E6%A0%91
[2]《机器学习实战》 -- Peter Harrington
[3]《机器学习》 -- 周志华

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzjzy.html