机器学习爬大树之决策树(CART与剪枝)

        分类与回归树(classification and regression tree,CART)是应用广泛的决策树学习方法,同样由特征选择树的生成以及剪枝组成,既可以用于分类也可以用于回归。CART假设假设决策树是二叉树,内部结点特征的取值为“是”或‘否’,左分支是取值为‘是’的分支,右分支是取值为“否”的分支,例如有个特征为‘年龄’,它的特征值为{‘年龄’:[‘小孩’,‘成年’,‘老人’]};那么左分支为去{‘年龄’ = ‘小孩’}的情况下为{{‘小孩’},{‘成年’,‘老人’}};这样的决策树等价于递归地二分每个特征,将输入空间即特征空间划分为有限个单元,并在这些单元上确定预测的概率分布,也就是在输入给定的条件下输出的条件概率分布!

      CART算法有以下两步组成:

            i)决策树的生成:基于训练数据集生成决策树,生成的决策树要尽量大:而在递归地构建二叉决策树时,对生成回归树用平方误差最小化准则,对分类树用基尼指数(Gini index)最小化准则,进行特征选择,生成二叉树。

           ii)决策树剪枝:用数据集对已生成的树进行剪枝并选择最优子树,这时用损失函数最小作为剪枝的标准。

 一、CART之回归树

        一个回归树对应着输入空间(即特征空间)的一个划分以及在划分的单元上的输出值;当输入空间的划分确定时,可以用平方误差在表示回归树对于训练数据 的预测误差,用平方误差最小的准则求解每个单元上的最优输出值。

      问题是怎样对输入空间进行划分呢?、这里采用启发式的方法,这里我们假设有\boldsymbol{N}个特征,每个特征都有\boldsymbol{s_i(i=1,2,...,n)}取值,那么我们遍历所有的特征,尝试该特征下的所有取值,直到我们取得了最小的特征\boldsymbol{j}的特征值\boldsymbol{s},使得损失函数最小,这样就得到一个划分点,即:

                             \large \min_{j,s}\left [ \min_{c_1}\sum _{x_i\in R_1(j,s)}Loss(y_i,c_1) + \min_{c_2}\sum _{x_i\in R_2(j,s)}Loss(y_i,c_2)\right ]

     接着,对每个区域重复上述划分过程, 假设 将输入空间划分为M个单元\large \boldsymbol{R_1,R_2,...,R_M},则每个划分空间的输出值为                                                         \large \boldsymbol{C_M=ave(y_i\mid x_i\in R_M(j,s))}

   直到满足停止条件为止,这样就生成一颗回归树。这样的回归树通常称为最小二乘回归树(least squares regression tree)

   具体算法步骤参考李航(统计学习方法):

  

 为了便于理解,我们以一个简单的例子来生成一个回归树(最小二乘回归树):

\large x_i 1 2 3 4 5 6 7 8 9 10
\large y_i 4.50 4.75 4.91 5.34 5.80 7.05 7.90 8.23 8.70 9.00

首先我们的划分点集合为:

                                          

\large s 1.5 2.5 3.5 4.5 5.5 6.5 7.5 8.5 9.5

来寻找最优划分点(因为我们的例子只有一个特征\large x,所以无需考虑\large j

当s=1.5时,R_1=\left \{ 1 \right \},R_2=\left \{ 2,3,4,5,6,7,8,9,10 \right \},由划分后的输入空间的输出值公式:

                                          \large \boldsymbol{C_M=ave(y_i\mid x_i\in R_M(j,s))}

C_1 = 4.50

   C_2=(4.75+4.91+5.34+5.80+7.05+7.90+8.23+8.70+9.00) / 9=6.85

同理得到如下表:

\boldsymbol{s} 1.5 2.5 3.5 4.5 5.5 6.5 7.5 8.5 9.5
C_1 4.50 4.62 4.72 4.87 5.06 5.39 5.75 6.06 6.35
C_2 6.85 7.11 7.43 7.78 8.17 8.45 8.64 8.85 9.0

s, C_1C_2带入公式

                            \large m(s)=\min_{j,s}\left [ \min_{c_1}\sum _{x_i\in R_1(j,s)}Loss(y_i,c_1) + \min_{c_2}\sum _{x_i\in R_2(j,s)}Loss(y_i,c_2)\right ] 

\boldsymbol{s} 1.5 2.5 3.5 4.5 5.5 6.5 7.5 8.5 9.5
\large m(s) 22.64 17.70 12.19 7.38 3.36 5.07 10.05 15.18 21.33

由上表可以很清楚的知道当s=5.5时,损失函数最小\large m(s)=3.36,故将训练集划分为:

R_1=\left \{ 1,2,3,4,5 \right \}C_1 = 5.06;             R_2=\left \{ 6,7,8,9,10 \right \},C_2 = 8.17;

那么此时的回归树可以表示为:

                                                    \LARGE f(x)=\left\{\begin{matrix} 5.06 & x\leq 5.5\\ 8.17&x> 5.5 \end{matrix}\right.

然后分别对R_1=\left \{ 1,2,3,4,5 \right \}R_2=\left \{ 6,7,8,9,10 \right \}重复上面的步骤:

当划分时R_1=\left \{ 1,2,3,4,5 \right \},有

\boldsymbol{x_i} 1 2 3 4 5
\boldsymbol{y_i} 4.50 4.75 4.91 5.34 5.80

此时的划分点为:

\boldsymbol{s} 1.5 2.5 3.5 4.5

同理计算每个划分下的\boldsymbol{m(s)},然后找到最小的划分点作为最后的划分点,如下表:

\boldsymbol{s} 1.5 2.5 3.5 4.5
C_3 4.50 4.63 4.72 4.88
C_4 5.20 5.35 5.57 5.80

s, C_3C_4带入公式 \boldsymbol{m(s)},得到下表:

\boldsymbol{s} 1.5 2.5 3.5 4.5
\boldsymbol{m(s)} 0.67 0.43 0.191 0.37

因此最小划分点为\boldsymbol{s}=3.5,故将 R_1=\left \{ 1,2,3,4,5 \right \}    ,分为R_3=\left \{ 1,2,3 \right \}, 其输出值C_3=4.72;   R_4=\left \{ 4,5 \right \}  ,其 输出值 C_4=5.57.

当划分时R_2=\left \{ 6,7,8,9,10 \right \},有 

      

\boldsymbol{x_i} 6 7 8 9 10
\boldsymbol{y_i} 7.05 7.90 8.23 8.70 9.00

此时的划分点为:

\boldsymbol{s} 6.5 7.5 8.5 9.5

同理计算每个划分下的\boldsymbol{m(s)},然后找到最小的划分点作为最后的划分点,如下表:

\boldsymbol{s} 6.5 7.5 8.5 9.5
C_5 7.05 7.48 7.73 7.97
C_6 8.46 8.64 8.85 9.0

 将s, C_5C_6带入公式 \boldsymbol{m(s)},得到下表:

\boldsymbol{s} 6.5 7.5 8.5 9.5
\boldsymbol{m(s)} 0.72 0.66 0.79 1.45

因此最小划分点为\boldsymbol{s}=7.5,故将 R_2=\left \{ 6,7,8,9,10 \right \}    ,分为R_5=\left \{ 6,7 \right \}, 其输出值C_5=7.48;   R_6=\left \{ 8,9,10 \right \}  ,其 输出值 C_6=8.64.

我们的终止条件是最小损失函数小于某个阈值,或者是规定树的深度,亦或者是样本个数小于预定阈值

所以假设我们规定树的深度为3,那么以上划分将终止,最后的回归树为:

                                           \LARGE f(x)=\left\{\begin{matrix} 4.72 & x\leq 3.5\\ 5.06 &3.5< x\leq 5.5 \\ 7.48 &5.5< x\leq 7.5 \\ 8.64 &x>7.5 \end{matrix}\right.

在GBDT中无论是回归还是分类问题,都是使用CART回归树,那么如何用CART的回归树解决CBDT的分类,我将在后续的博客中论述。

二、CART之分类树

           CART决策树使用“基尼指数”(Gini index)来选择划分特征,其定义如下:

给定一个样本集合D,假设有K个类,第k类的样本集合为D_k,其概率为p_k,则样本集合D的基尼指数定义为:

                                   \large Gini(D)=1-\sum _{k=1}^{K}\left ( \frac{\left | D_k \right |}{\left | D \right |} \right )^2=1-\sum _{k=1}^{K}p_k^2

        直观来说,\large Gini(D)反映了从数据集\large D中随机抽取两个样本,其类别标记不一致的概率。因此,\large Gini(D)越小,则数据集\large D的纯度越高。

        如果样本集合\large D根据特征\large A是否取某一可能属性值\large a被分割成\large D_1\large D_2两部分,即:

                                \large D_1=\left \{ (x,y)\in D\mid A(x)=a \right \}   , \large D_2=D-D_1

       则在特征\large A的条件下,集合\large D的基尼指数定义为:

                                \large Gini(D,A)=\frac{\left | D_1 \right |}{\left | D \right |}Gini(D_1)+\frac{\left | D_2 \right |}{\left | D \right |}Gini(D_2)

基尼指数\large Gini(D)表示\large D的不确定性,基尼指数\large Gini(D,A)表示经\large A=a分割后集合\large D的不确定性。基尼指数值越大,样本集合的不确定性也就越大,这一点与熵相似。

算法停止计算的条件一般为:

      (1)结点中的样本个数小于预定的阈值;

      (2)样本集的基尼指数小于预定阈值(样本基本属于同一类)

      (3)没有更多特征

由于这边的知识点较为简单,并且例子很多,比如李航的书就有,所以就不再举例说明了!

三、决策树的剪枝

     剪枝(pruning)是决策树学习算法对付“过拟合”的主要手段。在决策树学习中,为了尽可能正确分类训练样本,结点划分过程将不断重复,有时会造成决策树分支过多,这时就可能因训练样本学得“太好了”,以致于把训练集自身的一些特点当做所有数据都具有的一般性质而导致过拟合。因此,可通过主动去掉一些分支来降低过拟合的风险。

    当前存在许多种不同的剪枝方法,分为预剪枝(preprunning)和后剪枝(postpruning),后者应用较为广泛,后剪枝又可以分为两类,一类是把训练数据集分为树生成集与树剪枝集一类是树的生长与剪枝过程中都使用同一训练数据集,预剪枝的缺点是使树的生长可能过早停止,因此应用较少,因此我们主要讲讲后剪枝的知识点。

   1、ID3与C4.5的剪枝

       决策树的剪枝往往通过极小化决策树整体的损失函数(loss function)或代价函数(cost function)来实现。设树\large \boldsymbol{T}的叶节点的个数为\large \left | T \right |\large t是树\large \boldsymbol{T}的叶节点,该叶节点有\large N_t个样本点,其中\large k类的样本点有\large N_{tk}个,\large k=1,2,...,K,\large H_t(T)为叶结点\large t上的经验熵,\large a\geq 0为参数,则决策树学习的损失函数为:

                                                   \large C_\alpha (T)=\sum _{t=1}^{\left | T \right |}N_tH_t(T)+\alpha \left | T \right |

    其中经验熵为:

                                                  \large H_t(T)=-\sum _k^{K}\frac{N_{tk}}{N_t}log\frac{N_{tk}}{N_t}

 既然损失函数这么定义(虽然我也不知道是怎么来的),我们就好好分析一下这个函数,我们不难发现,决定损失函数的只与叶结点有关,而跟内部节点一点关系都没有,在损失函数中,若有如下定义:

                                               

                                               \large C(T)=\sum _{t=1}^{\left | T \right |}N_tH_t(T)=-\sum _{t=1}^{\left | T \right |}\sum _k^{K}N_{tk}log\frac{N_{tk}}{N_t}

这时有:                               

                                               \large C_\alpha (T)=C(T)+\alpha \left | T \right |

                  \large C(T)表示模型对训练数据的预测误差,即模型与训练数据的拟合程度;

                  \large \left | T \right |表示模型复杂度;

 我的理解是\large \alpha相当于领回归中的正则化参数,首先我们想要最小化的损失函数,那么当\large \alpha很小的时候,对\large \left | T \right |的惩罚也就很小,因此\large \left | T \right |就会很大,这样得到的决策树因为叶结点多所以较为复杂,当\large \alpha=0时,整棵树就是最好的;同理当\large \alpha很大的时候,对\large \left | T \right |的惩罚也就很大,因此\large \left | T \right |就会很小,这样得到的决策树因为叶结点少所以较为简单。

   剪枝就是当\large \alpha确定时,选择损失函数最小的模型;因此我们可以这么理解,\large T_B表示剪枝前的树,\large T_A表示剪枝后的树,看下表:

剪枝前损失函数 \large C_\alpha (T_B)
剪枝后损失函数 \large C_\alpha (T_A)

如果剪枝前的损失函数大于剪枝后的损失函数(我们想要损失函数越小越好)即\large C_\alpha (T_A)\leq C_\alpha (T_B),那么一定要剪枝的啊,好处多多,比如说剪枝后损失函数小;剪枝后因为少了\large \left | T \right |-1个叶子结点所以树的模型也变得简单,因此算法如下:

其实这种剪枝方法类似于REP(reduced error pruning)方法,它需要一个分离数据集\large D用于剪枝,对于决策树\large T的每颗非叶子树\large S,用叶结点代替这颗子树。如果\large S被叶结点替代后形成的新树关于\large D的误差等于或者小于\large S关于\large D所产生的误差,则用叶子结点替代\large S

  我们以下图为例说明REP的剪枝过程,图(a)为剪枝数据集,图(b)和图(c)显示的是基于REP的方法:

我们看图(b)中根结点\large t_1,\large A(3)表示这个结点分类为\large A时的误差为3,即括号里的数是分类误差;在遍历树过程中,采用自底向上的方式,该方式可以保证剪枝后的结果是关于剪枝数据集的具有最小误差的最小剪枝树。

我们以图(b)为例,\large t_4结点有两个叶子结点(\large t_8,t_9),那么\large t_4结点到底需不需要剪枝呢 ?我们看下剪枝前与剪枝后的误差的大小关系来决定:

             剪枝前:\large t_8,t_9的误差之和为1        \large \geq        剪枝后:\large t_8,t_9作为叶子结点被剪掉)\large t_4作为叶子结点误差为0

所以我们决定剪枝(之前2个叶子结点,现在变成了一个,使模型边的简单)得到图(c),余下的过程类似。

   2.CART剪枝

  CART剪枝算法从“完全生长”的决策树的底端剪去一些子树,使决策树变小(模型变简单),从而能够对未知数据有更准确的预测常用CCP(cost-complexity pruning)

CART剪枝算法由两步组成:

   (1):从生成算法产生的决策树\large T_0底端开始不断剪枝,直到\large T_0的根结点,形成一个子树序列\large \left \{ T_0,T_1,...,T_n \right \};

   (2):然后通过交叉验证法在独立的验证数据集上对子树序列进行测试,从中选择最优子树。

在步骤(1)中,生成子树序列\large \left \{ T_0,T_1,...,T_n \right \}的基本思想是从\large T_0开始,裁剪\large T_i中关于训练数据集误差增加最小的分枝来得到\large T_{i+1},实际上,当一棵树\large T在结点\large t处剪枝时,它的误差增加直观上认为是\large C(t)-C(T_t),其中,\large C(t)为在结点\large t的子树被裁剪后的结点\large t的误差(其实就是内部结点t经过裁剪后变成叶子结点t),\large C(T_t)为在结点\large t的子树没被裁剪时的子树\large T_t误差;然而,剪枝后,\large T的叶子数减少了\large \left | T_t \right |-1,其中,\large \left | T_t \right |为子树\large T_t的叶结点数,也就是说,\large T的复杂性减少了因此,考虑树的复杂性因素,树分支被裁剪后误差增加率由下式决定:

                                                            \large \alpha =\frac{C(t)-C(T_t)}{\left | T_t \right |-1}

     其中 \large C(t)=r(t)\ast p(t)\large r(t)结点\large t的误差率\large p(t)是结点\large t的样本个数与训练集样本个数的比值

            \large C(T_t)等于子树\large T_t所有叶子结点的误差之和

那么问题是上式是怎么来的?

首先我们看下在剪枝过程中,计算子树的损失函数:

                                               \large C_\alpha (T)=C(T)+\alpha \left | T \right |

  与上面的一样是不是,我们知道\large C_a(T)为参数为\large \alpha时的子树\large T的整体损失,对于固定的\large \alpha,一定存在使损失函数\large C_a(T)最小的子树,将其表示为\large T_\alpha\large T_\alpha在损失函数\large C_a(T)最小的意义下是最优的。并且Breiman已经证明这样的最优子树是唯一的。

具体的,从整体树\large T_0开始剪枝。对\large T_0的任意内部结点\large t,,若将\large t进行剪枝,即以\large t为单结点的损失函数为

                                           \large C_\alpha (t)=C(t)+\alpha \left

                                  (对\large t剪枝后,由于叶结点变成它自己,所以\large \left | T \right |=1

\large t为根节点的子树\large T_t的损失函数为:

                                          \large C_\alpha (T_t)=C(T_t)+\alpha \left | T_t \right |

                                    (没有对\large t剪枝,所以它还有叶结点\large \left | T_t \right |)

     

\large t剪枝前 \large C_\alpha (T_t) \large \left | T_t \right |
\large t剪枝后 \large C_\alpha (t) \large \left | T \right |=1

\large \alpha=0\large \alpha充分小时,有不等式

                                        \large C_\alpha (T_t)<C_\alpha (t)

                               (前面讲过\large \alpha=0叶结点很是多的,所以复杂度高,分的细,精度高,所以损失函数小;那么剪枝后,由于剪去了\large \left | T_t \right |-1个叶结点,所以精度变得低了一些,自然损失函数就大了一些,所以有了这个不等式)

\large \alpha增大时,在某一\large \alpha

                                       \large C_\alpha (T_t)= C_\alpha (t)

                                  

                                (因为无论\large \alpha怎么变化,剪枝后的树就是客观存在的,所以\large C_\alpha (t)都是不变的,那么当\large \alpha变大之后,剪枝前叶子结点就越少,所以分的没以前细,精度就变得低了一些,直到剪枝前的误差等于剪枝后的误差)

\large \alpha再增大时,不等式反向,所以只要

                                         \large C_\alpha (T_t)= C_\alpha (t)

                                         \large C(t)+\alpha \left=\large C(T_t)+\alpha \left | T_t \right |

                  解得:

                                            \large \alpha =\frac{C(t)-C(T_t)}{\left | T_t \right |-1}

\large T_t\large t有相同的损失函数值,而\large t的结点少了\large \left | T_t \right |-1(剪枝前与剪枝后的损失函数一样,并且剪枝后的叶节点也少了,当然要剪枝啦),对\large T_t进行剪枝!\large T_{i+1}就是\large T_i中具有最小\large \alpha值对应的剪枝树。

接下来我们就一个例子来简单的描述一个剪枝的过程:

如图所示为一个有80个样本的决策树,分类分别为\large A,B\large B,其中对于结点\large t_4(\large A,B类样本有46个,\large B类样本有4个),根据多数分类原则结点\large t_4应该分为\large A,B类,所以:

               结点\large t_4的叶结点(\large t_8,t_9)被裁剪之后的误差为\large \frac{4}{50}\ast \frac{50}{80}=\frac{1}{20}

              结点\large t_4被裁剪之前的误差为\large \frac{1}{45}\ast \frac{45}{80}+\frac{2}{5}\ast \frac{5}{80}=\frac{3}{80}

              带入\large \alpha =\frac{C(t)-C(T_t)}{\left | T_t \right |-1}

              得\large \alpha=\frac{4/80-3/80}{2-1}=0.125,其他过程类似得到:

从上表可以看出,原始树\large T_0中最小的\large \alpha 结点\large t_4,将其剪掉之后为树\large T_1,它的最小\large \alpha结点\large t_2\large t_3,从图中可以看出剪掉结点\large t_2能使树的模型更加简单,裁剪后得到\large T_2

最后利用独立的验证集,测试子树序列\large \left \{ T_0,T_1,...,T_n \right \}中各颗子树的平方误差或基尼指数。平方误差或基尼指数最小的决策树被认为是最优的决策树!具体算法参考李航的统计学习方法!

参考:

周志华 西瓜树

李航 统计学习方法

魏红宁. 决策树剪枝方法的比较[J]. 西南交通大学学报, 2005, 40(1):44-48

https://blog.csdn.net/u014688145/article/details/53326910

https://blog.csdn.net/zhihua_oba/article/details/72230427

猜你喜欢

转载自blog.csdn.net/weixin_41580067/article/details/84886154