首页  >  文章  >  后端开发  >  python机器学习决策树详细介绍

python机器学习决策树详细介绍

高洛峰
高洛峰原创
2017-03-19 14:20:142026浏览

决策树(Decision Trees ,DTs)是一种无监督的学习方法,用于分类和回归。 

优点:计算复杂度不高,输出结果易于理解,对中间值缺失不敏感,可以处理不相关的特征数据
缺点:可能会产生过度匹配的问题
适用数据类型:数值型和标称型  source code下载  https://www.manning.com/books/machine-learning-in-action

运行demo    

关键算法

if so return 类标签;

else

  寻找划分数据集的最好特征
         划分数据集
         创建分支节点
             for 每个分支节点
                   调用函数createBranch并增加返回结果到分支节点中
       return 分支节点

对应代码

def createTree(dataSet,labels):
     classList = [example[-1] for example in dataSet] 不是dataset[-1] {dataset倒数第一元素} ,而这时里,dataset每一个元素里的倒数第一元素
     if classList.count(classList[0]) == len(classList): 如果返回分类List count类型一样,则返回该类型!在子节点 是否可分类 如是一类型 返回  否则 递归往下分类
           return classList[0]#stop splitting when all of the classes are equal
     if len(dataSet[0]) == 1: #stop splitting when there are no more features in dataSet 如果只有一个元素
           return majorityCnt(classList)
     bestFeat = chooseBestFeatureToSplit(dataSet)      选择最好的特征索引
     bestFeatLabel = labels[bestFeat]      而得到这个label  flippers 还是 no surfaces 呢
     myTree = {bestFeatLabel:{}}      然后创建该最好的分类 的子树
     del(labels[bestFeat])    删除了该最好分类
     featValues = [example[bestFeat] for example in dataSet]
     uniqueVals = set(featValues)     set是归类,看只有多少种类
     for value in uniqueVals:
           subLabels = labels[:]       #copy all of labels, so trees don't mess up existing labels
           myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels)
     return myTree          

在划分数据集之前之后信息发生的变化称为信息增益,划分数据集的最大原则是将无序的数据变得更加有序。 这里理解成切饼原理:

python机器学习决策树详细介绍

把信息的复杂度,信息量用单位熵描述程度。 对应的是饼的密度,如果是均等密度的垂直切饼,

每部分重量g = 总G * 其占大圆比例!  类比地,如果划分后信息熵一样, 每个小部分数据的  小h = pro * 总 H,   而 求和 h[i] = H.

 然而:我们需要的恰恰相反:需要的不是信息熵一样,而是不均等,比如上面,上绿的可能是草每馅,黄色是苹果馅,蓝色是紫薯,每个密度不同!

我们需要把它正确划分!分类出来,找出逼近不同馅之间的那条线。 这里的 小h会最小化,而最终在面积不变下,总H会 逼近最小值,是最优化问题求解。


调试过程
calcShannonEnt : [[1, 'no'], [1, 'no']] = 0    log(1,2) * 0.4 = 0 为什么是0,因为pro必然是1
log(prob,2) log(1,2) = 0;2^0=1,因为 prob <=1,所以 log(Value,2) <0
: [[1, 'yes'], [1, 'yes'], [0, 'no']] = 0.91 >> * 0.6 = 0.55
25行 for featVec in dataSet: 计频 for prop
chooseBestFeatureToSplit()  
0.9709505944546686 = calcShannonEnt(dataSet) : [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]

#检测数据集的每个子项是否属于同一类: 如果值都是a,而result都是y或n 则为一类 所以,只是两个参数输入
0.5509775004326937 = += prob * calcShannonEnt(subDataSet) 分开的子集后,的概率*香农滴,得到的和,原来的整体的香浓滴比

# 数据越接近,香浓熵值越少,越接近0 ,越不同,越多分逻辑,香浓熵就越大
# 只计算 其dataSet的featVec[-1] 结果标签
def calcShannonEnt(dataSet):


0.4199730940219749  infoGain = baseEntropy - newEntropy

 

总结:  

  一开始,看代码看不懂,不明白到底是要做什么!分类,我们的目标是把一堆数据分类,以label来标签上。
像k邻近 classify([0, 0], group, labels, 3) 意思是,把新数据[0,0] 按k=3的邻近算法在 group,labels数据里的分类! group与label对应!

后面看到了

        python机器学习决策树详细介绍

 

才理解,数据dataSet 的意思是 条个维度的值 而最后一个是 是否为 fish的,结果标签


所以,是要把每个维度 切出来 + 结果标签 成二维的 一列数组,去比较分类
测试应该是,把前n个维量的值,向量输入,输出是yes or no!
一开始看,比较头晕,条理清楚,理顺下思路,看代码才易懂!
理解了目标和初始数据,你才明白,原来classList是结果标签!,是对应将要分类的dataset的对应结果标签
而labels 则是 特征名,对应开始的dataset的维度,特征的名strname
bestFeatLabel 最好分类特征的维度名 是第一维度还是第二,第N
featValues 是bestFeatLabel 的维度下,的值数组。就是这一维度下的组 用来做新的分类比较。
uniqueVals 用set判断来是否一类,
比如
  dataSet = [[1, 1, 'yes'],[0, 1, 'yes'],[1, 0, 'no'],[1, 0, 'no'],[0, 0, 'no']]
  labels = ['no surfacing','flippers',]
这样的createTree :{'flippers': {0: 'no', 1: 'yes'}} 直接把no surfacing的维度省略了

 

最后,再用一段话来讲讲决策树:

  决策树本质上:是加快效率!用‘最大最优’划分 第一个否定标签,而肯定标签要继续划分!而否定,直接返回叶结点答案!而对应的其它维度就不继续判断!

理论上,即使不用决策树算法,就盲目穷举,就是每次都把数据所有维度轮一次!而有最后个标签答案!维度数*数据个数!为复杂度! 这是对记忆的匹配回答!合适专家系统! 预测未出现的情况能力差!但数据量大,速度快,也能有智能的感觉! 因为是对过去经验的重演! 然而它是死的?不,它不是死的!穷举是死的,但决策树是动态的! 学习的!变化树!至少它的建成是动态的!当数据不完全时,它也可能是不完全的!当一个判断可以解决就用一个判断,不能就再需要一个!维度增加!


以上是python机器学习决策树详细介绍的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn