决策树
来源:互联网 发布:淘宝cos店便宜 编辑:程序博客网 时间:2024/06/05 14:17
一 、什么是决策树?
决策树(Decision Tree)是在已知各种情况发生概率的基础上,通过构成决策树来求取净现值的期望值大于等于零的概率,评价项目风险,判断其可行性的决策分析方法,是直观运用概率分析的一种图解法。由于这种决策分支画成图形很像一棵树的枝干,故称决策树。在机器学习中,决策树是一个预测模型,他代表的是对象属性与对象值之间的一种映射关系。
决策树的任务是为了理解数据中所蕴含的知识信息,因此决策树可以使用不熟悉的数据集合,并从中提取出一系列规则,并创建规则。
二 、决策树的构建
(1)计算信息增益
划分数据集的最大原则是:将无序的数据变的更加有序;所以我们要计算信息增益。
信息增益:划分数据集之前、之后信息发生的变化,我们计算每个特征值划分的数据集获得熵,与原始的数据熵相比获得增量。信息增量最高的特征就是最好的选择。
信息熵的计算公式为:
其中 D 表示训练数据集,c 表示数据类别数,Pi 表示类别 i 样本数量占所有样本的比例。
数据集样例
Python代码实现如下(计算给定数据集的信息熵):
def calcShannonEnt(dataSet): numEntries = len(dataSet)#数组长度5 labelCounts = {} for featVec in dataSet: #print featVec 分别取出每组数组[1, 1, 'yes'],[1, 1, 'yes'],[1, 0, 'no'],[0, 1, 'no'],0, 1, 'no'] currentLabel = featVec[-1]#取出数组中最后一个元素,yes or no if currentLabel not in labelCounts.keys(): labelCounts[currentLabel] = 0 labelCounts[currentLabel] += 1#统计yes and no标签的总数 shannonEnt = 0.0 #print labelCounts {'yes': 2, 'no': 3} for key in labelCounts: prob = float(labelCounts[key])/numEntries#计算yes和no标签分别占有的比例 shannonEnt -= prob * log(prob,2) #log base 2 return shannonEnt接下来我们建立测试数据的函数:
def createDataSet(): dataSet = [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']] labels = ['no surfacing','flippers'] #change to discrete values return dataSet, labels依次输入import tree,myDat,labels=tree.createDataSet(),tree.calcShannonEnt(myDat)测试结果:大概为0.97
证明划分数据集前的信息熵为0.97,熵越高,信息的混合数据越高。
(2)划分数据集
计算出数据集的无序程度后,我们接下来应该划分数据集,然后度量划分数据集的熵。
我们要对每个分类特征划分数据集的结果计算一次信息熵,然后判断哪个特征划分的数据集是最好的划分。代码如下:
def splitDataSet(dataSet, axis, value): retDataSet = [] for featVec in dataSet: #print featVec[axis] 取出第axis列数据 if featVec[axis] == value: #print featVec[:axis] 选取分割轴 reducedFeatVec = featVec[:axis] #chop out axis used for splitting reducedFeatVec.extend(featVec[axis+1:]) #print reducedFeatVec[1, 'yes'] [1, 'yes'] [0, 'no'] retDataSet.append(reducedFeatVec) return retDataSet其中三个输入的参数分别为数据集,特征(每一列代表一个分类特征),返回的特征值(0或1)
我们用刚才的数据集测试,输入tree.splitDataSet(myDat,0,1),tree.splitDataSet(myDat,0,0)分别计算第一列数据中是,否水面可以生存对应的情况。
(3)选择最好的数据集划分方式
当我们切割好每种特征类别是与否的情况后,我们分别计算每种分类的信息熵,和原始信息熵比较,计算最好的信息增益,作为我们要选取的分类。代码如下:
def chooseBestFeatureToSplit(dataSet): numFeatures = len(dataSet[0]) - 1 #the last column is used for the labels baseEntropy = calcShannonEnt(dataSet) bestInfoGain = 0.0; bestFeature = -1 for i in range(numFeatures): #iterate over all the features featList = [example[i] for example in dataSet]#create a list of all the examples of this feature #print featList得到每一列(每一类)中的元素 uniqueVals = set(featList) #得到每一列中不同的特征值set([0, 1]) newEntropy = 0.0 for value in uniqueVals: subDataSet = splitDataSet(dataSet, i, value) #看不同分类下每个特征值的结果 prob = len(subDataSet)/float(len(dataSet)) newEntropy += prob * calcShannonEnt(subDataSet) #print newEntropy 计算每一类中的新熵值 infoGain = baseEntropy - newEntropy #计算信息增益,越大越好,代表该分类越明显 #print infoGain if (infoGain > bestInfoGain): #compare this to the best gain so far bestInfoGain = infoGain #if better than current best, set to best bestFeature = i return bestFeature #returns an integer
结果表明第0列,也就是不浮出水面是否能生存更适合作为我们的分类标准。
(4)构建决策树
其工作原理如下:得到原始数据集,然后基于最好的属性值划分数据集,第一次划分后,数据将向下传递到树分支的下一个节点,在这个节点上我们再次划分数据。我们可以采用递归的原则处理数据集。
递归结束的条件为(1)程序遍历完所有划分数据集的属性;(2)每个分支下的实例都有相同的分类
Python代码如下:
def majorityCnt(classList): classCount={} for vote in classList: if vote not in classCount.keys(): classCount[vote] = 0 classCount[vote] += 1 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0]def createTree(dataSet,labels): classList = [example[-1] for example in dataSet] #classList统计分类结果,Yes和No的数量 if classList.count(classList[0]) == len(classList): return classList[0]#classList.count(classList[0])统计某一类别的数量,类别相同则停止分类 if len(dataSet[0]) == 1: return majorityCnt(classList) #遍历完所以特征,返回出现次数最多的类别 bestFeat = chooseBestFeatureToSplit(dataSet) bestFeatLabel = labels[bestFeat] #print labels[bestFeat]为特征标签 myTree = {bestFeatLabel:{}} del(labels[bestFeat]) #删除已经构建在树节点上的特征标签 featValues = [example[bestFeat] for example in dataSet] #print featValues(1,1,1,0,0) uniqueVals = set(featValues) #print uniqueVals set(1,0) for value in uniqueVals: subLabels = labels[:] #print subLabels #copy all of labels, so trees don't mess up existing labels myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels) return myTree
输出结果为:{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}至此,完成决策树的构建。
(5)使用决策树构建分类函数
def classify(inputTree,featLabels,testVec):# 决策树分类函数 firstStr = inputTree.keys()[0]# 得到树中的第一个特征 secondDict = inputTree[firstStr] # 得到第一个对应的值 featIndex = featLabels.index(firstStr) key = testVec[featIndex] valueOfFeat = secondDict[key] if isinstance(valueOfFeat, dict): #遍历决策树 classLabel = classify(valueOfFeat, featLabels, testVec) else: classLabel = valueOfFeat return classLabel#返回分类标签
(6)决策树的存储
但如果每次构建决策树是很耗时的任务,会花费很多计算空间,所以我们调用创建好的分类将会节省时间。
为此我们使用Python模块pickle序列化对象,并将序列化后的结果保存在磁盘上,在需要的时候都出来即可。
def storeTree(inputTree,filename): import pickle #导入模块pickle序列化对象 fw = open(filename,'w') pickle.dump(inputTree,fw)#决策树序列化 fw.close() def grabTree(filename): import pickle fr = open(filename) return pickle.load(fr)#从文件中读取决策树,就不用每次每次构建,在需要的时候读取即可
三 、小结
决策树分类器就像带有终止块的流程图,终止块表示分类结果。开始处理数据时,我们首先测量数据的不一致性,也就是熵,最后选择最优的划分数据集的分类特征,使所有数据属于不同的分类中。ID3(决策树)算法用于划分布尔型数据,构建决策树时,我们通常采用递归方法将数据集(使用Python字典存储树的节点信息)转换为决策树。
此外,我们还能使用Matplotlib的注释功能,将存储的树结构转换为容易理解的图形。Pickle模块则用来存储决策树树的结构。
- 决策树
- 决策树
- 决策树
- 决策树
- 决策树
- 决策树
- 决策树
- 决策树
- 决策树
- 决策树
- 决策树
- 决策树
- 决策树
- 决策树
- 决策树
- 决策树
- 决策树
- 决策树
- normalize 函数使用
- 0-1背包
- Java注解
- 解决 Successfully created project '' on GitHub, but initial push failed: Could not read from remote re
- SpringMVC整合UEditor
- 决策树
- 链接保存
- java过滤器与拦截器
- mysql代码注释,练习用
- Linux功耗管理(24)_Linux PM QoS framework(3)_per-device PM QoS
- 【学习笔记三】- 动态添加元素绑定事件函数测试
- 安卓FileProvider
- 接口返回升级报场景授权编号错误
- 访问图像中每个像素的值 opencv