常用的分支准则方法有三种:信息增益、信息增益率、基尼系数。其实,这里问题就来了,决策树是可以不加限制的生长到有可能到很深的吗?当然是不行的,这就是这一节需要介绍的主要内容之一决策树的修剪,当然还会对决策树算法规律稍微总结一下,并用几个小例子说明R语言的具体实现。
决策树的修剪
单单根据决策树算法完成树的建立后,各个叶节点代表不同的种类,部分叶节点可能只包含少数样本,有可能还是一些异常数据,没有足够的支持度,增加了树的深度,过度适配也会导致分类错误率的增加。这就需要修剪决策树,原理是:从树的底部开始,检查每个节点和该节点的子决策树,看是否能将该子决策树去掉而该节点就自然成为了叶节点代替原来的子决策树,生成一个分类错误率更低、树的深度更低的决策树。
决策树的修剪分为
事前修剪
事后修剪
顾名思义,事前修剪就是在决策树的生长过程中,比如叶节点中数据数要大于3或者信息增益值要大于一个事先设定的阈值;否则,就停止分支。事后修剪就是在树的生长完成后进行修剪,引入测试组样本来验证决策树对于新输入数据的分类与预测结果。事后修剪法较前者效率略微低下,但可避免产生稀疏叶节点,对噪声的忍耐程度也更强。这里我们主要介绍事后修剪法。
事后修剪法考虑成本复杂度,我们以R(t)代表t为起始节点的决策树分类错误率。给定一个复杂系数a可以理解为代表决策树节点个数的影响,因为我们定义他们是正比例关系的,再给定一个未修剪的节点t,就可以将一决策树成本复杂性定义为决策树节点个数与分类错误率的函数Ra(t)。
Ai表示节点A的所有直接一级子节点,就不要往下深入了,m表示节点A的直接一节子节点个数,|Aierror|表示子节点Ai分类错误的样本数,|Ai|表示子节点 Ai的样本总数.这里Nleaf表示叶子节点个数,就是m。若有一个节点产生分支,在给定复杂系数a下,若分支后的成本复杂度大于分支前的成本复杂度,则进行剪枝,还是用上篇文章数据那个小例子加以说明。
职员表现决策树(未修剪)
将其用Gini系数构建的未经修剪的完整的决策树,共有10个样本,11个叶节点。可以根据节点中哪种类别数据的数量最大决定类别,比如ID = 10的叶子节点,由于其包含2个优秀,一个普通,最终判别为“优秀”。如下
拿ID = 8的节点为例,如果剪枝剪掉节点10、11,造成的错分成本为:
R(t = 8) = 1/4*(4/10) = 0.1
若未删除节点10、11,给定复杂系数a = 0.01下,节点8的叶节点个数Nleaf = 2,产生的加权平均分类错误率如下:
Ra(t = 8)=R(t = 8)+axNleaf
= (1/3*(3/10)+0)+0.01*2=0.12
注意:这里上一式的R(t = 8)与二式的R(t = 8)是不一样的,前者经过剪枝,直接算,后者因为没有剪枝,是一个加权平均分类错误率,需要根据子节点错误率进行占比加权。
由于,Raa(t = 8)>R(t = 8),所以需要进行剪枝。再拿节点5为例,前面强调过,虽然它有孙子节点,但我们只看直接子节点。
那么,同理
R(t = 5) = 1/5*(5/10) = 0.1
Ra(t = 5)=R(t = 5)+axNleaf
=(1/4*(4/10)+0)+0.01*2 = 0.12
同样,Raa(t = 5)>R(t = 5),所以需要进行剪枝。
最终剪枝结果是:把8、9、10、11这四个节点修剪了,形成了最终的决策树。
决策树规则提取
完成决策树的生长、修剪后,我们最终目的是需要利用决策树帮助我们做出决策,那么就需要决策树规则的提取。
主要步骤:从根节点出发,利用IF-THEN规则,走完每条到叶节点的路径,提取分类规则模型。
比如,从上面的决策树我们可以提取出规则:
IF |
THEN |
若学历为大专 |
表现为普通 |
若学历为研究所且资历小于5年 |
表现为优等 |
若学历为研究所且资历为10年以上且有相关经验 |
表现为优等 |
若学历为研究所且资历为10年以上且无相关经验 |
表现为普通 |
这就把决策树规则提取出来了,遇到含有较少样本的规则,可以选择在上级节点直接合并,使其更加轻量、耐用。
决策树算法小结
查了一些资料,常用的决策树算法分支原理以及它们分别适合做分类的数据类型小结如下:
CART以Gini系数作为决定分支变量的准则,C4.5/C5.0以信息增益比作为决定分支变量的准则,CHAID是AID算法的延伸,它是根据卡方检定统计量的显著性检定,决定最佳的分支属性。
R语言小例子
R语言有一个决策树常用的一种包"rpart",这里用的是R语言里面help('rpart')的内容,用的数据是脊椎后凸儿童的矫正手术结果数据集(kyphosis),大概就是这么个意思(英语不太好!),旨在说明R语言实现决策树还是很方便的。
这个例子,在R里面help('rpart')命令是可以出来的。
我们首先看一下这份数据1
1> head(kyphosis)
2 Kyphosis Age Number Start
31 absent 71 3 5
42 absent 158 3 14
53 present 128 4 5
64 absent 2 5 1
75 absent 1 4 15
86 absent 1 2 16
有一个变量名叫Kyphosis,首字母大写,与数据集名kyphosis(首字母小写)不要混淆。我们可以猜到,用好像可以作为因子变量的第一列(实际是手术成功与否结果)作为目标变量,构建决策树模型!
代码很简单,如下:
1rm(list = ls())
2library(rpart)
3attach(kyphosis)
4#不加复杂系数限制模型
5fit <- rpart(Kyphosis~Age+Number+Start)
6#加复杂系数限制模型
7fit2 <- rpart(Kyphosis~Age+Number+Start,control = rpart.control(cp = 0.05))
8par(mfrow = c(1,2),xpd = NA)
9plot(fit,main = '不加复杂系数限制')
10text(fit)
11plot(fit2,main = '加复杂系数限制')
12text(fit2,use.n = TRUE)
这样就构建了一个以变量Kyphosis(第一列)为目标变量的决策树模型,fit与fit2的区别,在于是否加复杂因子限制,加了复杂因子可能会剪枝,使决策树更简洁。这里也可以这样写
1fit2 <- rpart(Kyphosis~.,data = kyphosis,control = rpart.control(cp = 0.05))
只是省略分支变量,加上data = kyphosis指定应用到kyphosis这个数据集上,用"."代替一长串变量名,可以自动识别目标变量,就是指定的"~"前面的变量。
最终画出的两棵决策树如图:
猜你喜欢
本文分享自微信公众号 - 数据分析挖掘与算法(ikeguang2)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
来源:oschina
链接:https://my.oschina.net/u/3658210/blog/4427123