任务3·决策树算法梳理

本文深入探讨了决策树算法的基础,包括信息熵、信息增益、基尼不纯度等概念,以及ID3、C4.5和CART算法的工作原理。此外,还介绍了决策树防止过拟合的手段,如预剪枝和后剪枝策略,以及模型评估方法。最后,提到了Python中sklearn库的决策树参数和绘图技巧。
摘要由CSDN通过智能技术生成

决策树学习采用的是自顶向下的递归方法,其基本思想是以信息熵为度量构造一颗熵值下降最快的树,到叶子节点处,熵值为0。其具有可读性、分类速度快的优点,是一种有监督学习。最早提及决策树思想的是Quinlan在1986年提出的ID3算法和1993年提出的C4.5算法,以及Breiman等人在1984年提出的CART算法。

信息论基础

引入:如何定义信息量

某事件发生的概率小,则该事件的信息量大。即信息量可以代表不确定性;

  • 如果两个事件X和Y独立,即p(xy) = p(x)p(y),假定X和Y的信息量分别为h(X)和h(Y),则二者同时发生的信息量应该为h(XY) = h(X) + h(Y)
  • 定义事件X发生的概率为:p(x),则X的信息量为:h(p(x)) = -lnp(x)

对随机事件的信息量求期望,得熵的定义:

H(X) = -Σp(x)lnp(x)

经典熵的定义,底数是2,单位为bit;
为了方便计算可以使用底数e,则单位为nat(奈特)。

可以得到,当一个变量X服从均匀分布时,它所包含的信息熵是最大的。

计算如下:
p(xi) = 1/N, 则熵为:H§ = -Σpi * lnpi = -Σ1/N * ln(1/N) = lnN

所以,我们可以得到如下结论:

  • 0 <= H(X) <= ln|X|

  • 熵是随机变量不确定性的度量,不确定性越大,熵值越大;
    若随机变量退化为定值,则熵最小,为0;
    锁随机分布为均匀分布,熵最大。

联合熵

两个随机变量X,Y的联合分布,可以形成联合熵(Joint Entropy)
即:H(X, Y) = -Σp(x, y) lnp(x, y)

条件熵

H(X|Y)=H(X, Y) - H(Y)
表示在Y发生的前提下,X发生新带来的熵。
在这里插入图片描述

信息增益

在概率中定义为:待分类的集合的熵和选定某个特征的条件熵之差(这里只的是经验熵或经验条件熵,由于真正的熵并不知道,是根据样本计算出来的),公式如下:
在这里插入图片描述
信息增益在决策树算法中是用来选择特征的指标,信息增益越大,则这个特征的选择性越好。

基尼不纯度

从一个数据集中随机选取子项,度量其被错误的划分到其他组里的概率。
在这里插入图片描述
结论:

  • 基尼不纯度可以作为 衡量系统混乱程度的 标准;基尼不纯度越小,纯度越高, 集合的有序程度越高,分类的效果越好;
  • 基尼不纯度为 0 时,表示集合类别一致;
  • 在决策树中,比较基尼不纯度的大小可以选择更好的决策条件(子节点)。

决策树的不同分类算法

在这里插入图片描述

ID3算法

在信息论中,期望信息越小,那么信息增益就越大,从而纯度就越高。ID3算法的核心思想就是以信息增益来度量属性的选择,选择分裂后信息增益最大的属性进行分裂。该算法采用自顶向下的贪婪搜索遍历可能的决策空间。

  • 输入:训练数据集D,特征集A,阈值ε;
  • 输出:决策树T.

Step1:若D中所有实例属于同一类,则T为单结点树,并将类作为该节点的类标记,返回T;

Step2:若A=Ø,则T为单结点树,并将D中实例数最大的类作为该节点的类标记,返回T;

Step3:否则,2.1.1(3)计算A中个特征对D的信息增益,选择信息增益最大的特征;

Step4:如果的信息增益小于阈值ε,则T为单节点树,并将D中实例数最大的类作为该节点的类标记,返回T

Step5:否则,对的每一种可能值,依将D分割为若干非空子集,将中实例数最大的类作为标记,构建子结点,由结点及其子树构成树T,返回T;

Step6:对第i个子节点,以为训练集,以为特征集合,递归调用Step1~step5,得到子树,返回;

C4.5

C4.5算法与ID3算法很相似,C4.5算法是对ID3算法做了改进,在生成决策树过程中采用信息增益比来选择特征。

【信息增益比】

我们知道信息增益会偏向取值较多的特征,使用信息增益比可以对这一问题进行校正。

定义:特征A对训练数据集D的信息增益比GainRatio(D,A)定义为其信息增益Gain(D,A)与训练数据集D的经验熵H(D)之比:
在这里插入图片描述

CART分类树

  • 输入:训练数据集D,停止计算的条件
  • 输出:CART决策树

根据训练数据集,从根结点开始,递归地对每个结点进行以下操作,构建二叉树:

Step1:设结点的训练数据集为D,计算现有特征对该数据集的基尼指数。此时,对每一个特征A,对其可能取的每个值a,根据样本点A=a的测试为“是”或“否”将D分割为D1和D2两部分,利用上式Gini(D,A)来计算A=a时的基尼指数。

Step2:在所有可能的特征A以及他们所有可能的切分点a中,选择基尼指数最小的特征及其对应可能的切分点作为最有特征与最优切分点。依最优特征与最有切分点,从现结点生成两个子节点,将训练数据集依特征分配到两个子节点中去。

Step3:对两个子结点递归地调用Step1、Step2,直至满足条件。

Step4:生成CART决策树

算法停止计算的条件是节点中的样本个数小于预定阈值,或样本集的基尼指数小于预定阈值,或者没有更多特征。

回归树原理

决策树实际上是将空间用超平面进行划分的一种方法,每次分割的时候,都将当前的空间一分为二, 这样使得每一个叶子节点都是在空间中的一个不相交的区域,在进行决策的时候,会根据输入样本每一维feature的值,一步一步往下,最后使得样本落入N个区域中的一个(假设有N个叶子节点),如下图所示。
在这里插入图片描述
既然是决策树,那么必然会存在以下两个核心问题:如何选择划分点?如何决定叶节点的输出值?

一个回归树对应着输入空间(即特征空间)的一个划分以及在划分单元上的输出值。分类树中,我们采用信息论中的方法,通过计算选择最佳划分点。而在回归树中,采用的是启发式的方法。假如我们有n个特征,每个特征有si(i∈(1,n))
个取值,那我们遍历所有特征,尝试该特征所有取值,对空间进行划分,直到取到特征j的取值s,使得损失函数最小,这样就得到了一个划分点。公式如下:
在这里插入图片描述
假设将输入空间划分为M个单元:R1,R2,…,Rm,那么每个区域的输出值就是:cm=ave(yi|xi∈Rm),也就是该区域内所有点y值的平均数。

决策树防止过拟合手段

产生过度拟合数据问题的原因有哪些?

原因1:样本问题

(1)样本里的噪音数据干扰过大,大到模型过分记住了噪音特征,反而忽略了真实的输入输出间的关系;

(2)样本抽取错误,例如样本数量太少,抽样方法错误,抽样时没有足够正确考虑业务场景或业务特点等等,导致抽出的样本数据不能有效足够代表业务逻辑或业务场景;

(3)建模时使用了样本中太多无关的输入变量。

原因2:构建决策树的方法问题

在决策树模型搭建中,我们使用的算法对于决策树的生长没有合理的限制和修剪的话,决策树的自由生长有可能每片叶子里只包含单纯的事件数据或非事件数据,可以想象,这种决策树当然可以完美匹配(拟合)训练数据,但是一旦应用到新的业务真实数据时,效果是一塌糊涂。

这里我们主要讨论第二种情况的解决办法——决策树的剪枝。有两种思路:预剪枝(Pre-Pruning)和后剪枝(Post-Pruning)。

【先剪枝】
有多种不同的方式可以让决策树停止生长,下面介绍几种停止决策树生长的方法:

   1.定义一个高度,当决策树达到该高度时就可以停止决策树的生长,这是一种最为简单的方法;

   2.达到某个结点的实例具有相同的特征向量,即使这些实例不属于同一类,也可以停止决策树的生长。这种方法对于处理数据中的数据冲突问题非常有效;

   3.定义一个阈值,当达到某个结点的实例个数小于该阈值时就可以停止决策树的生长;

   4.定义一个阈值,通过计算每次扩张对系统性能的增益,并比较增益值与该阈值的大小来决定是否停止决策树的生长。

【后剪枝】

后剪枝算法有很多种,这里简要总结如下:

Reduced-Error Pruning (REP,错误率降低剪枝)

这个思路很直接,完全的决策树不是过度拟合么,我再搞一个测试数据集来纠正它。对于完全决策树中的每一个非叶子节点的子树,我们尝试着把它替换成一个叶子节点,该叶子节点的类别我们用子树所覆盖训练样本中存在最多的那个类来代替,这样就产生了一个简化决策树,然后比较这两个决策树在测试数据集中的表现,如果简化决策树在测试数据集中的错误比较少,那么该子树就可以替换成叶子节点。该算法以bottom-up的方式遍历所有的子树,直至没有任何子树可以替换使得测试数据集的表现得以改进时,算法就可以终止。

Pessimistic Error Pruning (PEP,悲观剪枝)

PEP剪枝算法是在C4.5决策树算法中提出的, 把一颗子树(具有多个叶子节点)用一个叶子节点来替代的话,比起REP剪枝法,它不需要一个单独的测试数据集。

把一棵子树(具有多个叶子节点)的分类用一个叶子节点来替代的话,在训练集上的误判率肯定是上升的,但是在测试数据上不一定,我们需要把子树的误判计算加上一个经验性的惩罚因子,用于估计它在测试数据上的误判率。对于一棵叶子节点,它覆盖了N个样本,其中有E个错误,那么该叶子节点的错误率为(E+0.5)/N。这个0.5就是惩罚因子,那么对于该棵子树,假设它有L个叶子节点,则该子树的误判率估计为:
在这里插入图片描述
剪枝后该子树内部节点变成了叶子节点,该叶子结点的误判个数J同样也需要加上一个惩罚因子,变成J+0.5。那么子树是否可以被剪枝就取决于剪枝后的错误J+0.5在
在这里插入图片描述
的标准误差内。对于样本的误差率e,我们可以根据经验把它估计成伯努利分布,那么可以估计出该子树的误判次数均值和标准差
在这里插入图片描述
使用训练数据,子树总是比替换为一个叶节点后产生的误差小,但是使用校正的误差计算方法却并非如此。剪枝的条件:当子树的误判个数大过对应叶节点的误判个数一个标准差之后,就决定剪枝:
在这里插入图片描述

模型评估

1 保持方法

在保持(Holdout)方法中,将被标记的原始数据划分成两个不相交的集合,分别称为训练集合检验集。在训练数据集上归纳分类模型,在检验集上评估模型的性能。分类器的准确率根据模型在检验集上的准确率估计。

保持方法有一些众所周知的局限性。第一,用于训练的被标记样本较少,因为要保留一部分记录用于检验。因此,建立的模型不如使用所有被标记样本建立的模型好。第二,模型可能高度依赖于训练集和检验集的构成。一方面,训练集越小,模型的方差越大。另一方面,如果训练集太大,根据用较小的检验集估计的准确率又不太可靠。这样的估计具有很宽的置信区间。最后,训练集合检验集不再是相互独立的。因为训练集和检验集来源于同一个数据集,在一个子集中超出比例的类在另一个子集就低于比例,反之亦然。

2 随机二次抽样

可以多次重复保持方法来改进对分类器性能的估计,这种方法称作随机二次抽样。设acci是第i次迭代的模型的准确率,总准确率是:
。
随机二次抽样也会遇到一些与保持方法同样的问题,因为在训练阶段也没有利用尽可能多的数据。并且,由于它没有控制每个记录用于训练和检验的次数,因此,有些用于训练的记录使用的频率可能比其他记录高很多。

3 交叉验证

4 自助法

迄今为止,我们介绍的方法都是假定训练记录采用不放回抽样,因此,训练集和检验集都不包含重复记录。在自助(boostrap)方法中,训练记录采用有放回抽样,使得它等概率地被重新抽取。如果原始数据有N个记录,可以证明,平均来说,大小为N的自助样本大约包含原始数据中63.2%的记录。这是因为一个记录被自助抽样抽取的概率是1-(1-1/N)N,当N充分大时,该概率逐渐逼近1-e-1=0.632。没有抽中的记录就称为检验集的一部分,将训练集简历的模型应用到检验集上,得到自助样本准确率的一个估计εt。抽样过程重复b次,产生b个自助样本。  按照如何计算分类器的总准确率,有几种不同的自助抽样法。常用的方法之一是.632自助(.632 boostrap),它通过组合每个自助样本的准确率εt和由包含所有标记样本的训练集计算的准确率(accs)计算总准确率(accboot):
在这里插入图片描述

sklearn参数详解,Python绘制决策树

'''
scikit-learn中有两类决策树,它们均采用优化的CART决策树算法。
'''
from sklearn.tree import DecisionTreeRegressor
'''
回归决策树
'''
DecisionTreeRegressor(criterion="mse",
                         splitter="best",
                         max_depth=None,
                         min_samples_split=2,
                         min_samples_leaf=1,
                         min_weight_fraction_leaf=0.,
                         max_features=None,
                         random_state=None,
                         max_leaf_nodes=None,
                         min_impurity_decrease=0.,
                         min_impurity_split=None,
                         presort=False)
'''
参数含义:
1.criterion:string, optional (default="mse")
            它指定了切分质量的评价准则。默认为'mse'(mean squared error)。
2.splitter:string, optional (default="best")
            它指定了在每个节点切分的策略。有两种切分策咯:
            (1).splitter='best':表示选择最优的切分特征和切分点。
            (2).splitter='random':表示随机切分。
3.max_depth:int or None, optional (default=None)
             指定树的最大深度。如果为None,则表示树的深度不限,直到
             每个叶子都是纯净的,即叶节点中所有样本都属于同一个类别,
             或者叶子节点中包含小于min_samples_split个样本。
4.min_samples_split:int, float, optional (default=2)
             整数或者浮点数,默认为2。它指定了分裂一个内部节点(非叶子节点)
             需要的最小样本数。如果为浮点数(0到1之间),最少样本分割数为ceil(min_samples_split * n_samples)
5.min_samples_leaf:int, float, optional (default=1)
             整数或者浮点数,默认为1。它指定了每个叶子节点包含的最少样本数。
             如果为浮点数(0到1之间),每个叶子节点包含的最少样本数为ceil(min_samples_leaf * n_samples)
6.min_weight_fraction_leaf:float, optional (default=0.)
             它指定了叶子节点中样本的最小权重系数。默认情况下样本有相同的权重。
7.max_feature:int, float, string or None, optional (default=None)
             可以是整数,浮点数,字符串或者None。默认为None。
             (1).如果是整数,则每次节点分裂只考虑max_feature个特征。
             (2).如果是浮点数(0到1之间),则每次分裂节点的时候只考虑int(max_features * n_features)个特征。
             (3).如果是字符串'auto',max_features=n_features。
             (4).如果是字符串'sqrt',max_features=sqrt(n_features)。
             (5).如果是字符串'log2',max_features=log2(n_features)。
             (6).如果是None,max_feature=n_feature。
8.random_state:int, RandomState instance or None, optional (default=None)
             (1).如果为整数,则它指定了随机数生成器的种子。
             (2).如果为RandomState实例,则指定了随机数生成器。
             (3).如果为None,则使用默认的随机数生成器。
9.max_leaf_nodes:int or None, optional (default=None)
             (1).如果为None,则叶子节点数量不限。
             (2).如果不为None,则max_depth被忽略。
10.min_impurity_decrease:float, optional (default=0.)
             如果节点的分裂导致不纯度的减少(分裂后样本比分裂前更加纯净)大于或等于min_impurity_decrease,则分裂该节点。
             个人理解这个参数应该是针对分类问题时才有意义。这里的不纯度应该是指基尼指数。
             回归生成树采用的是平方误差最小化策略。分类生成树采用的是基尼指数最小化策略。
             加权不纯度的减少量计算公式为:
             min_impurity_decrease=N_t / N * (impurity - N_t_R / N_t * right_impurity
                                - N_t_L / N_t * left_impurity)
             其中N是样本的总数,N_t是当前节点的样本数,N_t_L是分裂后左子节点的样本数,
             N_t_R是分裂后右子节点的样本数。impurity指当前节点的基尼指数,right_impurity指
             分裂后右子节点的基尼指数。left_impurity指分裂后左子节点的基尼指数。
11.min_impurity_split:float
             树生长过程中早停止的阈值。如果当前节点的不纯度高于阈值,节点将分裂,否则它是叶子节点。
             这个参数已经被弃用。用min_impurity_decrease代替了min_impurity_split。
12.presort: bool, optional (default=False)
             指定是否需要提前排序数据从而加速寻找最优切分的过程。设置为True时,对于大数据集
             会减慢总体的训练过程;但是对于一个小数据集或者设定了最大深度的情况下,会加速训练过程。
属性:
1.feature_importances_ : array of shape = [n_features]
             特征重要性。该值越高,该特征越重要。
             特征的重要性为该特征导致的评价准则的(标准化的)总减少量。它也被称为基尼的重要性
2.max_feature_:int
             max_features推断值。
3.n_features_:int
             执行fit的时候,特征的数量。
4.n_outputs_ : int
             执行fit的时候,输出的数量。
5.tree_ : 底层的Tree对象。
Notes:
控制树大小的参数的默认值(例如``max_depth``,``min_samples_leaf``等)导致完全成长和未剪枝的树,
这些树在某些数据集上可能表现很好。为减少内存消耗,应通过设置这些参数值来控制树的复杂度和大小。
方法:
1.fit(X,y):训练模型。
2.predict(X):预测。
'''
 
from sklearn.tree import DecisionTreeClassifier
'''
分类决策树
'''
DecisionTreeClassifier(criterion="gini",
                 splitter="best",
                 max_depth=None,
                 min_samples_split=2,
                 min_samples_leaf=1,
                 min_weight_fraction_leaf=0.,
                 max_features=None,
                 random_state=None,
                 max_leaf_nodes=None,
                 min_impurity_decrease=0.,
                 min_impurity_split=None,
                 class_weight=None,
                 presort=False)
'''
参数含义:
1.criterion:string, optional (default="gini")
            (1).criterion='gini',分裂节点时评价准则是Gini指数。
            (2).criterion='entropy',分裂节点时的评价指标是信息增益。
2.max_depth:int or None, optional (default=None)。指定树的最大深度。
            如果为None,表示树的深度不限。直到所有的叶子节点都是纯净的,即叶子节点
            中所有的样本点都属于同一个类别。或者每个叶子节点包含的样本数小于min_samples_split。
3.splitter:string, optional (default="best")。指定分裂节点时的策略。
           (1).splitter='best',表示选择最优的分裂策略。
           (2).splitter='random',表示选择最好的随机切分策略。
4.min_samples_split:int, float, optional (default=2)。表示分裂一个内部节点需要的做少样本数。
           (1).如果为整数,则min_samples_split就是最少样本数。
           (2).如果为浮点数(0到1之间),则每次分裂最少样本数为ceil(min_samples_split * n_samples)
5.min_samples_leaf: int, float, optional (default=1)。指定每个叶子节点需要的最少样本数。
           (1).如果为整数,则min_samples_split就是最少样本数。
           (2).如果为浮点数(0到1之间),则每个叶子节点最少样本数为ceil(min_samples_leaf * n_samples)
6.min_weight_fraction_leaf:float, optional (default=0.)
           指定叶子节点中样本的最小权重。
7.max_features:int, float, string or None, optional (default=None).
           搜寻最佳划分的时候考虑的特征数量。
           (1).如果为整数,每次分裂只考虑max_features个特征。
           (2).如果为浮点数(0到1之间),每次切分只考虑int(max_features * n_features)个特征。
           (3).如果为'auto'或者'sqrt',则每次切分只考虑sqrt(n_features)个特征
           (4).如果为'log2',则每次切分只考虑log2(n_features)个特征。
           (5).如果为None,则每次切分考虑n_features个特征。
           (6).如果已经考虑了max_features个特征,但还是没有找到一个有效的切分,那么还会继续寻找
           下一个特征,直到找到一个有效的切分为止。
8.random_state:int, RandomState instance or None, optional (default=None)
           (1).如果为整数,则它指定了随机数生成器的种子。
           (2).如果为RandomState实例,则指定了随机数生成器。
           (3).如果为None,则使用默认的随机数生成器。
9.max_leaf_nodes: int or None, optional (default=None)。指定了叶子节点的最大数量。
           (1).如果为None,叶子节点数量不限。
           (2).如果为整数,则max_depth被忽略。
10.min_impurity_decrease:float, optional (default=0.)
         如果节点的分裂导致不纯度的减少(分裂后样本比分裂前更加纯净)大于或等于min_impurity_decrease,则分裂该节点。
         加权不纯度的减少量计算公式为:
         min_impurity_decrease=N_t / N * (impurity - N_t_R / N_t * right_impurity
                            - N_t_L / N_t * left_impurity)
         其中N是样本的总数,N_t是当前节点的样本数,N_t_L是分裂后左子节点的样本数,
         N_t_R是分裂后右子节点的样本数。impurity指当前节点的基尼指数,right_impurity指
         分裂后右子节点的基尼指数。left_impurity指分裂后左子节点的基尼指数。
11.min_impurity_split:float
         树生长过程中早停止的阈值。如果当前节点的不纯度高于阈值,节点将分裂,否则它是叶子节点。
         这个参数已经被弃用。用min_impurity_decrease代替了min_impurity_split。
12.class_weight:dict, list of dicts, "balanced" or None, default=None
         类别权重的形式为{class_label: weight}
         (1).如果没有给出每个类别的权重,则每个类别的权重都为1。
         (2).如果class_weight='balanced',则分类的权重与样本中每个类别出现的频率成反比。
         计算公式为:n_samples / (n_classes * np.bincount(y))
         (3).如果sample_weight提供了样本权重(由fit方法提供),则这些权重都会乘以sample_weight。
13.presort:bool, optional (default=False)
        指定是否需要提前排序数据从而加速训练中寻找最优切分的过程。设置为True时,对于大数据集
        会减慢总体的训练过程;但是对于一个小数据集或者设定了最大深度的情况下,会加速训练过程。
属性:
1.classes_:array of shape = [n_classes] or a list of such arrays
        类别的标签值。
2.feature_importances_ : array of shape = [n_features]
        特征重要性。越高,特征越重要。
        特征的重要性为该特征导致的评价准则的(标准化的)总减少量。它也被称为基尼的重要性
3.max_features_ : int
        max_features的推断值。
4.n_classes_ : int or list
        类别的数量
5.n_features_ : int
        执行fit后,特征的数量
6.n_outputs_ : int
        执行fit后,输出的数量
7.tree_ : Tree object
        树对象,即底层的决策树。
方法:
1.fit(X,y):训练模型。
2.predict(X):预测
3.predict_log_poba(X):预测X为各个类别的概率对数值。
4.predict_proba(X):预测X为各个类别的概率值。
'''

python绘制决策树

# -*- coding: utf-8 -*-
"""
    author:Rita
    date:2019/3/5
"""

import matplotlib.pyplot as plt

decisionNode = dict(boxstyle="sawtooth", fc="0.8")
leafNode = dict(boxstyle="round4", fc="0.8")
arrow_args = dict(arrowstyle="<-")


# 计算树的叶子节点数量
def getNumLeafs(myTree):
    numLeafs = 0
    firstStr = myTree.keys()[0]
    secondDict = myTree[firstStr]
    for key in secondDict.keys():
        if type(secondDict[key]).__name__ == 'dict':
            numLeafs += getNumLeafs(secondDict[key])
        else:
            numLeafs += 1
    return numLeafs


# 计算树的最大深度
def getTreeDepth(myTree):
    maxDepth = 0
    firstStr = myTree.keys()[0]
    secondDict = myTree[firstStr]
    for key in secondDict.keys():
        if type(secondDict[key]).__name__ == 'dict':
            thisDepth = 1 + getTreeDepth(secondDict[key])
        else:
            thisDepth = 1
        if thisDepth > maxDepth:
            maxDepth = thisDepth
    return maxDepth


# 画节点
def plotNode(nodeTxt, centerPt, parentPt, nodeType):
    createPlot.ax1.annotate(nodeTxt, xy=parentPt, xycoords='axes fraction', xytext=centerPt, textcoords='axes fraction',
                            va="center", ha="center", bbox=nodeType, arrowprops=arrow_args)


# 画箭头上的文字
def plotMidText(cntrPt, parentPt, txtString):
    lens = len(txtString)
    xMid = (parentPt[0] + cntrPt[0]) / 2.0 - lens * 0.002
    yMid = (parentPt[1] + cntrPt[1]) / 2.0
    createPlot.ax1.text(xMid, yMid, txtString)


def plotTree(myTree, parentPt, nodeTxt):
    numLeafs = getNumLeafs(myTree)
    depth = getTreeDepth(myTree)
    firstStr = myTree.keys()[0]
    cntrPt = (plotTree.x0ff + (1.0 + float(numLeafs)) / 2.0 / plotTree.totalW, plotTree.y0ff)
    plotMidText(cntrPt, parentPt, nodeTxt)
    plotNode(firstStr, cntrPt, parentPt, decisionNode)
    secondDict = myTree[firstStr]
    plotTree.y0ff = plotTree.y0ff - 1.0 / plotTree.totalD
    for key in secondDict.keys():
        if type(secondDict[key]).__name__ == 'dict':
            plotTree(secondDict[key], cntrPt, str(key))
        else:
            plotTree.x0ff = plotTree.x0ff + 1.0 / plotTree.totalW
            plotNode(secondDict[key], (plotTree.x0ff, plotTree.y0ff), cntrPt, leafNode)
            plotMidText((plotTree.x0ff, plotTree.y0ff), cntrPt, str(key))
    plotTree.y0ff = plotTree.y0ff + 1.0 / plotTree.totalD


def createPlot(inTree):
    fig = plt.figure(1, facecolor='white')
    fig.clf()
    axprops = dict(xticks=[], yticks=[])
    createPlot.ax1 = plt.subplot(111, frameon=False, **axprops)
    plotTree.totalW = float(getNumLeafs(inTree))
    plotTree.totalD = float(getTreeDepth(inTree))
    plotTree.x0ff = -0.5 / plotTree.totalW
    plotTree.y0ff = 1.0
    plotTree(inTree, (0.5, 1.0), '')
    plt.show()


###############测试代码
tree = {'navel': {'even': 0L,
                  'little_sinking': {'root': {'curl_up': 0L,
                                              'little_curl_up': {'color': {'black': {'texture': {'blur': 1L,
                                                                                                 'distinct': 0L,
                                                                                                 'little_blur': 1L}},
                                                                           'dark_green': 1L,
                                                                           'light_white': 1L}},
                                              'stiff': 1L}},
                  'sinking': {'color': {'black': 1L, 'dark_green': 1L, 'light_white': 0L}}}}
createPlot(tree)

在这里插入图片描述
参考:
解释机器学习中的熵、联合熵、条件熵、相对熵和交叉熵
最大熵模型
决策树中基尼不纯度初步理解
机器学习之-常见决策树算法
回归树的原理及其 Python 实现
Regression Tree 回归树
决策树如何防止过拟合
决策树的过拟合问题
数据挖掘导论
机器学习sklearn中决策树模型参数释义
实现决策树画图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值