决策树与随机森林(1)—— 决策树算法数学推导与实例演练中,我们介绍了决策树的概念, 及信息熵、信息增益和基尼系数的定义和数学推导。其中我们引入了决策树构建的两个核心问题:
建议认真读上面
的参数解读,接下来我们实例演练一下
第一个问题主要通过决策树的几种核心算法进行解决:1.到底由谁来做根节点和内部节点;
2.如何让决策树停止生长,防止过拟合。
算法 | 简介 | R包 |
ID3 | 使用信息增益作为分类标准 | rpart |
CART | 使用基尼系数作为分类标准 | rpart |
CD4.5 | 使用信息增益和增益率相结合作为分类标准 | RWeka |
CD5.0 | 对CD4.5的改进,通过加入自适应增强(adaptive boosting)算法构建多棵决策树,然后这些决策树通过投票表决的方法为每个案例选择最优分类 | C50 |
1.详解rpart函数
rpart(formula, data, weights, subset, na.action = na.rpart, method,
model = FALSE, x = FALSE, y = TRUE, parms, control, cost, ...)
参数 | 解释 |
formula | y~x1+x2+x3/y~.(表示输入变量为除y的所有变量) |
data | 训练数据集(数据框),用来对应formula的变量 |
weights | 类别权重(可选) |
subset | 从data中选取子集建模 |
na.action | 缺失值处理,默认为na.rpart。表示删除所有y缺失的行,但保留那些缺少一个或多个x的行 |
method | 选择决策树的类型。”anova”对应回归树。“class”用于分类变量,对应分类树。“poisson”用于二分类变量,对应分类树。“exp”用于生存分析。 |
parms | 此参数只适用于分类变量。若method=”class”,则parms=list(split,prior,loss).其中split可取“information”(信息增益分类规则),“gini” (基尼分类规则)。不同的分类规则分别对应上述不同的算法。 |
control | 控制rpart的各种细节参数,需要输入一个列表格式的参数设置;control=list(minsplit,minbucket=round(minsplit/3),…) |
minsplit | 每个内部节点中所含样本最小数,默认为20 |
minbucket | 叶子节点中所含样本最小数,如果只指定了minbucket或minsplit中的一个,代码会根据需要将minsplit设置为minbucket*3,或将minbucket设置为minsplit/3 |
cp | 复杂度参数(complexity parameter),通常设定阈值用来剪枝;这个参数的主要作用是通过删除明显不值得的分割来节省计算时间;对每一步进行拆分,指模型的拟合优度必须提高的程度 |
maxdepth | 树的深度,根节点的深度为0,maxdepth默认值为30 |
xval | 几折交叉验证,默认为10折;交叉验证会产生估计误差(结果中的xerror列和xstd列),在剪枝的时候,我们通常选择具有最小xerror的cp的方法。 |
2.构建一棵树
data(iris) ## 使用的数据集head(iris)
所以模拟的思路是以分类变量Species作为因变量,其它四个变量(前四列)作为自变量来对构建一棵决策树。
library(rpart)Tree <- rpart(formula = Species~Sepal.Length+Sepal.Width+Petal.Length+Petal.Width, data = iris,method = 'class',parms = list(split='gini')) summary(Tree) ##查看下函数内部情况
这里我们使用的基尼系数来进行选择决策变量,#CP--剪枝前的复杂度 ;nsplit-分枝数;rel error--训练集对应的误差;xerror--10折交叉验证误差 ;xstd--交叉验证误差的标准差。简单画一棵树(下面会详解画图参数rpart.p):
library(rpart.plot)rpart.plot(Tree,branch=1,type=2, fallen.leaves=T,cex=0.8,main='Gini index')
上面便是使用CART算法也就是Gini系数建立的决策树,将
parms = list(split='gini') 中的gini改为information则就换成ID3算法,这便是一棵简单决策树的构建过程
rpart函数实现了两种算法:ID3和CART。CD4.5和CD5.0的实现函数在下节介绍。3.这棵树的泛化能力
接下来让探索该树在新数据集中的预测能力new <-data.frame(Sepal.Length=c(1,2,3,4), Sepal.Width=c(2,3,4,5), Petal.Length=c(3,4,5,1), Petal.Width=c(4,5,1,2), row.names = LETTERS[1:4])new
predict(Tree,newdata = new,type = 'class')
通过这棵决策树 "Tree",A和B被分为virginica,C被分为versicolor,D被分为setosa,其实这棵决策树也不复杂,我们可以根据A-D的数据直接心算它们会被分到什么类别;此外,如果A-D这四个样本有标签值,那我们可以通过crosstable来评估这棵树的表现怎么样。
4.详解rpart.plot函数
参数 | 解释 |
x | 输入一个rpart对象 |
type | 可取0~5来控制图形中节点的形式 (控制树外观的重要参数) |
extra | 在节点上显示额外的信息;可输入auto或0~11来调整,最好自己实验一下。 |
under | 用于extra>0,如果under=T表示extra text要放在box下面 |
fallen.leaves | 默认值为True, 在树的底端显示叶子节点 |
digits | 图中extra text中的数字要保留几位小数 |
varlen faclen | 这两个参数主要调整图中文本的长度的,个人感觉作用不大,很少使用 |
roundint | 当roundint=True时,如果一个自变量的值在训练集中都是整数,则该变量的splits会被四舍五入为整数。比如nsibings<2.5, 在设置为roundint=T后,会改为nsiblings<3 |
cex | 文本字体大小 |
tweak | 顾名思义,就是微调的意思,比起cex更推荐使用这个参数,因为它可以根据当前的文本字体进行调整,比如tweak=1.2 就是指文本要比当前的文本大20% |
branch | 控制的分支线的形状,0~1,类似于角度的范围,1就是垂直落下,0就是V形落下,0到1的角度越来越接近于直角 |
box.palette | =“auto” 自动选择一个调色板 =0 箱子中是背景色也就是白色 =“Grays” 渐变的灰色 =“gray” 统一都是灰色 可以选择一个预定义的调色板,来改变颜色,具体调整方法如下方示例 |
shadow.col | box下方的阴影颜色 |
show.prp.palettes()
想改成什么颜色,输入对应的英文ID就可。我们再来画一棵树:
rpart.plot(x = Tree, extra = 2, under = F, fallen.leaves = T, cex = 0.8, box.palette = 'GnYlRd')
5.文章实例
该文章识别了由PD-L2、肿瘤内CD3 以及基质FOXP3 组成的免疫预后风险模型,该模型所得到的风险得分的高低显著和胰腺导管癌病人的OS 显著相关。作者通过随机森林筛选变量后构建了一棵决策树,我们后面进行到随机生存森林的时候再回过头来看这篇文章的细节,我们也选择肝癌中的这三个基因的表达值对病人的死亡与否进行预测,这从某些角度来看的话,不太合理,所以仅仅作为例子。rm(list = ls())library(rpart)library(rpart.plot)head(data)
Tree <- rpart(OS~PDL2+FOXP3+CD3, data = data, cp=0.02, parms = list(split='gini'))rpart.plot(x = Tree, type = 5, extra = 2, under = T, fallen.leaves = T, cex = 1, branch=0, box.palette = 'YlGnBl')
pp <- predict(Tree,newdata = data,type = 'class')table(pp,data$OS)
其实这些信息从决策树中叶子节点的结果就可以算出来,四格表的作用算是更清楚地汇总下决策树的结果,这个结果显而易见是很一般的,在训练集中都一般,那再测试集中就不用说了,也一定较为糟糕。决策树相对来说比较简单,对于有R基础的同学,建议好好读读上面的参数说明,或者自己阅读下原始的英文文档。下期介绍CD4.5和CD5.0算法的R实现。