CART剪枝算法详解
CART剪枝算法
CART剪枝算法从“完全生长“的决策树的底端剪去一些子树,使决策树变小(模型变简单),从而能够对未知数据有更准确的预测。CART剪枝算法由两步组成:首先从生成算法产生的决策树T0底端开始不断剪枝,直到T0的根节点,形成一个子树序列{T0,T1 ,…, Tn};然后通过交叉验证法在独立的验证数据集上对子树序列进行测试,从中选择最优子树。
1. 剪枝,得到子树序列
子树的损失函数:
Cα(T)=C(T)+α∣T∣{C_\alpha }(T) = C\left( T \right) + \alpha \left| T \right|Cα(T)=C(T)+α∣T∣
T为任意子树,C(T)为对训练数据的预测误差,可以是基尼指数,|T|为子树T的叶子节点个数,α>= 0为参数,Cα(T)为参数是α时的子树T的整体损失,|T|衡量树的复杂度,α权衡训练数据的拟合程度与树的复杂度。
为了使得损失函数减小,有两种办法:
1> 降低第一部分的不确定次数,但我们知道这是不可能的了,因为降低不确定次数的办法是再找寻一个特征,或者找寻特征的最优切分点。这在生成决策时就已经决定了,无法改变。 (换句话说就是使得子树T的预测误差下降,这可能就要重新选择特征)
2> 进行剪枝操作,这是可以的。剪枝最明显地变化就是叶结点个数变少。假设是一个三叉树,那么一次剪枝它的叶结点数减少2个。变化量为2α,有了这变化量,我们就可以用来求解最优决策子树了。
在α参数给定时,假设只有一个子结点发生剪枝,那么该子结点上的叶结点都将全部归并到该结点,由此我们计算此结点的不确定次数。倘若不确定次数增大的量超过2α,那么剪枝失败,算法将尝试其他子结点。因为新得的子树损失函数反而增大。 这从侧面又反映了什么样的事实? 该子结点的分类规则大大降低了不确定次数,并不存在噪声,所以没必要进行剪枝。所以在剪枝过程中,找寻的就是那些噪声点,被过度规则的那些子结点,把这些合并了,万事大吉,自然而然决策树的准确率将上升。
那么问题来了,α是未知的,从函数和以上的分析中我们可以看出α的值对剪枝结果有很大的影响,我们如何找到这个合适的α来使拟合程度与复杂度之间达到最好的平衡呢,最好的办法就是,我们将α从0取到正无穷,对于每一个固定的α,我们都可以找到使得Cα(T)最小的最优子树T(α) 。当α 很小的时候,T0是最优子树,当α很大的时候,单独一个根节点Tn是最优的子树。(Breiman等人证明:可以用递归的方法对树进行剪枝,将a从小增大,a0<a1<…<an<+无穷,产生一系列的区间[ai,ai+1),i =0,1,…,n;剪枝得到的子树序列对应着区间[ai,ai+1),i =0,1,…,n的最优子树序列{T0, T1, … , Tn},序列中的子树是嵌套的。嵌套应该很好理解,向上剪枝的过程,树越变越小嘛)
我们通过无限个α去求有最优的子树序列式很困难的,是一个NP完全问题,那怎么办呢?
这里有一个前提,对固定的α,一定存在使损失函数Cα(T)最小的子树,将其表示为Tα。Tα在损失函数最小的意义下是最优的,这样的最优的子树是唯一的。其实所要表达的意思就是Tα和α是一一对应的。
我们通过无限个α去求最优的子树序列是很困难的,但是根据剪枝的核心思想我们知道,无论多么复杂的决策树,生成的最优子树序列都是有限的,这里记作{T0,T1 ,…, Tn},那么我们只需要寻找每一个最优子树对应的α不就可以了嘛。
如上分析,我们现在的思路就是要得出最优子树序列,这子树序列又如何生成呢?(怎么感觉说着说着又说回来了呢,我们的最终结果不就是要得到这些最优子树序列吗?为什么还要记录相应的α值呢?这个本人也不胜理解)我们先说说求子树序列的事情。
我们先假设我们找到了当前的最优子树,且必然发生剪枝(一定要注意这句话,这是我们接下来所有推导的前提)。具体地,从整体树T0开始剪枝,我们每次剪枝剪的都是某个内部节点的子节点,也就是将某个内部节点的所有子节点回退到这个内部节点里,并将这个内部节点作为叶子节点。因此在计算整体的损失函数时,这个内部节点以外的值都没变,只有这个内部节点的局部损失函数改变了,因此我们本需要计算全局的损失函数,但现在只需要计算内部节点剪枝前和剪枝后的损失函数。
对任意内部节点t,
剪枝前的状态:有|Tt| 个叶子节点,预测误差是C(Tt)
剪枝后的状态:只有本身一个叶子节点,预测误差是C(t)
剪枝前以t结点为根结点的子树的损失函数是:
Cα(Tt)=C(Tt)+α∣Tt∣{C_\alpha }({T_{\rm{t}}}) = C\left( {{T_t}} \right) + \alpha \left| {{T_t}} \right|Cα(Tt)=C(Tt)+α∣Tt∣剪枝以后以t为单结点树的损失函数是:Cα(t)=C(t)+α{C_\alpha }(t) = C\left( t \right) + \alpha Cα(t)=C(t)+α
当alpha=0及alpha充分小,有不等式Cα(Tt)<Cα(t){C_\alpha }({T_t}) < {C_\alpha }(t)Cα(Tt)<Cα(t)
当alpha增大时,在某一alpha有
Cα(Tt)=Cα(t)⋅⋅⋅⋅⋅⋅⋅(1){C_\alpha }({T_t}) = {C_\alpha }(t)·······(1)Cα(Tt)=Cα(t)⋅⋅⋅⋅⋅⋅⋅(1)
当alpha再增大时,以上不等式(1)反向。在(1)式的情况下,α1=C(t)−C(Tt)∣Tt∣−1{\alpha _1} = \frac{{C(t) - C({T_t})}}{{\left| {{T_t}} \right| - 1}}α1=∣Tt∣−1C(t)−C(Tt)我们之前假设在得到最优子树时必然发生了剪枝,那么什么时候必然发生剪枝?当我们取得损失函数中的α>=α1时,必然对Tt进行剪枝,因为此时剪枝后损失函数的值要比剪枝前小。
那是不是剪掉当前的t结点就可以得到最优子树了呢,当然不是,不同的结点会计算出不同的α1,我们就以此α1作为损失函数的α值(解释一下,当α=α1时,该节点剪枝前后的损失函数的值是一样的,但是剪枝后结点少,也必然要剪枝,此时该结点处的损失函数值也是最小的),这时会算出不同的损失函数值来,当然是取损失函数值最小的结点来剪枝。这里我们将结点t作为变量,计算得到的α记为α(t),则有如下公式:mintC(t)+α(t)(2)\mathop {\min }\limits_t C(t) + \alpha (t) (2)tminC(t)+α(t) (2)但是在李航的《统计学习方法》中却用以下公式来衡量应该剪枝的结点:g(t)=C(t)−C(Tt)∣Tt∣−1(3)g(t) = \frac{{C(t) - C({T_t})}}{{\left| {{T_t}} \right| - 1}} (3)g(t)=∣Tt∣−1C(t)−C(Tt) (3) 有一篇博文是这样解释的:整体损失函数 = 内部节点t的损失函数 + 其他节点的损失函数和 我们在计算2式的时候只是让等号右边的第一项达到了最小,可是局部结点的损失函数最小并不能代表整体的损失函数最小,所以并不能以2式来剪枝。但本人认为这种说法经不起推敲,如果我们对2式了解透彻的话应该知道,在α确定的情况下,整体的损失函数的计算相当于是对局部结点损失函数的累加,在某个结点剪枝而其他结点不改变的情况下,2式等号右边的第二项并没有变化,因此这并不能说明问题。但我们可以这样说,针对单个结点的剪枝我们可以用2式来衡量,可多个结点的剪枝用这种局部结点的计算公式是行不通的。
而α就不一样了,在上面已经说过了,剪枝得到的子树序列对应着区间[ai,ai+1),i =0,1,…,n的最优子树序列{T0, T1, … , Tn},我们在不同的α(g(t))下剪枝可以得到一一对应的有限个最优子树。在李航的《统计学习方法》中,将g(t)解释为剪枝后整体的损失函数减少额程度,如果不看之前的推导,只看公式3,我们是可以理解的,其实这跟信息增益的概念差不多,但加入了结点个数这个变量来权衡模型复杂度的影响。在T0中剪去g(t)最小的Tt,将得到的子树作为T1,同时将最小的g(t)设为α1。T1为区间[α1, α2)的最优子树。
那为什么是最小的g(t)呢?(以下是别的博文上的解释,说的很好,我就直接拿过来用了,自己就不再赘述了)
以图中两个点为例,结点1和结点2,g(t)2大于g(t)1, 假设在所有结点中g(t)1最小,g(t)2最大,两种选择方法:当选择最大值g(t)2,即结点2进行剪枝,但此时结点1的不修剪的误差大于修剪之后的误差,即如果不修剪的话,误差变大,依次类推,对其它所有的结点的g(t)都是如此,从而造成整体的累计误差更大。反之,如果选择最小值g(t)1,即结点1进行剪枝,则其余结点不剪的误差要小于剪后的误差,不修剪为好,且整体的误差最小。从而以最小g(t)剪枝获得的子树是该alpha值下的最优子树!
通过以上的说明,我们现在应该可以理解,将α从小增大,产生一系列的区间,剪去 g(t)属于[αi, αi+1)的对应的结点,就会得到该区间上的最优子树,如此剪下去,直到得到根结点。在这一过程中,不断增加α的值,产生新的区间。
2. 从剪枝得到的子树序列中通过交叉验证选取最优子树Tα。
具体地,利用独立的验证数据集,测试子树序列T0, T1, … , Tn中各棵子树的平方误差或基尼指数。平方误差或基尼指数最小的决策树被认为是最优的决策树。在子树序列中,每棵子树T0, T1, … , Tn都对应于一个参数α0, α1, … ,αn。所以,当最优子树Tk确定时,对应的αk也确定了,即得到最优决策树Tα。
最后附上CART剪枝算法:
输入:CART算法生成的决策树T0
输出:最优决策树Tα
(1)设k=0,T=T0
(2)设α=+∞
(3)自下而上地对各个内部结点t计算C(Tt),|Tt|以及
g(t)=C(t)−C(Tt)∣Tt∣−1g(t) = \frac{{C(t) - C({T_t})}}{{\left| {{T_t}} \right| - 1}}g(t)=∣Tt∣−1C(t)−C(Tt) α=min(α,α(t))α=min(α,α(t))α=min(α,α(t))这里,Tt表示t为根结点的子树,C(Tt)是对训练数据的预测误差,|Tt|是Tt的叶结点个数。
(4)对α(t)=α的内部结点t进行剪枝,并对叶结点t以多数表决法决定其类,得到树T。
(5)设k=k+1,αk=α,Tk=T。
(6)如果Tk不是由根结点及两个叶结点构成的树,则回到步骤3;否则令Tk=Tn。
(7)采用交叉验证法在子树序列T0,T1,…,Tn中选取最优子树Tα
最后,我还是不明白这一点,为什么我们还要记录最终的α值,不是只要得到最优子树就可以了吗?
参考文献:
- Demon的黑与白 https://blog.csdn.net/u014688145/article/details/53326910
- MrTriste https://blog.csdn.net/wjc1182511338/article/details/76793164
- 李航. 统计学习方法[M]. 北京:清华大学出版社,2012
CART剪枝算法详解相关推荐
- python alpha beta 剪枝_一看就懂的 Alpha-Beta 剪枝算法详解
Alpha-Beta剪枝用于裁剪搜索树中没有意义的不需要搜索的树枝,以提高运算速度. 假设α为下界,β为上界,对于α ≤ N ≤ β: 若 α ≤ β 则N有解. 若 α > β 则N无解. ...
- 一看就懂的Alpha-Beta剪枝算法详解
原贴:http://blog.csdn.net/tangchenyi/article/details/22925957 Alpha-Beta剪枝算法(Alpha Beta Pruning) [说明] ...
- 经典算法详解--CART分类决策树、回归树和模型树
Classification And Regression Tree(CART)是一种很重要的机器学习算法,既可以用于创建分类树(Classification Tree),也可以用于创建回归树(Reg ...
- 回溯算法详解之全排列、N皇后问题
回溯算法详解 回溯算法框架.解决一个回溯问题,实际上就是一个决策树的遍历过程.你只需要思考 3 个问题: 1.路径:也就是已经做出的选择. 2.选择列表:也就是你当前可以做的选择. 3.结束条件:也就 ...
- c4.5算法 程序语言,决策树之C4.5算法详解-Go语言中文社区
决策树之C4.5算法详解 主要内容 C4.5算法简介 分裂属性的选择--信息增益率 连续型属性的离散化处理 剪枝--PEP(Pessimistic Error Pruning)剪枝法 缺失属性值的处理 ...
- Apriori算法详解之【一、相关概念和核心步骤】
感谢红兰整理的PPT,简单易懂,现在将其中精彩之处整理,与大家分享. 一.Apriori算法简介: Apriori算法是一种挖掘关联规则的频繁项集算法,其核心思想是通过候选集生成和情节的向下封闭检测 ...
- JDA人脸检测算法详解
JDA人脸检测算法详解: 第一步: JDA算法原理详解: 作者建立了一个叫post classifier的分类器,方法如下: 1.样本准备:首先作者调用OpenCV的Viola-Jones分类器,将r ...
- Apriori算法详解与实现
Apriori算法详解与实现 一.摘要 二.绪论 三.算法介绍 1.项目 2.项集 3.项集的支持度 4.关联规则 5.关联规则的置信度 6.频繁k项集 7.算法流程 四.代码实现 五.引用 一.摘要 ...
- Matlab人脸检测算法详解
这是一个Matlab人脸检测算法详解 前言 人脸检测结果 算法详解 源代码解析 所调用函数解析 bwlabel(BW,n) regionprops rectangle 总结 前言 目前主流的人脸检测与 ...
- 图论-最短路Dijkstra算法详解超详 有图解
整体来看dij就是从起点开始扩散致整个图的过程,为什么说他稳定呢,是因为他每次迭代,都能得到至少一个结点的最短路.(不像SPFA,玄学复杂度) 但是他的缺点就是不能处理带负权值的边,和代码量稍稍复杂. ...
最新文章
- oracle 关联出现重复数据,ORACLE 分页查询出现重复记录的解决办法
- Linux 搭建Sphinx 全文检索引擎
- sniffer 工具
- 微信小程序image组件中aspectFill和widthfix模式应用详解
- 3Dshader之膨胀与收缩
- day_log 12月份的
- java 冒泡_Java中的冒泡排序
- java最新2019面试题
- prince和学生们侃侃而谈系列03
- 《Python基础教程(第3版)》笔记:第8章异常
- 蓝牙无法连接手机解决大全(转)
- 小程序正则验证 身份证号、统一社会信用代码
- 2018年的总结和2019年的期望
- 【电子技术】如何抑制共模、差模噪声?
- 可能是历史上最伟大的一次 Git 代码提交
- jquery表单ajax json数据,jquery序列化form表单使用ajax提交后处理返回的json数据
- MVC之Identity身份验证
- 使用vlookup嵌套INDIRECT函数实现跨表数据引用
- Allegro 17.4完整教学内容+视频
- iOS - AVPlayer播放视频,获取视频尺寸(宽高)
热门文章
- tcl语言读取文件一行_TCL语言笔记:TCL中的列表操作
- MCSA / Windows Server 2016 PowerShell DSC
- 【高速PCB电路设计】2.高速电路DDR原理图概述
- 学习笔记(5):Google开发专家带你学 AI:入门到实战(Keras/Tensorflow)(附源码)-深度学习“四件套”:数据、模型、损失函数与优化器...
- TextCNN(文本分类)
- 创建线程的三种方法c语言,创建线程 - Python教程 - C语言网
- 计算机程序设计流程图循环,流程图循环画法_流程图用什么办公软件
- 软考中级软件设计师该怎么备考
- android笔画输入法的字库,献给爱好笔画输入的机友们 速度才是王道之大众码新笔画输入法...
- 【PR】PR剪辑视频编辑软件视频去字幕