决策树基本理论学习以及Python代码实现和详细注释
2017-10-17 20:16
1091 查看
首先是树的概念我们都比较熟悉了,然后决策树其实就是一棵树,通过在每一个几点通过特征的不同,走向不同的子树直到走到叶子节点找到分类的标签,算是完成了分类的过程。分类的过程不难理解,主要的是数据构造过程。
首先是构造的依据是什么呢,以什么依据作为特征使用的选择条件呢。这里使用的信息增益,通过计算信息增益的方式来选择特征作为划分数据集合的依据,信息增益最高的特征就是划分数据的最佳方式。
这里熵的计算方式是 H=−∑ni=1p(xi)log2p(xi)
计算熵的python代码如下
划分数据集合利用该特征的不同数据分类,比如选择人的视力作为分类标准,就可以有近视和正常两类。划分数据集合的代码如下
通过计算每一个特征作为分类依据划分数据集合后计算响应的熵,减去原来的熵计算信息增益,遍历完所有的特征后选择信息增益最大的特征作为划分数据集合的依据。
实现:
递归的结束条件有两个:
1、集合内所有的数据都是一个类别
2、用完了所有的特征依然没有能够得到分类,这个时候选择出现次数最多的类别作为返回结果。
构建决策树后可以进行存储,减少以后的计算。
到此决策树的功能基本实现,决策树的好处在于我们能够看到其工作过程,每个特征在决策书中所在的位置也是可以看到的,所以可以用可视化的方式绘制决策树。
完整版的代码见https://code.csdn.net/snippets/2593867.git
测试生成的决策树结果
决策树的优缺点
优点:计算复杂度不高,输出结果利于理解,对中间值缺失不敏感,可以处理不相关的特征数据
缺点:可能会产生过度匹配的问题
适用数据类型:数值型和标称型
首先是构造的依据是什么呢,以什么依据作为特征使用的选择条件呢。这里使用的信息增益,通过计算信息增益的方式来选择特征作为划分数据集合的依据,信息增益最高的特征就是划分数据的最佳方式。
信息增益和熵的计算
信息增益(information gain)就是选择一个特征之后所计算的熵(entropy),与原来的熵的差值即 infoGain=newEntropy−oldEntropy ,这里熵的计算方式是 H=−∑ni=1p(xi)log2p(xi)
计算熵的python代码如下
def calcShannonEnt(dataSet): numEntries=len(dataSet) #得到数据集合的总数 labelCounts={} #建立字典存储类别总数 for featVec in dataSet: #计算每种类别的数量,用于计算每种类别出现的概率 currentLabel=featVec[-1] if currentLabel not in labelCounts.keys(): labelCounts[currentLabel]=0 labelCounts[currentLabel]+=1 shannonEnt=0.0 for key in labelCounts: prob=float(labelCounts[key])/numEntries #计算每种类别出现的概率 shannonEnt-=prob*log(prob,2) #计算香农熵 return shannonEnt
划分数据集合
计算熵之后通过计算每个特征的信息增益,来找到最大的信息增益,选择出最佳分类特征,划分数据集合。划分数据集合利用该特征的不同数据分类,比如选择人的视力作为分类标准,就可以有近视和正常两类。划分数据集合的代码如下
def splitDataSet(dataSet,axis,value): #这个函数的作用就是从dataSet的第axis维中找到值维value的行, #然后将axis这个位置的值去掉后返回 retDataSet=[]#存储返回结果 for featVec in dataSet: if featVec[axis]==value:#找到在axis列上值为value的行 reduceFeatVec=featVec[:axis] # print reduceFeatVec reduceFeatVec.extend(featVec[axis+1:])#构造去掉axis位置值的list retDataSet.append(reduceFeatVec)#添加到结果list return retDataSet
通过计算每一个特征作为分类依据划分数据集合后计算响应的熵,减去原来的熵计算信息增益,遍历完所有的特征后选择信息增益最大的特征作为划分数据集合的依据。
实现:
def chooseBestFeatureToSplit(dataSet): numFeatures=len(dataSet[0])-1 #除去最后一列分类标签,得到所有特征的数量 baseEntropy=calcShannonEnt(dataSet) #最初的香农熵 baseInfoGain=0.0#基础信息增益初始化 bestFeature=-1#选择的特征初始化 for i in range(numFeatures): #遍历所有的特征选择计算每个特征的增益 featlist=[example[i] for example in dataSet] #抽取出该维的所有特征 uniqueVals=set(featlist) # print i,uniqueVals #对特征进行驱虫,创建唯一分类标签列表 newEntropy=0.0#初始化去掉该特征之后的香农熵 for value in uniqueVals: #计算新的香农熵 subDataSet=splitDataSet(dataSet, i, value) #利用前边的划分函数抽取出该维特征 prob=len(subDataSet)/float(len(dataSet)) #计算value类在数据中的概率 newEntropy+=prob*calcShannonEnt(subDataSet) #计算新的熵 infoGain=baseEntropy-newEntropy #计算该维特征的信息增益 # print infoGain,baseEntropy,newEntropy if infoGain>baseInfoGain: #如果大于原来的信息增益,则进行替换,并标记增益最大的特征维 baseInfoGain=infoGain bestFeature=i return bestFeature #返回增益最大的特征的列
构建决策树
能够选择出最佳的划分数据集合的特征之后,要做的就是构建决策树,这里使用递归的方式来构建决策树,每次选择信息增益最大的特征作为一次分类的根节点,根据特征的不同值来继续递归构建子树。递归的结束条件有两个:
1、集合内所有的数据都是一个类别
2、用完了所有的特征依然没有能够得到分类,这个时候选择出现次数最多的类别作为返回结果。
def createTree(dataSet,labels): classList=[example[-1] for example in dataSet] if classList.count(classList[0])==len(classList): #count计算classlist【0】这个标签出现的数量, #如果和总数一致,则说明所有的都是这一个类的,可以作为终止条件 return classList[0] if len(dataSet[0])==1: #dataset[0]是数据集的第一行, #如果第一行只有一列则说明已经使用完了所有的特征 #这时候室友出现次数最多的类别作为返回 return majorityCnt(classList) bestFeat=chooseBestFeatureToSplit(dataSet) #选择信息增益最大的特征列 bestFeatLabel=labels[bestFeat] #返回特征的描述 myTree={bestFeatLabel:{}} #创建树。用字典进行存储 del(labels[bestFeat]) #从标签中删除所选的标签 featValues=[example[bestFeat] for example in dataSet] #去除数据集合中所选特征列的所有数据 uniqueVals=set(featValues) #对数据进行去重 for value in uniqueVals: #对特征列的每一个类别建立子树 subLables=labels[:] myTree[bestFeatLabel][value]=createTree(splitDataSet(dataSet, bestFeat, value), subLables) return myTree
构建决策树后可以进行存储,减少以后的计算。
def storeTree(inputTree,filename): import pickle fw=open(filename,'w') pickle.dump(inputTree, fw) #将树序列化之后存储到文件中 fw.close() def grabTree(filename): import pickle fr=open(filename,'r') return pickle.load(fr) #将序列化的数解析成树的形式,返回结果
利用决策树进行分类
利用决策树进行分类,通过已有的训练好的决策树,给未知类别但是知道不同特征数据的变量进行分类def classify(inputTree,featLabels,testVec): firstStr=inputTree.keys()[0] secondDict=inputTree[firstStr] featIndex=featLabels.index(firstStr) #确顶当前特征在数据矩阵中的第几维 for key in secondDict.keys(): if testVec[featIndex]==key: #testVex[featIndex]是待分类数据在该特征出的数据值, #通过这个数据值找到子树的内容 if type(secondDict[key]).__name__=='dict': #如果是字典则需要继续向下进行从他的子树中找到分类结果 classLabel=classify(secondDict[key], featLabels, testVec) else: #走到叶子节点则返回分类类型 classLabel=secondDict[key] return classLabel
到此决策树的功能基本实现,决策树的好处在于我们能够看到其工作过程,每个特征在决策书中所在的位置也是可以看到的,所以可以用可视化的方式绘制决策树。
完整版的代码见https://code.csdn.net/snippets/2593867.git
测试生成的决策树结果
决策树的优缺点
优点:计算复杂度不高,输出结果利于理解,对中间值缺失不敏感,可以处理不相关的特征数据
缺点:可能会产生过度匹配的问题
适用数据类型:数值型和标称型
相关文章推荐
- 决策树ID3算法python实现代码及详细注释
- logistic回归算法详细分析与Python代码实现注释
- 传智博客佟老师jqurey学习笔记,以及例子代码详细注释。
- 机器学习之决策树(Decision Tree)及其Python代码实现
- **决策树基础以及Python代码实现**
- BP神经网络以及在手写数字分类中python代码的详细注释
- python学习一:软件版本选择以及代码调试初探
- PHP和Ajax实现二级联动下拉菜单(代码、详细注释)
- 彩色图像直方图均衡化及颜色直方图显示 opencv实现 完整代码及详细注释
- JXCELL实例学习与研究(六) 之 sheet的分页功能的实现,以及基本EXCEL公式的使用 以及补充函数说明
- Jquery选择器的概念以及选择器的学习一(基本、层级、简单,另有简单动画效果代码)
- 利用正则表达式实现统计代码中的注释行、空行、以及代码行的数量。
- IOC&AOP学习和探索(一)——AOP基本理论及实现
- Jquery Ajax客户端跨域请求 以及服务端Python代码实现
- 彩色图像直方图均衡化及颜色直方图显示 opencv实现 完整代码及详细注释
- IOC&AOP学习和探索(一)——AOP基本理论及实现
- 【学习笔记】用python实现bubblesort以及shakersort
- 最近在研究enigma2的代码,那叫个庞大,C/C++写中间件,上层应用全部用python实现,可以学习一下plugin的实现机制了.
- 决策树学习 之 ID3 C++STL代码实现
- 设计模式学习笔记以及java代码实现