决策树是数据挖掘领域中的经常使用模型,其基本思想是对预测变量进行二元分离,从而构造一颗可用于预测新样本单元所属类别的树node
针对乳腺癌数据集中的良性/恶性,和一组预测变量对应9个细胞特征为基础算法
(1) 选定一个最佳预测变量将所有样本单元分为两类,实现两类中的纯度最大化(即一类中良性样本单元尽量多,另外一类中恶性样本尽量的多)tcp
a、若是预测变量连续,则选定一个分割点进行分类,使得两类纯度最大化;函数
b、若是预测变量为分类变量,则对各种别进行合并再分类性能
(2)对每个子类分别继续执行比步骤(1)spa
(3)重复步骤(1)~(2),直到子类别中所含的样本单元数过少,或者没有分类法能将不纯度下线到一个给定阈值如下,最终集中的子类别即终端节点(terminal node)。根据每个终端节点中样本单元数众数来判别这一终端节点的属性类别code
(4)对任同样本单元执行决策树,获得其终端节点,便可根据步骤3获得模型预测的所属类别,orm
不过,上述算法一般会获得一棵过大的树,从而出现过分 拟合现象,致使对于训练集外单元的分类性能较差,可用 10折交叉验证法,这一 剪枝后的树用于预测。ci
R中的 repart() 函数构造决策树,prune() 函数对决策树进行减枝terminal
#使用rpart()函数建立分类决策树 > library(rpart) > set.seed(1234) > dtree <- rpart(class ~.,data = df.train,method="class",parms = list(split="information")) #生成树
rpart()返回的cptable值中包括不一样大小的树对应的预测偏差,所以可用于辅助设定最终的树的大小
a、复杂度参数(cp)用于惩罚过大的树
b、树的大小即分支数(nsplit),有 n 个分支的树将有 n+1 个终端节点
c、rel eeror栏中即各类树对应的偏差
d、xerror即基于训练样本所得的10折交叉验证偏差
e、xstd栏为交叉验证偏差的标准差
> dtree$cptable CP nsplit rel error xerror xstd 1 0.800000 0 1.00000 1.00000 0.06484605 2 0.046875 1 0.20000 0.30625 0.04150018 3 0.012500 3 0.10625 0.20625 0.03467089 4 0.010000 4 0.09375 0.18125 0.03264401
plotcp()函数可画出交叉验证偏差与复杂度参数的关系图,对于全部交叉验证偏差在最小交叉验证偏差一个标准差范围内的树,最小的树即最优的树
本例子中 最小交叉偏差(xerror)为0.18125,它标准差(xstd)为0.03264401,因此最优的树在 0.18 +- 0.0326 (0.15和0.21)之间的树
> plotcp(dtree) #绘制交叉验证偏差与复杂度参数的关系图,借助关系图能够肯定最优的树
图1 复杂度参数
复杂度参数与交叉验证偏差,虚线是基于一个标准差准则获得上限(0.18+1*0.0326=0.21),从图像来卡,应选择虚线最左侧 cp 值对应的树
由 cptable 的结果可知,四个终端节点(即三次分割)的树知足要求(交叉验证偏差为0.20625),根据图能够选的最优树,即三次分隔(四个节点)对应的树
prune()函数根据复杂度参数剪掉最不重要的枝,从而将树的大小控制在理想范围内,从上述cptale中获得,三次分割对应的复杂度参数为0.0125,因此剪枝获得一个理想大小的树
prune(dtree,cp = 0.0125)
prp()z中有不少的参数(详见?prp),
type=2:画出每一个节点下分隔的标签
extra = 104:画出每一类的几率以及每一个节点处的样本占比
fallen.leaves:可在图的底端显示终端节点
对观测点分类时,从树的顶端开始,若知足条件则从左枝往下,不然从右枝往下,重复这个过程知道碰到一个终端节点为止,该终端节点即为这一观测点的所属类别
> dtree.pruned <- prune(dtree, cp=.0125) > library(rpart.plot) #导入rpart.polt包中的prp()函数 > prp(dtree.pruned, type = 2, extra = 104, + fallen.leaves = TRUE, main="Decision Tree")
图2 用剪枝后的传统决策树预测癌症状态,从树的顶端开始若是条件成立则从左枝往下,否者从右枝往下,当观测点到达终端节点时,分类结束。每个节点处都有对应类别的几率以及样本单元的占比
predict()函数用来验证集中的观测点分类
> dtree.pred <- predict(dtree.pruned, df.validate, type="class") > dtree.perf <- table(df.validate$class, dtree.pred, #实际类别与预测类别的交叉表 + dnn=c("Actual", "Predicted")) > dtree.perf Predicted Actual benign malignant benign 122 7 malignant 2 79
从总体来看,验证集中的准确率达到96%,与逻辑回归不一样的是,验证集中的210个样本单元均可由最终树来分类。
值得注意的是,对于水平数不少或者缺失值不少的预测变量决策树可能会有偏