初始R语言——决策树

来源:互联网 发布:mac顶部菜单栏截图工具 编辑:程序博客网 时间:2024/06/04 00:20

初始R语言——决策树

决策树是机器学习里很重要的分类算法, 网上也有很多博客进行细致地讲解,这里就不再叙述原理,而是直接运用 R 语言的程序包来进行数据处理。

数据描述

本文使用的数据是对乳腺癌肿瘤良性还是恶性的分类,使用 Breast Cancer Wisconsin (Original) Data Set 数据集。简单描述一下,数据集共有 699 个样本, 根据乳腺癌肿瘤的厚度,细胞大小,细胞形状,附着能力,上皮组织细胞特性,细胞核,染色质以及有丝分裂的特性,来对细胞的良性与恶性进行分类。其中 label 是最后的 class 列(2 代表良性,4 代表恶性),而其他特征值都处于 1-10 之间。

函数包介绍

R 语言中有两个不同的函数包可以进行决策树的生成, 分别是 rpart 和 party。 两者的不同在“R语言中的tree和rpart有什么区别”中有详细的解释,比较重要的一点在于,rpart 包通过rpart.control 有不同的方式来决定何时结束分裂,比如 minsplit,代表最小分支节点数,也就是需要划分的样本数小于一定数值后,就不再进行分裂。rpart 包是可以通过剪枝(prune)来改善过拟合的。而 party 是不需要进行剪枝的。

party包代码

# 导入数据dat <- read.csv("breast-cancer-wisconsin.data")# 定义列名names(dat) <- c("id", "clump_thickness", "uniformity_of_cell_size", "uniformity_of_cell_shape","marginal_adhesion", "single_epithelial_cell_size", "bare_nuclei", "bland_chromatin","normal_necleoli", "mitoses", "class")# 将class作为分类变量dat$class <- as.factor(dat$class)head(dat)# 拆分训练集和测试集 # 按照 7:3 的比例划分数据ind <- sample(2, nrow(dat), replace=TRUE, prob=c(0.7,0.3))trainData <- dat[ind==1,]testData <- dat[ind==2,]library(party)myFormula <- class ~ clump_thickness + uniformity_of_cell_size + uniformity_of_cell_shape + marginal_adhesion + single_epithelial_cell_size + bare_nuclei + bland_chromatin + normal_necleoli + mitosesdat_tree <- ctree(myFormula, data=trainData)plot(dat_tree,type="simple")trainPredict = predict(dat_tree,trainData)# 使用 table 来简单直观的评估效果table(trainPredict,trainData$class)testPredict <- predict(dat_tree,testData)table(testPredict,testData$class)

我们可以来看一下这个决策树的样子:


这里写图片描述

我们同样可以用文字来对这个树进行描述:


这里写图片描述

rpart函数包

# 使用 rpart 程序包来生成树library(rpart)myFormula <- class ~ clump_thickness + uniformity_of_cell_size + uniformity_of_cell_shape + marginal_adhesion + single_epithelial_cell_size + bare_nuclei + bland_chromatin + normal_necleoli + mitoses# 使用rpart来生成决策树,minsplit=10 说明小于10不再分类dat_rpart <- rpart(myFormula, data=trainData, control = rpart.control(minsplit = 10))# 使用得到的决策树进行测试trainPredict <- predict(dat_rpart,trainData,type="class")table(trainPredict,trainData$class)testPredict <- predict(dat_rpart,testData,type="class")table(testPredict,testData$class)# 画图plot(dat_rpart,branch=0, margin=0.1,uniform=TRUE);text(dat_rpart,use.n=T,all=TRUE)# 剪枝opt <- which.min(dat_rpart$cptable[,"xerror"])cp <- dat_rpart$cptable[opt,"CP"]dat_prune <- prune(dat_rpart, cp=cp)trainPrunePredict <- predict(dat_prune,trainData,type="class")table(trainPrunePredict,trainData$class)testPrunePredict <- predict(dat_prune,testData,type="class")table(testPrunePredict,testData$class)

这里对剪枝进行下解释,我们知道当一个决策树很复杂,会出现过拟合现象。复杂性是由这个 cp(complexity parameter)参数来衡量,其中 xerror 参数体现的就是过拟合。复杂度越高,cp值就越小。过拟合程度越高,xerror值也越小。而这里剪去的 cp 是 xerror 参数最小的那一个,即对过拟合影响最大的那一个。但是我们又要尽量保证复杂度不要太低,以保证准确性。

看一下这个树的样子:


这里写图片描述

以及代码描述:


这里写图片描述

随机森林

R 语言中随机森林是使用 randomForest 程序包进行实现的:

library(randomForest)# 因为随机森林不像决策树一样固定,所以class~后面不是固定的# ntree 的数量是 100rf <- randomForest(class~., data=trainData,ntree=100,proximity=TRUE)rfTrainPredict <- predict(rf,trainData,type="class")table(rfTrainPredict,trainData$class)rfTestPredict <- predict(rf,testData,type="class")table(rfTestPredict,testData$class)

结果分析

因为使用的是随机划分数据集和训练集并且没有使用seed,所以每次结果会有所出入。
这里使用 table 来观察结果,显示分错与分对的个数。


这里写图片描述
party包得到结果


这里写图片描述
rpart包未剪枝结果

未剪枝情况下 rpart 不如 party 准确。

这里写图片描述
rpart剪枝后结果

对比下剪枝前后效果,训练集的误差会有所增大,测试集总数没有发生变化但是误差更加平均。
但是很多时候剪枝前后结果是完全一样的,这是不是说明该数据本身已经有很强的可分性了呢?

最后是随机森林,按照经验来说肯定会优于前两个。


这里写图片描述

果然,孤木难支,森林的力量还是令人畏惧的。

总结

最近在学习R语言,练习运用已有的程序包来实现一些最基本的机器学习算法。很多函数也是看了很多博客论坛慢慢实践摸索出来的,可能会有所纰漏也会有理解错误的地方,还望指正。

原创粉丝点击