本篇是决策树系列的第二篇,介绍一下决策树的剪枝过程。过拟合是决策树构建过程中常见的问题,信息失衡、噪声等问题都会导致过拟合,剪枝则是提高决策树模型泛化能力的重要手段,下面对常用的剪枝方法作一些介绍。
决策树系列第一篇《分类:决策树——树的生长》中提到过,树的生长是一种“完全”式的生长,终止条件也仅有“所有的样本属于同一类,或者所有的样本具有相同的属性值”这两条,但有时可以再增加一些终止条件,提前结束树的生长,这个过程相当于在一棵“完全”生长的树上剪去一些枝干,这就是预剪枝过程。例如,可以增加这样一条生长终止条件:当结点划分后度量参数(信息增益、增益率或者基尼指数)变化小于设定阈值时,则将该结点当作叶子结点,不予划分。
预剪枝过程简单,计算量也较小,但是它有两个缺点,一个是前面提到的终止生长时设定的阈值,该值通常难以确定,另一个则是会出现“欠拟合”现象,在当前结点上的划分效果不理想时,但其子女结点上的划分效果可能会比较理想,预剪枝过程容易发生这种情况。
一般预剪枝方法在实际中不会用到。
后剪枝是在决策树生长停止之后进行的剪枝,按照剪枝的方向,分为从上至下(top-bottom)和从下至上(bottom-top)。后剪枝方法有多种,除了剪枝方向的区别外,主要的区别在在于剪枝的条件,现依据剪枝条件的不同,介绍一下常用的几种后剪枝方法。
REP方法是Quinlan教授提出的,采用从下至上(bottom-top)的剪枝方式。使用该方法时,需要将样本划分为训练集和验证集,然后从树底到树顶,将每个内部结点生成的子树用该结点代替,实现剪枝,用验证集来判断剪枝前后的误差,若剪枝后误差增大,则取消剪枝,反之则剪枝。
从剪枝的过程来看,REP方法是比较简单的,每个子树只需要访问一次,所以它的计算过程是线性的。该方法的缺点一个是需要将样本集划分为训练集与验证集,这在样本量不足够大时比较影响模型构建;另外一个是当验证集/训练集中包含的信息在训练集/验证集中未出现时,剪枝反而降低了模型泛化能力。
样本量不大时一般不使用REP剪枝方法。
PEP方法是Quinlan教授为了弥补REP方法需要单独的验证集的缺点而提出的剪枝方法,模型的构建、剪枝过程使用同一个样本集,该方法使用采用从上至下(top-bottom)的方式。由于剪枝时采用的同一样本集,因此更趋向于不剪枝,毕竟更多的子树能做更准确的分类,为此PEP方法中为每一个叶子结点引入了惩罚项 ,一般取 。对于一棵二叉树来说, 意味着只要能够改善一个训练记录的分类,就应该划分结点;对于一棵m叉树来说, 意味着必须改善 个训练记录的分类时才应该划分结点,其中 表示大于 的最小整数。因此,在引入惩罚项后,更多的子树就不一定能做到更准确的分类了。
未引入惩罚项前,叶子结点 的误分类率 定义为
为该结点上的误分类数, 为该结点所包含的样本数。引入惩罚项后,其误差率定义为
假设一棵子树的叶子结点数为k,则该子树的误分类数 与误分类率 分别为
将该子树剪掉、用叶子结点代替后,其误分类数 为
为未引入惩罚项前的误分类数。对于指定的子树,树上的样本数是确定的,因此可以用误分类数代替误分类率,按照REP方法中的剪枝策略,当满足
时即将子树剪掉。
引入了惩罚项后,剪枝条件还是比较严格的,拿二叉树来说,很容易做到改善一个训练样本的分类结果,从而取消剪枝。为此,Quinlan教授重新定义了剪枝的条件。在一颗子树上,一个样本的分类结果只有“正确”和“错误”两种,这实际上是一个伯努利过程,错误分类的概率为 ,当子树上包含 个样本时,那么这 个样本的分类结果就服从概率为 的二项分布,期望为 ,方差为 。对于一棵包含 个样本的子树,其误分类率 是可以统计出来的(即已知的,见式(4)),即
则该子树上被正确分类的样本的标准差为
尽管当前子树的误分类数为 ,但是参考其误分类数的标准差来看,对于一些待分类的样本,该子树的误分类数可能会达到
为此,Quinlan教授将子树的剪枝条件放宽为
PEP方法是后剪枝方法中唯一采用从上至下(top-bottom)剪枝的方法,因而其有着与预剪枝方法一样的优点,就是效率高,是后剪枝方法中精度较高的方法之一,并且不需要验证数据集。
CCP方法是Breiman等人提出的,是CART算法中采用的剪枝方法,剪枝时采用从下至上(bottom-top)的方式。
首先,定义子树的损失函数
式(9)中, 表示任意的子树, 表示子树对训练数据的预测误差(如基尼指数、误分类率等,由于CART算法使用基尼指数作度量,因此这里一般使用基尼指数), 表示子树的叶子结点数, 为子树的参数( ), 为指定参数 下子树 的整体损失。
先来定义最优子树: 最优子树是指在训练样本上损失函数最小的子树 。从式(9)中对子树的损失函数定义可以看到,当 较大时子树叶子结点的个数(子树的复杂度)对损失函数的影响较大,最优子树偏小;当 较小时子树的预测误差对损失函数影响较大,最优子树偏大。极端情况下,当 时整体树是最优的,当 时根节点构成的单结点树是最优的。可以证明,对于一个给定的 值,最优子树是唯一的,由于 的取值范围为 ,因此在 增大的过程中可以得到一系列的最优子树。对于一个决策树,由于内部结点个数是一定的,因此 可能在一个区间范围内对应的最优子树都是同一棵子树。接下来,考虑一下如何寻找给定 值下的最优子树。
显然,通过递增 值,然后遍历树上所有结点计算损失函数、得到最优子树的方式是不现实的, 值的连续变化导致这个计算复杂度难以估计,因此我们可以换一个思路来寻找最优子树。试想一下,既然我们的目的就是为了剪枝,那何不采用遍历树上所有内部结点(非叶子结点)、逐个剪枝,比较得到的子树的损失函数的方式来确定最优子树呢?这个计算复杂度只与内部结点个数相关。
具体的过程以树的任一内部结点 来说明,以结点 为根节点生成的子树,其损失函数为
以结点 替换子树、得到单结点树的损失函数为
当 =0及充分小时,有如下关系
随着 逐渐增大,到某个值时存在如下关系
再继续增大时,不等式(12)将反向。当等式(13)成立时
此时将该子树剪去(这里剪去的意思是用单一结点代替其生成的子树,后面不再说明)后损失函数不变,但是整体树的结点更少,因此应该执行剪枝。对结点 来说,当公式(14)成立时,剪枝前后损失函数不变的只是它本身,但整体树的损失函数由于 的取值而发生变化,很显然 越小,余下的树的损失函数越小,也越优(可以参照公式(9)理解)。有人可能会想,那我剪去叶子结点更多的子树可以吗?答案是不可以,因为这会改变余下的树的预测误差,由公式(12)可知反而会增大损失函数。
从下至上,对树的每一个内部结点按照公式(14)计算出 值,选择其中最小 值对应的结点,将以该结点生成的子树剪枝,完成本轮剪枝过程。
说完了单轮的剪枝过程,现在我们以整体树 为初始树说明CPP方法中完整的剪枝过程。树 经过第一轮剪枝后得到树 ,第一轮剪枝结点对应的 值为 (按照公式(14)计算出),那树 是不是一个全局的最优子树呢?不见得,就算不用验证集进行验证我们也可以这样说,因为树 只是 取 时的最优子树,由前面所讲内容及公式(12)可知,实际上树 也是 在 上的最优子树。如果只在树 上变化 值,不管 取多少,根据公式(12)、(13)、(14)所说明的内容,最优的子树仍然是树 。因此,我们可以以树 为初始树,继续下一轮剪枝,此时初始树的结构变了,这样可以得到最优子树 及对应的 (显然 ),然后以树 为初始树继续这个过程,知道整体树 的根节点,最终我们会得到一系列最优子树 ,这些最优子树是训练集上的最优子树。
在验证集上使用交叉验证法验证 ,其中表现最好的子树将作为的剪枝结果。
EBP剪枝方法是C4.5算法中默认使用的剪枝方法,它采用的是一种从下至上的剪枝方式。