CART 剪枝
损失函数构建
在前面的章节中,我们了解到可以通过平方误差最小化准则和基尼指数最小化准则生成一颗回归树和分类树 \(T\)。但是通常在实现过程中,我们会对CART树进行剪枝以达到简化模型的目的。同决策树的剪枝类似,在CART树剪枝过程中,我们也需要计算子树\(T\)的损失函数:
\[\begin{align} C_\alpha(T) = C(T) + \alpha |T| \end{align} \]
其中,\(T\)是任意子树, \(C(T)\)是子树\(T\)在训练数据上的误差,\(|T|\)是子树的叶结点个数代表着子树的复杂度,\(\alpha\)是权重因子,用于平衡误差与复杂度。
不难发现,当\(\alpha\)越大时,通过最小化损失函数,很容易去优化子树\(T\)的复杂度,得到一颗简单的子树。极端情况下,当\(\alpha \to \infty\)时,由根结点组成的单结点树是最优的。反之,当\(\alpha \to 0\)时,模型趋向于优化树的分类或回归的准确性。此时,整树是最优的,但是可能会额外复杂。
CART剪枝思想
CART树剪枝思想十分巧妙,具体来说它对树中的每个内部结点\(t\)做一个判断:如果剪枝之前以\(t\)为根结点的子树的损失函数\(C_\alpha(T_t)\)等于剪枝之后以\(t\)为单结点树的损失函数\(C_a(t)\),那么就进行剪枝(既然剪枝之后损失函数没用增加,还降低了复杂度为什么不剪掉呢?)。
\[\begin{align} C_\alpha(T_t) = C(T_t) + \alpha |T_t| \end{align} \]
\[\begin{align} C_\alpha(t) = C(t) + \alpha \end{align} \]
通知上式可以观察到,当\(\alpha=0\)或比较小时,必然有\(C_\alpha(T_t) < C_\alpha(t)\),当\(\alpha\)增大,并到达某一点时,必然有\(C_\alpha(T_t) = C_\alpha(t)\),当\(\alpha\)继续增大时,不等式反向\(C_\alpha(T_t) C_\alpha(t)\)
由此可见只要令\(C_\alpha(T_t) = C_\alpha(t)\),那么我们就可以在保证模型准确度的同时减少模型的复杂度,即:
\[\begin{align} \alpha = g(t) = \frac{C(t) - C(T_t)}{|T_t| - 1} \end{align} \]
这时候,我们在\(T_0\)中减去\(g(t)\)最小的子树得到\(T_1\), 同时将最小的\(g(t)\)作为\(\alpha_1\),接着我们对\(T_1\)进行相同的操作,依次判断其内部每个结点的情况,并得到\(T_2, \alpha_2\)。
最终我们可以得到一个子树序列:\(T_0, T_1, \ldots, T_n\)以及对应的参数\(\alpha_1, \alpha_2, \ldots, \alpha_n\),它们是一一对应的,同时\(\alpha_i\)也是递增的。最终,使用交叉验证法在子树序列中选取最优子树\(T_\alpha\)。
这里需要解释一下为什么通过这种剪枝方式\(\alpha_i\)是递增的?
回答:剪枝前后的代价是一样的(损失函数的值一样!!!)
CART剪枝算法
输入:由CART算法生成的CART树\(T_0\)
输出:剪枝后的CART树\(T_\alpha\)
具体步骤如下:
-
设\(k=0, T = T_0\),这里\(k\)表示第\(k\)个子树。
-
设\(\alpha=+\infty\)。
-
自下而上地对树的内部结点\(t\)计算\(C(T_t)\), \(|T_t|\)、\(g(t)\)以及\(\alpha=min(\alpha, g(t))\)
-
对\(g(t)=\alpha\)的子树进行剪枝,并对叶结点\(t\)以多数表决法决定其类得到树\(T\)。
-
设\(k = k+1, \alpha_k = \alpha, T_k = T\)
-
如果\(T_k\)不是由根结点及两个叶结点构成的树,则继续从步骤2开始执行,否则\(T_k = T_n\),\(n\)就是最后一个可以剪枝的树。
-
从子树序列\(T_1, T_2, \ldots, T_n\)中采用交叉验证法找到最优子树\(T_\alpha\)。