精华内容
下载资源
问答
  • Cart决策树算法

    2020-01-19 16:51:30
    Cart(Classification And Regression Tree)决策树作为决策树算法分支的一类,是一类非线性的模型,从CART决策树的全称不难看出这是一类可用于分类与回归的决策树。 CART算法主要由以下两步组成: 决策树生成:...

    Cart(Classification And Regression Tree)决策树作为决策树算法分支的一条,是一类非线性的模型,从CART决策树的全称不难看出这是一类可用于分类与回归的决策树。

    CART算法主要由以下两步组成:

    1. 决策树生成:基于训练数据集生成决策树,生成的决策树要尽量大。
    2. 决策树剪枝:用验证数据集对已生成的树进行剪枝并选择最优子树,这时用损失函数最小作为剪枝的标准。

    CART决策树生成

    与多叉决策树ID3,C4.5不同,CART决策树是一棵递归建树的二叉树,,对回归树用平方误差最小化准则,对分类树用基尼系数最小化准则,进行特征选择,生成二叉树。

    CART回归决策树生成

    输入:训练集D
    输出:回归决策树f(x)

    1. 记X为输入数据,Y为输出值,且Y为连续变量,给定训练数据集:

      D={(x1,y1),(x2,y2),,(xN,yN)}D=\left\{\left(x_{1}, y_{1}\right),\left(x_{2}, y_{2}\right), \cdots,\left(x_{N}, y_{N}\right)\right\}

    2. 选择第j个变量xj及其取值s作为切分变量和切分点,并定义两个区域: R1(j,s)={xxjs},R2(j,s)={xxj>s}R_{1}(j, s)=\left\{x | x_{j} \leq s\right\}, \quad R_{2}(j, s)=\left\{x | x_{j}>s\right\}
      切分点的选取基于最小平方误差准则: j,s=argminj,s[minc1xiR1(j,s)(yic1)2+minc2xiR2(j,s)(yic2)2]j, s=\arg \min _{j, s}\left[\min _{c_{1}} \sum_{x_{i} \in R_{1}(j, s)}\left(y_{i}-c_{1}\right)^{2}+\min _{c_{2}} \sum_{x_{i} \in R_{2}(j, s)}\left(y_{i}-c_{2}\right)^{2}\right] 其中c1,c2分别为R1,R2区间内的输出平均值,即:
      cm=1NxiRm(j,s)yi,m=1,2c_{m}=\frac{1}{N} \sum_{x_{i} \in R_{m}(j, s)} y_{i}, \quad m=1,2

    3. 对切分好的区域继续进行切分,依然切分为两部分,并基于最小平方误差计算切分点。

    4. 重复3操作直至无法继续切分,最后将空间划分为M个区域R1,R2,⋯,RM ,在每个区域上的输出为cm,m=1,2,⋯,M,CART回归树可表示为:
      f(x)=m=1Mc^mI(xRm)f(x)=\sum_{m=1}^{M} \hat{c}_{m} I\left(x \in R_{m}\right)

    总结:此方法的复杂度较高,尤其在每次寻找切分点时,需要遍历当前所有特征的所有可能取值,假如总共有F个特征,每个特征有N个取值,生成的决策树有S个内部节点,则该算法的时间复杂度为:O(FNS)\mathbf{O}\left(\mathbf{F}^{\star} \mathbf{N}^{\star} \mathbf{S}\right)

    CART分类决策树生成

    输入:训练数据集D,特征A,阈值ε​
    输出:分类决策树

    1. 设训练集为D,共有k个不同类别对每一个特征A,对其可能取的每个值a,根据样本点对A=a的测试为“是”或“否”将D分割成D1和D2两部分,并计算Gini(D,A):
      D1={(x,y)A(x)=a},D2=DD1D_{1}=\{(x, y) | A(x)=a\}, \quad D_{2}=D-D_{1}
      Gini(D,A)=D1DGini(D1)+D2DGini(D2)\operatorname{Gini}(D, A)=\frac{\left|D_{1}\right|}{|D|} \operatorname{Gini}\left(D_{1}\right)+\frac{\left|D_{2}\right|}{|D|} \operatorname{Gini}\left(D_{2}\right)
      其中Gini(D)=1k=1K(CkD)2\operatorname{Gini}(D)=1-\sum_{k=1}^{K}\left(\frac{\left|C_{k}\right|}{|D|}\right)^{2}为基尼指数,|Ck|表示属于第k类的样本个数,|D|表示数据集样本总数,基尼指数Gini(D)表示集合D的不确定性,基尼指数Gini(D,A)表示经A=a分割后集合D的不确定性。基尼指数值越大,样本集合的不确定性也越大,这一点与熵类似。
    2. 与回归树相类似,选取使得基尼指数Gini(D,A)最小的特征及其对应的切分点(如A=a)作为最优特征与最优切分点。依此从现结点生成两个子结点,将训练数据集依特征分配到两个子结点中去。
    3. 对2中分配好的节点继续进行1,2操作,直至满足停止条件(算法停止计算的条件是结点中的样本个数小于预定阈值,或样本集的基尼指数小于预定阈值,或者没有更多特征)。
    4. 生成分类决策树

    总结:CART分类决策树复杂度计算与回归决策树类似

    CART决策树剪枝

    剪枝目的:决策树是一类很容易过拟合的非线性机器学习模型,合理的剪枝可以有效的降低其过拟合程度

    大致思路:对于原始的CART树T0,先剪去一棵子树,生成子树T1,然后再从A1剪去一棵子树生成T2,直到最后剪到只剩一个根结点的子树Tn,于是得到了T0-TN一共n+1棵子树。
    然后再用n+1棵子树预测独立的验证数据集,谁的误差最小就选谁

    输入:CART决策树T0
    输出:最优决策树Tα​
    记决策树字子数序列为T0,T1,…,Tn

    1. 设k=0,T=T0

    2. 设α=+∞

    3. 自下而上地对各内部结点t计算C(Tt),|Tt|,以及
      g(t)=C(t)C(Tt)Tt1g(t)=\frac{C(t)-C\left(T_{t}\right)}{\left|T_{t}\right|-1}
      α=min(α,g(t))\alpha=\min (\alpha, g(t))
      其中,Tt​表示以t​为根结点的子树,C(Tt)​是对训练数据的预测误差,|Tt|​是Tt​的叶结点个数。g(t) 为裁剪阈值,每次与之前所存的最小的g(t)对比

    4. 自下而上地访问内部结点t​,如果有g(t)=α​,则进行剪枝,并对叶结点t​以多数表决法决定其类别,得到树T​

    5. 设k=k+1,αk=α,Tk=T

    6. 如果T​不是由根结点单独构成的树,则回到步骤4.

    7. 采用交叉验证法在子树序列T0,T1,⋯,Tn​中选取最优子树Tα​

    展开全文
  • CART算法步骤 特征选择; 递归建立决策树决策树剪枝; CART分类树算法 ID3中使用了信息增益选择特征,增益大优先选择。C4.5中,采用信息增益率选择特征,减少因特征值多导致信息增益大的问题。CART分类树算法...

    ID3和C4.5算法,生成的决策树是多叉树,只能处理分类不能处理回归。而CART(classification and regression tree)分类回归树算法,既可用于分类也可用于回归。 分类树的输出是样本的类别, 回归树的输出是一个实数。

    CART算法步骤

    1. 特征选择;
    2. 递归建立决策树;
    3. 决策树剪枝;

    CART分类树算法

    ID3中使用了信息增益选择特征,增益大优先选择。C4.5中,采用信息增益率选择特征,减少因特征值多导致信息增益大的问题。CART分类树算法使用基尼系数选择特征,基尼系数代表了模型的不纯度,基尼系数越小,不纯度越低,特征越好。这和信息增益(率)相反。

    基尼系数

    数据集D的纯度可用基尼值来度量
    Gini(D)=i=1np(xi)(1p(xi))=1i=1np(xi)2 \begin{aligned}Gini(D)&=\sum_{i=1}^{n}{p(x_i)*(1-p(x_i))}\\ &=1-\sum_{i=1}^{n}{{p(x_i)}^2}\end{aligned}
    其中,p(xi)p(x_i)是分类xix_i出现的概率,n是分类的数目。Gini(D)反映了从数据集D中随机抽取两个样本,其类别标记不一致的概率。因此,Gini(D)越小,则数据集D的纯度越高

    对于样本D,个数为|D|,根据特征A 是否取某一可能值a,把样本D分成两部分D1D2D_1和D_2 。所以CART分类树算法建立起来的是二叉树,而不是多叉树。
    D1={(x,y)DA(x)=a},D2=DD1 D_1= {\{(x,y)∈D|A(x)=a\}},D_2=D−D_1
    在属性A的条件下,样本D的基尼系数定义为
    GiniIndex(DA=a)=D1DGini(D1)+D2DGini(D2) GiniIndex(D|A=a)=\frac{|D_1|}{|D|}Gini(D_1)+\frac{|D_2|}{|D|}Gini(D_2)

    对连续特征和离散特征的处理

    连续特征

    与C4.5思想相同,都是将连续的特征离散化。区别在选择划分点时,C4.5是信息增益率,CART是基尼系数。

    具体思路:

    1. m个样本的连续特征A有m个值,从小到大排列a1,a2,...,ama_1,a_2,...,a_m,则CART取相邻两样本值的平均数做划分点,一共有m-1个,其中第i个划分点Ti表示为:Ti=(ai+ai+1)/2T_i=(a_i+a_{i+1})/2
    2. 分别计算以这m-1个点作为二元分类点时的基尼系数。选择基尼系数最小的点为该连续特征的二元离散分类点。比如取到的基尼系数最小的点为ata_t,则小于ata_t的值为类别1,大于ata_t的值为类别2,这样就做到了连续特征的离散化。

    注意的是,与ID3、C4.5处理离散属性不同的是,如果当前节点为连续属性,则该属性在后面还可以参与子节点的产生选择过程。

    离散特征

    思路:不停的二分离散特征。

    在ID3、C4.5,特征A被选取建立决策树节点,如果它有3个类别A1,A2,A3,我们会在决策树上建立一个三叉点,这样决策树是多叉树,而且离散特征只会参与一次节点的建立。

    CART采用的是不停的二分,且一个特征可能会参与多次节点的建立。CART会考虑把特征A分成{A1}\{A_1\}{A2,A3}{A2}{A1,A3}{A3}{A1,A2}\{A_2,A_3\}、\{A_2\}和\{A_1,A_3\}、\{A_3\}和\{A_1,A_2\}三种情况,找到基尼系数最小的组合,比如{A2}\{A_2\}{A1,A3}\{A_1,A_3\},然后建立二叉树节点,一个节点是A2A_2对应的样本,另一个节点是对{A1,A3}\{A_1,A_3\}对应的样本。由于这次没有把特征A的取值完全分开,后面还有机会对子节点继续选择特征A划分A1A_1A3A_3

    例子

    数据集的属性有3个,分别是有房情况,婚姻状况和年收入,其中有房情况和婚姻状况是离散的取值,而年收入是连续的取值。拖欠贷款者属于分类的结果。

    在这里插入图片描述

    对于有房情况这个属性,它是离散型数据,那么按照它划分后的Gini系数计算如下

    在这里插入图片描述

    对于婚姻状况属性,它也是离散型数据,它的取值有3种,按照每种属性值分裂后Gini系数计算如下

    在这里插入图片描述

    年收入属性,它的取值是连续的,那么连续的取值采用分裂点进行分裂。如下

    在这里插入图片描述

    根据这样的分裂规则CART算法就能完成建树过程 。

    建立CART分类树步骤

    输入:训练集D,基尼系数的阈值,切分的最少样本个数阈值

    输出:分类树T

    算法从根节点开始,用训练集递归建立CART分类树。

    1. 对于当前节点的数据集为D,如果样本个数小于阈值或没有特征,则返回决策子树,当前节点停止递归;
    2. 计算样本集D的基尼系数,如果基尼系数小于阈值,则返回决策树子树,当前节点停止递归 ;
    3. 计算当前节点现有各个特征的各个值的基尼指数,
    4. 在计算出来的各个特征的各个值的基尼系数中,选择基尼系数最小的特征A及其对应的取值a作为最优特征和最优切分点。 然后根据最优特征和最优切分点,将本节点的数据集划分成两部分D1D_1D2D_2,同时生成当前节点的两个子节点,左节点的数据集为D1D_1,右节点的数据集为D2D_2
    5. 对左右的子节点递归调用1-4步,生成CART分类树;

    对生成的CART分类树做预测时,假如测试集里的样本落到了某个叶子节点,而该节点里有多个训练样本。则该测试样本的类别为这个叶子节点里概率最大的类别。

    剪枝

    当分类回归树划分得太细时,会对噪声数据产生过拟合,因此要通过剪枝来解决。剪枝又分为前剪枝和后剪枝,前剪枝是指在构造树的过程中就知道哪些节点可以剪掉 。 后剪枝是指构造出完整的决策树之后再来考查哪些子树可以剪掉。

    在分类回归树中可以使用的后剪枝方法有多种,比如:代价复杂性剪枝、最小误差剪枝、悲观误差剪枝等等。这里只介绍代价复杂性剪枝法

    对于分类回归树中的每一个非叶子节点计算它的表面误差率增益值α
    α=C(t)C(Tt)Tt1 \alpha = \frac{C(t)-C(T_t)}{|T_t|-1}
    Tt|T_t|:子树中包含的叶子节点个数

    C(t):以t为单节点树的误差代价,该节点被剪枝
    C(t)=r(t)p(t) C(t)=r(t)*p(t)
    r(t):节点t的误差率

    p(t):节点t上的数据占所有户数的比例

    C(Tt)C(T_t)是以t为根节点的子树TtT_t的误差代价,如果该节点不被剪枝, 它等于子树TtT_t上所有叶子节点的误差代价之和。

    比如有个非叶子节点T4如图所示:

    在这里插入图片描述

    已知所有的数据总共有60条,则节点T4的节点误差代价为:
    C(t)=r(t)p(t)=7161660=760 C(t)=r(t)*p(t)=\frac{7}{16}*\frac{16}{60}=\frac{7}{60}
    子树误差代价为:
    C(Tt)=C(i)=25560+02260+39960=560 C(T_t)=\sum{C(i)}=\frac{2}{5}*\frac{5}{60}+\frac{0}{2}*\frac{2}{60}+\frac{3}{9}*\frac{9}{60}=\frac{5}{60}
    以T4为根节点的子树上叶子节点有3个,则
    α=7/605/6031=160 \alpha=\frac{7/60-5/60}{3-1}=\frac{1}{60}
    找到αα值最小的非叶子节点,令其左、右子节点为NULL。当多个非叶子节点的α值同时达到最小时,取Tt|T_t|最大的进行剪枝。

    总结

    算法 树结构 支持模型 特征选择 连续值处理 缺失值处理 剪枝
    ID3 多叉树 分类 信息增益 不支持 不支持 不支持
    C4.5 多叉树 分类 信息增益率 支持 支持 支持
    CART 二叉树 分类、回归 基尼系数、平方误差和 支持 支持 支持

    相关链接

    书籍:《机器学习实战》、周志华的西瓜书《机器学习》

    例子参考链接

    剪枝参考链接

    ID3算法

    C4.5算法

    CART回归树算法

    展开全文
  • CART决策树算法浅谈(回归树部分)

    千次阅读 2017-08-24 21:30:25
    CART 回归树算法浅谈

    近日受小C同学的影响,开始慢慢培养写博客的习惯,“开坑之作”(之前那篇请无视~~)就打算谈谈最近研究的CART。鄙人不才,为了写这篇博客参考了不少资料,若写的有不正确的地方,还请各位大牛指正。
    套话说完了,正式开始吧。CART全名为分类与回归树,意指该模型可以同时处理分类与回归问题。对于给定的训练数据集,CART通过最小化数据集的GINI系数(分类树)或者基于最小二乘准则最小化输入与输出的总均方误差(回归树)实现机器学习任务,本文首先介绍CART在回归问题中的应用。回归树的生成可分为两步—树的生成和剪枝。

    1. 树的生成

    对于给定的训练数据集T={(x1,y1),(x2,y2),...(xN,yN)},回归树希望按照某几个特征对数据集进行递归式划分以形成二叉树,使得划分后的数据集叶子结点的输出尽可能接近训练样本的y值。这个过程主要涉及到分裂数据集的特征选择和树的递归生成。就特征选择而言,若设选择数据集T的j号特征某个分量s作为分割的阈值,将数据集分为R1={x|xjs},R2={x|xj>s}两部分,则分割后的数据集与实际y值的均方误差可表示为:

    min[minxiRii=1N(yif(xi))2+minxiRii=1N(yif(xi))2]

    其中,f(xi)代表模型的输出值,他越接近实际值说明模型精度越高,我们考虑里面的均方误差项M(f(xi))=minxiRii=1N(yif(xi))2,为求得合适的f(xi),求偏导并令其等于0,有
    Mf(xi)=2i=1N(yif(xi))=0f(xi)=i=1NyiN

    即在单个集合内,最优的f(xi)为集合内数据对应y值的平均值。
    回到具体的CART树训练过程中,由于CART的生成是每次基于当前已经分好的数据集,求解最优的分割准则,且每次将数据分为两份,则原始的优化目标变为在每次划分数据集过程中使用如下准则寻找最优的划分
    min[minc1i=1N(yic1)2+minc2i=1N(yic2)2]

    c1=i=1NR1yiNR1,c2=i=1NR2yiNR2

    具体来说,CART将按照每个特征,每个分量将数据集分为大于该分量和小于该分量的部分,并计算对应y值的平均,计算均方误差函数值在其中寻找值最小的那个分量,并将其作为分类准则。重复该寻找流程直到数据集空或者划分前后均方误差下降值小于一定阈值为止(初始阈值可设为inf)。
    CART树具体生成步骤如下:
    Step1:获得训练数据集,根据数据集第一个特征的第一个分量将数据集分为大于该分量和小于该分量的两个数据集R1和R2,其中R1={x|Rjs},R2={x|Rj>s}
    Step2:根据两个数据集对应y值的平均获得c1和c2,分别计算两个数据集的平均绝对误差(其实就是各个数据集y值的总均方差)。
    Step3:重复Step1~2,遍历整个数据集的所有特征所有分量,获得均方误差值的矩阵。
    Step4:根据矩阵寻找均方误差最小的分割方案,将该分割点作为树的节点,将分割后的数据集分别赋值给该节点左子树和右子树。
    Step5:重复步骤1~4,递归地将数据集分割为更小的部分,直到总均方差的下降值小于某阈值或者数据集中只剩下一类数据为止。
    可以看到,CART回归树的生成是一个贪心选择最优分割点的过程,这种贪心策略在一定程度上使得最开始生成的CART树具有很多缺点,这表现在树容易将噪声也拟合进去,出现过拟合,以及训练容易陷入局部最优等。为此,需要在树生成后进行一定的处理,这就是剪枝的目的。

    2. 树的剪枝

    如果生成的CART树枝条太多,容易把数据集中的一些噪声也拟合进去,这时候就需要减去一些枝条,防止CART树出现过拟合。剪枝又分为预剪枝和后剪枝。后剪枝需要一定数据,因此,实际使用CART树时,常常将训练数据分为训练集和剪枝的数据集。
    预剪枝通过调整树停止生长的策略,如提前终止树生长(通过调整均方误差下降的最小值实现)等可实现。这种方法不需要给定数据集,但是受到建模者所给参数的影响太大,有较大弊病。
    后剪枝的具体做法是,将数据根据训练好的树模型将数据集递归地分割到叶子结点,然后考虑减去叶子和不剪去叶子两种情况下数据集的均方误差值,如果剪枝使得该值变小,则剪之,否则放弃。遍历所有结点,剪去所有冗余的枝条,就实现了后剪枝。
    预剪枝和后剪枝在实际实现CART算法时常常结合使用,最大可能地避免树的过拟合。

    3. 基于Python的CART回归树模型实现

    基于Python的CART回归树模型实现参考了《机器学习实战》一书。使用numpy和pygraphviz绘图包。pygraphviz安装并不是直接pip install就能搞定的,具体安装步骤参见http://www.cnblogs.com/AimeeKing/p/5021675.html
    主要包含了树的创建函数createTree、根据特征的分量将数据集分裂的函数splitData、选择最优分裂点的函数chooseSplit、剪枝函数cutBranches、画树函数drawTree等。
    splitData函数根据选定的特征的目标分量thres将数据集分为该特征数值大于thres和小于thres的两部分数据。

    def splitData(data, feature, thres):
        mat0 = data[np.nonzero(data[:, feature] > thres)[0], :]
        mat1 = data[np.nonzero(data[:, feature] <= thres)[0], :]
        return mat0, mat1

    chooseSplit函数遍历所有特征的所有分量,寻找最合适的数据分裂方案

    def chooseSplit(data, ops=1):
        feature = data[:, 0:-1]
        # 获得特征数目以及样本数
        minFunc = []
        oriVal = float(np.var(data[:, -1]) * len(data[:, -1]))
        sampleNum, featureNum = map(int, np.shape(feature))
        if len(np.unique(np.array(feature))) == 1:  # 剩余样本都一样
            return None, np.mean(data[:, -1])  # 既然都一样,拿哪个特征无所谓
        for i in range(featureNum):
            tempFeature = feature[:, i]  # 获得切分数据集
            FeatureFunc = []
            for thres in tempFeature:
                # 拆分标签集
                subMat1, subMat2 = splitData(data, i, thres)
                # 获得标签便于计算目标函数
                y1, y2 = [subMat1[:, -1], subMat2[:, -1]]
                # 处理一下空集的情况
                if len(y2) == 0:
                    FeatureFunc.append(np.var(y1) * len(y1))
                elif len(y1) == 0:
                    FeatureFunc.append(np.var(y2) * len(y2))
                else:
                    FeatureFunc.append(np.var(y1) * len(y1) + np.var(y2) * len(y2))
            minFunc.append(FeatureFunc)
        # 寻找最优分割特征与数值
        locFeature, locVal = np.where(minFunc == np.amin(minFunc))
        # 下降值小于ops,不再生长树
        if (oriVal - np.amin(minFunc)) < ops:
            return None, float(np.var(data[:, -1]) * len(data[:, -1]))
        spVal = float(data[locVal, locFeature[0]])  # 用于分割数据的特征
        return locFeature[0], spVal

    splitData函数用于树的创建,首先选择当前数据集的最优分裂方案,如果只有一个数据点就返回,否则创建节点,并分裂数据集,将两个数据集递归地传给节点的左右子树继续分裂。最后返回生成的树。

    # 创建树,生成的树叶子结点没有左右子树!!!!
    def createTree(data, ops=1):
        # 选中最优的分割
        name, val = chooseSplit(data)
        if name is None:
            return val  # 直接返回
        tree = {'node': name, 'val': val}
        # 递归建树
        ldata, rdata = splitData(data, name, val)
        tree['rchild'] = createTree(rdata, ops)
        tree['lchild'] = createTree(ldata, ops)
        return tree

    cutBranches用于树的后剪枝,这里需要一个判断节点是否为叶子结点的函数,由于Python是借助字典实现树结构的,所以可以判断当前结点类型是否为dict来实现。如果左枝条或者右枝条不为叶子结点,则按照给定的树模型分割数据集,递归剪枝过程。当左右节点为叶子结点时,就先按照叶子结点的要求分割一次数据集计算y的均方误差,再计算不剪枝时的均方误差,比较判断是否有必要剪枝。

    # 后剪枝
    def cutBranches(tree, testData=[]):
        if len(testData) == 0:  # 没有测试数据
            print "没有测试数据,不能剪枝!"
        # 左只或右枝不为叶子,则进行数据分割
        if not (isLeaf(tree['lchild'])) or not (isLeaf(tree['rchild'])):
            ldata, rdata = splitData(testData, tree['node'], tree['val'])
        # 左枝不为叶子
        if not (isLeaf(tree['lchild'])):
            tree['lchild'] = cutBranches(tree['lchild'], ldata)
        # 右枝不为叶子
        if not isLeaf(tree['rchild']):
            tree['rchild'] = cutBranches(tree['rchild'], rdata)
        # 两边都是树叶,开始判断要不要减支
        if isLeaf(tree['lchild']) and isLeaf(tree['rchild']):
            ldata, rdata = splitData(testData, tree['node'], tree['val'])
            # 不进行剪枝的目标函数值
            noMerge = sum(np.power(ldata[:, -1] - tree['lchild'], 2)) + \
                      sum(np.power(rdata[:, -1] - tree['rchild'], 2))
            treeMean = 0.5 * (tree['lchild'] + tree['rchild'])
            Merge = sum(np.power(ldata[:, -1] - treeMean, 2))
            # 判断是否要剪枝
            if Merge < noMerge:
                print "merging..."
                return treeMean  # 返回左右子树平均值实现合并
            else:
                return tree
        else:
            return tree

    下图为剪枝之前CART生成的树,可以看到,生成的树臃肿,带有大量的叶子结点。如果不设置ops=1,则该树将会变得更加庞大臃肿,它甚至可能为每一个样本生成一个节点。

    下图为经过后剪枝之后的CART树,多余的枝条被减去,整棵树较之前显得更为小巧。说明在一定数据集的支撑下,后剪枝能够起到一定效果。
    这里写图片描述
    画树函数drawTree则判断节点是否有lchild属性或者rchild属性,如果有,则使用pygraphviz添加从节点到左右子树的节点然后递归调用画树函数,否则只添加有向边。

    # 画树
    def drawTree(graph, tree):
        # 递归画树
        if tree.has_key('lchild'):
            if not isLeaf(tree['lchild']):
                graph.add_edge(tree['val'], tree['lchild']['val'])
                drawTree(graph, tree['lchild'])
            else:
                graph.add_edge(tree['val'], tree['lchild'])
        if tree.has_key('rchild'):
            if not isLeaf(tree['rchild']):
                graph.add_edge(tree['val'], tree['rchild']['val'])
                drawTree(graph, tree['rchild'])
            else:
                graph.add_edge(tree['val'], tree['rchild'])
        drawTree(newGraph, tree)
        newGraph.layout(prog='dot')
        newGraph.draw('treeP.jpg')

    代码和相关数据我传了一份供交流参考。地址:https://github.com/FlyingRoastDuck/CART_REG

    参考文献

    [1] 李航. 统计学习方法 [M]. 北京:清华大学出版社, 2012: 65-70.
    [2] Peter H. 机器学习实战 [M]. 北京:人民邮电出版社,2013: 161-170.

    展开全文
  • 上一篇博客中介绍了ID3和C4.5两种决策树算法,这两种决策树都只能用于分类问题,而本文要说的CART(classification and regression tree)决策树不仅能用于分类问题,也能用于回归问题。 与ID3算法和C4.5算法相比,...

    注:本系列所有博客将持续更新并发布在githubgitee上,您可以通过github、gitee下载本系列所有文章笔记文件。

    1 引言

    上一篇博客中介绍了ID3和C4.5两种决策树算法,这两种决策树都只能用于分类问题,而本文要说的CART(classification and regression tree)决策树不仅能用于分类问题,也能用于回归问题。

    与ID3算法和C4.5算法相比,CART 还有个特性就是其所有非叶子结点都只有两个子树,也就是说在根据特征属性分裂数据集时,无论该特征属性有多少个可能取值,都只有两种选择——‘是’和‘否’,以上文中判断是否是程序员数据集为例,如果根据近视程度进行分裂,可以将数据集分为{‘轻微’}和{‘中等’,‘严重’}两个数据集(当然也可以是其两种组合)然后在进一步迭代中进一步细化分数据集。

    下面,我们分别说说CART算法如何解决分类问题和回归问题。

    2 分类问题

    对于分类问题,CART算法采用基尼指数作为最优分裂特征属性选择标准。

    先来说说基尼指数,与熵一样,基尼指数越小则数据集不确定性越小,代表着数据集纯度越高。给定数据集$X$包含$L$个分类,那么数据集$X$的基尼指数为:

     $$Gini(X) = \sum\limits_l^L {\frac{{|{X_l}|}}{{|X|}}(1 - \frac{{|{X_l}|}}{{|X|}})}  = 1 - {\sum\limits_{l = 1}^L {\left( {\frac{{|{X_l}|}}{{|X|}}} \right)} ^2}$$

    假设$A$是数据集$X$中包含若干个可能取值的一个特征属性,$a$是$A$的其中一个可能取值,将数据集$X$按照$a$进行划分,就可以分为两个数据集,分别是${X_1} = \left\{ {x \in X|{x_A} = a} \right\}$和${X_2} = \left\{ {x \in X|{x_A} \ne a} \right\}$,那么在特征$A$下,集合$X$的基尼指数为:

    $$Gini(X,A) = \left| {\frac{{{X_1}}}{X}} \right|Gini({X_1}) + \left| {\frac{{{X_2}}}{X}} \right|Gini({X_2})$$

    接下来,我们通过实例演示如何应用基尼指数选择最优分裂特征属性。还是使用上篇博客中介绍ID3算法时使用过的数据集,如下所示。先来计算三个特征属性各个可能取值的基尼指数。

    对属性$A$的“穿格子衬衫”这个值计算基尼指数:

    $$Gini(X,{A_1}) = \frac{5}{{10}} \times \left\{ {2 \times \frac{4}{5} \times \frac{1}{5}} \right\} + \frac{5}{{10}} \times \left\{ {2 \times \frac{3}{5} \times \frac{2}{5}} \right\} = 0.4$$

    对属性$A$的“不穿格子衬衫”这个值计算基尼指数,由于只有两个属性,无论按照哪个属性来计算结果都一样,所以:

    $$Gini(X,{A_2}){\text{ = }}Gini(X,{A_1}) = 0.4$$

    对属性$B$的“严重”这个值计算基尼指数:

    $$Gini(X,{B_1}) = \frac{3}{{10}} \times \left\{ {2 \times \frac{2}{3} \times \frac{1}{3}} \right\} + \frac{7}{{10}} \times \left\{ {2 \times \frac{5}{7} \times \frac{2}{7}} \right\} = 0.42$$

    对属性$B$的“中等”这个值计算基尼指数:

    $$Gini(X,{B_2}) = \frac{4}{{10}} \times \left\{ {2 \times \frac{4}{4} \times \frac{0}{4}} \right\} + \frac{6}{{10}} \times \left\{ {2 \times \frac{3}{6} \times \frac{3}{6}} \right\} = 0.3$$

    对属性$B$的“轻微”这个值计算基尼指数:

    $$Gini(X,{B_3}) = \frac{3}{{10}} \times \left\{ {2 \times \frac{1}{3} \times \frac{2}{3}} \right\} + \frac{7}{{10}} \times \left\{ {2 \times \frac{6}{7} \times \frac{1}{7}} \right\} = 0.46$$

    对属性$C$的“严重”这个值计算基尼指数:

    $$Gini(X,{C_1}) = \frac{3}{{10}} \times \left\{ {2 \times \frac{0}{3} \times \frac{3}{3}} \right\} + \frac{7}{{10}} \times \left\{ {2 \times \frac{4}{7} \times \frac{3}{7}} \right\} = 0.34$$

    对属性$C$的“中等”这个值计算基尼指数:

    $$Gini(X,{C_2}) = \frac{3}{{10}} \times \left\{ {2 \times \frac{1}{3} \times \frac{2}{3}} \right\} + \frac{7}{{10}} \times \left\{ {2 \times \frac{5}{7} \times \frac{2}{7}} \right\} = 0.42$$

    对属性$C$的“轻微”这个值计算基尼指数:

    $$Gini(X,{C_3}) = \frac{3}{{10}} \times \left\{ {2 \times \frac{1}{3} \times \frac{2}{3}} \right\} + \frac{7}{{10}} \times \left\{ {2 \times \frac{6}{7} \times \frac{1}{7}} \right\} = 0.46$$

    可见,属性$B$的“中等“取值时具有最小的基尼指数,所以这个值作为当前数据集的最优分裂特征属性值。分裂后,可以获得两个数据集,对获得的数据集继续计算基尼指数,选择最优分裂特征属性值,如此迭代形成一颗完整的决策树。

    对于连续型特征属性,可以参照C4.5算法对连续型特征属性的处理方法,只不过在CART算法中是计算基尼指数。

    3 回归问题

    此时,我们研究的已经是回归问题了(关于回归与分类,在讨论线性回归算法的时候已经分析过,如果还不清楚,传送门走起)所以,请转变思路,对于任意一个$x \in X$,经过决策树后的输出$f(x)$的可能取值已经不再像之前的分类决策树那样,$f(x)$的取值只可能是在$X$中出现过的那几种取值,回归树最后的输出$f(x)$可能是之前没有出现过的,甚至连可能值的个数都不固定。所以,对于回归树,首先解决的问题就是如何确定$f(x)$的可能值。

    对于数据集$X$,假设我们在其特征属性$A$上早上一个值$a$将数据集划分成两类:

    $${X_1} = \{ x|{x_A} \leqslant a\} $$

    $${X_2} = \{ x|{x_A} > a\} $$

    在这两个类上的输出值$f(x)$分别为${c_1}$和${c_2}$,那么根据特征属性$A$的值$a$对$X$进行划分,所产生的总误差是:

    $$Los{s_{A,a}} = \sum\limits_{x \in {X_1}} {(y - {c_1}} {)^2} + \sum\limits_{x \in {X_2}} {(y - {c_2}} {)^2}$$

    式中,$y$是$x$对应的真实值。我们的目标就是使得$Los{s_{A,a}}$最小化时的${c_1}$和${c_2}$,目标函数为:

    $${\min \sum\limits_{x \in {X_1}} {{{(y - {c_1})}^2}}  + \min \sum\limits_{x \in {X_2}} {{{(y - {c_2})}^2}} }$$

    那么,当${c_1}$和${c_2}$取什么值的的时候$Los{s_{A,a}}$最小呢?根据最小二乘的性质可知,当${c_1}$和${c_2}$分为为${X_1}$和${X_2}$中所有$y$的平均值的时候${c_1}$和${c_2}$去的最小值,即:

    $${c_i} = ave(y|x \in {X_i})$$

    所以,如果根据$a$划分之后得到的是叶子结点,那么最终输出的值就是所属样本子集所有$y$的平均值。

    $$f(x)={c_i} = ave(y|x \in {X_i})$$

    对数如何确定输出值的问题,就已经解决了。接下来还剩两个个问题需要解决,那就是选择哪个属性作为最优分割特征属性以及选择哪个值作为最佳的分割点。

    对于这个问题,可以通过遍历数据集各特征属性的可能取值的方式来解决:对数据集$X$中各特征属性$A$,计算其所有取值$a$下的$Los{s_{A,a}}$,然后对比所有$Los{s_{A,a}}$,取值最小的$Los{s_{A,a}}$所对应的特征属性$A$为当前最优分裂特征属性,$a$为最佳分裂点。

    至此,如何确定各分支的输出值、如何选择最优分割特征属性和分割点的问题都已解决,最后总结一下CART算法在回归问题中的决策树构建流程:

    (1)对当前数据集$X$,计算所有特征属性$A$下所有取值$a$作为分割点时的最小$Los{s_{A,a}}$;

    (2)对比所有$Los{s_{A,a}}$,选择最小的$Los{s_{A,a}}$所对应的特征属性$A$为当前最优分裂特征属性,$a$为最佳分裂点将数据集划分都左右两个子树中;

    (3)对左右两个子树的数据集重复(1)、(2)步骤继续划分,直到节点中数据集满足指定条件则决策树构建完成。

    4 树剪枝

    无论是面对分类问题,还是回归问题,最终生成的树都有可能过于复杂,容易发生过拟合的情况,所以决策树构建完成后,有必要进一步完成数剪枝。

    本文代价复杂度剪枝 Cost-Complexity Pruning(CCP) 方法,过程如下:

    输入:CART算法生成的决策树$T_0$  
    输出:剪枝后的最优决策树${T_\alpha }$  
    (1)令$k=0$, $T=T_0$,$\alpha  =  + \infty $;   
    (2)自上而下地对各内部节点计算$C({T_t})$,$|{T_t}|$以及

    $$g(t) = {{C(t) - C({T_t})} \over {|{T_t}| - 1}}$$

    $$\alpha  = \min (\alpha ,g(t))$$ 

    其中,$T_t$表示以$t$为根节点的子树,${C(t)}$是对$t$进行剪枝后对训练数据集的预测误差,${C({T_t})}$是对训练数据集的预测误差,${|{T_t}|}$是$T_t$的叶子结点个数;

    (3)自上而下地访问内部节点$t$,如果有$g(t)=\alpha$,则对$t$进行剪枝,并对叶子结点$t$以多数表决法决定输出,得到树$T$;

    (4)令$k=k+1$,${\alpha _k} = \alpha $,${T_k} = T$;

    (5)如果$T$不是由根节点单独构成的树,则回到步骤(3); 

    (6)采用交叉验证法在子树序列${T_0},{T_1}, \cdots ,{T_k} = T$选取最优的子树${T_\alpha }$。

    要理解CART决策树的整个剪枝过程,关键是明白$g(t)$的含义,对于一颗理想的决策树,我们当然希望预测误差越小越好,树的规模也越小越好,但是两者却不能两全,因为往往预测误差随着树规模的增大而减小,所以单独考虑预测误差变化或者树规模变化都不合适,最好是选择一个衡量标准能够同时考虑到预测误差变化量和树规模变化,例如两者的比值。

    仔细$g(t)$的计算发现,分子是剪枝前后预测误差相减,也就是预测误差变化量,分子是剪枝前后叶子结点数的变化量,所以我们可以认为两者的比值就是树$t$每个叶子节点所带来的的预测误差的变化量,或者说树$t$所带来的的预测误差变化率——这就是$g(t)$的含义。
    为什么每次对$g(t)$最小的节点进行剪枝呢?因为$g(t)$越小代表对$t$对整个决策树的作用越小,对其进行剪枝对决策树的准确率影响也是最想的,当然应该优先被剪枝。

    如果还不明白,那么通过下面的例子来理解吧(例子来源于:https://www.jianshu.com/p/b90a9ce05b28)。 

    有下面这个坐标中中的数据集,以及根据数据集构建好的决策树,如下图所示:

    此时,${\alpha _1} = 0$,树中共有3个节点,对每个节点分别计算其$g(t)$:

    $t_1$、$t_2$节点的$g(t)$最小,我们选择剪枝少的节点,也就是$t_3$进行剪枝,并且令${\alpha _2} = {1 \over 8}$。剪枝后决策树如下:

    剩下两个节点,继续计算每一个节点的$g(t)$:

    显然,$t_2$的$g(t)$更小,所以对$t_2$进行剪枝,并令${\alpha _3} = {1 \over 8}$:

    这时候仅剩下一个$t_1$,计算后有$g({t_3}) = {1 \over 4}$,所以${\alpha _4} = {1 \over 4}$

    完成上述所有计算后,我们得到序列${\alpha _0} = 0,{\alpha _2} = {1 \over 8},{\alpha _3} = {1 \over 8},{\alpha _4} = {1 \over 4}$,以及对应的子树。接下来剩余的工作就是利用独立的验证数据集计算每个子树的平方误差或者基尼指数,选择误差最小的那个子树作为最优的剪枝后的树。

    5 总结

    在本文末尾对3种决策树算法做一个简单对比总结:

    展开全文
  • CART决策树算法浅谈(分类树部分)

    千次阅读 2017-09-04 11:30:31
    CART决策树,分类树部分
  • 本文详细总结了CART树,包括了CART分类树和CART回归树,给出了相关的推导和思想,然后重点介绍了决策树的剪枝,最后总结了决策树的优缺点。
  • 本人计算机小白一枚,初学机器学习,将自己学到的知识点整理出来,一方面是对自己学习的小总结,另一方面是欢迎大家批评指正。如果觉得写得还可以,大家可以转发关注此博客,谢谢!后续会有新算法持续更新~
  • 决策树算法原理(ID3,C4.5) CART回归树 决策树的剪枝    在决策树算法原理(ID3,C4.5)中,提到C4.5的不足,比如模型是用较为复杂的熵来度量,使用了相对较为复杂的多叉树,只能处理分类不能处理回归。对这些...
  • 文章目录CART算法1....与ID3和C4.5只有决策树的生成不同的是,CART算法由以下两步组成: (1)决策树生成:基于训练数据集生成一棵尽量大的决策树。 (2)决策树剪枝:用验证数据集对已生成的树...
  •  在决策树算法原理(上)这篇里,我们讲到了决策树里ID3算法,和ID3算法的改进版C4.5算法。对于C4.5算法,我们也提到了它的不足,比如模型是用较为复杂的熵来度量,使用了相对较为复杂的多叉树,只能处理分类不能处理...
  • 决策树算法CART算法 二、实验目的与要求: 在软件方面:会用Clementine软件中CART建立决策树。 在理论方面:CART算法的原理。 三、实验原理: 1、CART算法的基本步骤及应用。 2、基尼系数的概念及其对变量取值纯度...
  • 决策树算法总结

    2020-12-26 01:29:38
    常见决策树类型比较1 ID3 算法2 C4.5算法3 CART算法cart剪枝为什么要剪枝常用的减枝方法预剪枝后剪枝决策树算法api案例:泰坦尼克号乘客生存预测泰坦尼克号数据步骤分析决策树可视化保存树的结构到dot文件网站显示...
  • CART(Classification and Regression Tree,即分类回归树算法)是一种著名的决策树学习算法,可用于分类和回归任务。 CARTCARTCART 算法使用“基尼指数”来选择划分属性。 基尼指数 假定当前样本集合 DDD 中第 ...
  • Python实现CART决策树

    千次阅读 2020-11-16 14:37:10
    CART决策树前言一、CART决策树算法二、Python代码实现1.计算结点GINI值2.分离数据集3.选择最好的特征4.生成决策树4.测试决策树6.决策树可视化7.主程序部分CART决策分类树所有代码总结 前言   CART算法的全称是...
  • (作者:陈玓玏) 决策树的本质是什么?是将特征空间逐级划分,如下图过程所示: ...图示就是每次都找不同的切分点,将样本空间逐渐进行细分,...基本的决策树算法有三类,按时间顺序分别是:ID3、C4.5、CART。...
  • I . 决策树模型 II . 决策树模型 示例 III . 决策树算法列举 IV . 决策树算法 示例 V . 决策树算法性能要求 VI . 决策树模型创建 ( 递归创建决策树 ) VII . 决策树 树根属性 选择
  • [Information Gain][equtation][equtation]: http://latex.codecogs.com/svg.latex?g_r(D,A)=H(D)-H(D|A)ID3算法在选择根节点和内部节点中的分支属性时,采用信息增益作为评价标准。信息增益的缺点是倾向于选择取值...
  • 分类算法决策树CART算法

    千次阅读 2017-08-21 11:01:06
     Classification And Regression Tree,即分类回归树算法,简称CART算法,它是决策树的一种实现,通常决策树主要有三种实现,分别是ID3算法,CART算法和C4.5算法。  CART算法是一种二分递归分割技术,把当前样本...
  • 决策树CART算法

    2020-08-22 09:06:59
    决策树算法详解(一) 连接 在前面介绍的决策树算法中,其特征的取值是离散的。就比如人的性别这个属性,只分为男女两个离散的值。在这样的情况下,决策树算法就无法应用到连续值上面去。为了将前面讲到的决策树算法...
  • 决策树算法

    千次阅读 多人点赞 2021-01-12 21:45:17
    决策树算法 一、决策树算法简介 二、决策树分类原理 1.熵 概念 案例 2.决策树的划分依据一----信息增益 概念 案例: 3.决策树的划分依据二----信息增益率 概念 案例 案例一 案例二 为什么...
  • 决策树cart算法详解

    2019-06-25 10:56:15
    CART假设决策树是二叉树,内部结点特征的取值为“是”和“否”,左分支是取值为“是”的分支,右分支是取值为“否”的分支。这样的决策树等价于递归地二分每个特征,将输入空间即特征空间划分为有限个单元,并在这些...
  • 决策树算法梳理

    2019-04-03 22:45:30
    决策树算法
  • 决策树算法介绍

    万次阅读 2018-08-27 16:28:06
    本篇博文主要对决策树算法做一个总结。主要内容包括,ID3算法和C4.5算法的简单介绍、CART算法的重点介绍和决策树是如何剪枝的,以及决策树的优缺点和决策树在sklearn中使用的一些技巧。 决策树是一种基本的分类与...
  • 决策树算法比较: ID3、C4.5、CART1. ID31.1 算法步骤:1.2 划分标准(信息增益):1.3缺点2. C4.52.1改进2.2 划分标准2.3剪枝策略2.4 缺点3. CART3.1算法步骤3.2 改进3.3 划分标准(基尼指数)3.4 缺失值处理3.5 ...
  • (一)实例:使用ID3算法给出“好苹果”的决策树 (二)决策树的工作原理 我们在做决策树的时候,会经历两个阶段:构造和剪枝。 构造原理——构造的过程就是选择什么属性作为节点的过程,构造过程中,存在三种节点...
  • 决策树(Decision Tree)是一种基于规则的基础而又经典的分类...典型的决策树有ID3、C4.5和CART(Classification And Regression),它们的主要区别在于树的结构与构造算法。其中ID3和C4.5只支持分类,而CART支持分类和...
  • 最近,在复习一些机器学习算法,根据还是要通过归纳总结的方式来梳理,这样思维脉络才能很清晰~ ...决策树学习的三个步骤: 特征选择、决策树的生成、树的剪枝 (1) 特征选择的标准: 信息增益、信息增益比、...
  • CART回归树算法过程

    千次阅读 2018-10-15 12:27:52
    CART决策树算法是一种分类及回归树算法,既可以用于分类,也可以用于回归。但是在李航老师的《统计学习方法》一书中,并没有详细介绍回归树,更多的是介绍分类树,所以有必要对CART回归树进行简单介绍,有利于对CART...
  • python与R实现决策树算法一、基于python(一)绘图环境的配置(Graphviz安装)(二)分类树1、模型拟合与决策树可视化2、重要属性、接口3、重要参数(三)回归树(四)总结二、基于R(一)ID3算法(二)CART算法(三...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,300
精华内容 2,520
热门标签
关键字:

cart决策树算法步骤