r语言机器学习篇——随机森林

zarzzzz1 zarzzzz1     2023-03-03     225

关键词:

参考书籍:陈强.机器学习及R应用.北京:高等教育出版社,2020

随机森林属于集成学习的方法,也称为组台学习,本章介绍随机森林与它的特例方法,装袋法,并分别以例子的形式讨论回归问题与分类问题的随机森林方法。

一 回归问题的随机森林

对于回归问题,调用MASS包数据框Boston作为数据集,分析波士顿房价的相关情况,选取70%左右的数据作为训练集,代码如下:

library(MASS)
dim(Boston)
set.seed(1)
train <- sample(506,354)  #随机选取70%数据

1.装袋法估计

使用R中的随机森林包进行装袋法估计,注意参数中的“mtry=13”表示在该例中使用全部的特征变量,“importance=TRUE”计算变量重要性。最后代码及输出结果如下

library(randomForest)
set.seed(123)
bag.fit <- randomForest(medv~.,data=Boston,subset=train,mtry=13,importance=TRUE,replace=T)
bag.fit
#Call:
 randomForest(formula = medv ~ ., data = Boston, mtry = 13, importance = TRUE,      replace = T, subset = train) 
               Type of random forest: regression
                     Number of trees: 500
No. of variables tried at each split: 13

          Mean of squared residuals: 11.94245
                    % Var explained: 86.9

结果显示’函数random forest()默认估计500棵决策树(B=500),在每个节点均使用全部的13个变量,根据袋外观测值计算的OOB均方误差为11.94245;而准R方为0.869,即模型可解释响应变量medv86.9%的方差,使用plot()画出袋外误差(OOB均方误差),结果如下:

plot(bag.fit,main="Bagging OOB Errors")

在该图中,横轴为决策树的数目(B),纵轴为袋外误差,由图可见,B>200时,误差就趋于平稳,这时继续增大B,也不会使之下降。

接下来展示变量重要性,如下所示:

#变量重要性
importance(bag.fit)
#          %IncMSE IncNodePurity
crim    16.955901    1112.22516
zn       2.071627      30.37986
indus    7.677858     140.58943
chas     0.339128      44.09888
nox     16.099685     438.55880
rm      68.838872   20374.08905
age     15.675505     493.82123
dis     20.897606    1413.37172
rad      3.470134      90.80601
tax      8.935524     193.32866
ptratio 22.174601     414.80738
black   10.508969     274.43954
lstat   40.192884    6898.26149
> varImpPlot(bag.fit,main="Variable Importance Plot")  #画图

输出结果中的变量重要结果的第1列(IncMSE)表示汇报在模型中去掉某个变量后,使得袋外误差上升的百分比(如去掉变量age,袋外误差上升15.68%);第2列(IncNodePurity)汇报基于训练样本计算的变量重要性。这里需要注意对于回归问题,NodePurity就是残差平方和;对于分类问题,则是基尼系数。

从图中可以看出,对于响应变量medv(社区房价中位数)影响最大的两个变量都是rm(房间数)和lstat(低端人口比重),若是想看某个变量的偏依赖图,可用以下的代码实现,以变量rm为例,结果如下所示:

#变量偏依赖图
partialPlot(bag.fit,Boston[train,],x.var=rm)

从上图可以看出,变量rm对房价medv的影响为正向,但并非完全线性。特别在rm较小或较大的尾部区域,变量rm对于房价medv的影响很微弱(函数几乎变为水平线)。另外,横轴上的地毯图(mgplot)标出变量rm的十分位数(即l/10,2/I0,…,9/10分位数)。这些分位数表明在rm的尾部区域观测值较少,因此尾部结果并非可信。

下面对测试集进行预测,并画出预测值与实际值之间的散点图,计算出MSE,如下:

bag.pred <- predict(bag.fit,newdata=Boston[-train,])     #得出测试集的预测值
y.test <- Boston[-train,"medv"]   #测试集的真实值
plot(bag.pred,y.test,main="Bagging Prediciton")
abline(0,1)
mean((bag.pred-y.test)^2)   #均方误差
#[1] 22.96509

接下来运用OLS方法,与随机森林方法对比,判断预测效果的优劣。

ols.fit <- lm(medv~.,Boston,subset=train)  
ols.pred <- predict(ols.fit,newdata=Boston[-train,])
mean((ols.pred-y.test)^2)  
#[1] 27.31196

结果显示OLS测试集MSE为27.31,高于装袋法,这表明,对于波士顿房价数据尽管单颗回归树预测效果不及OLS,但集成学习的效果则优于OLS。

可以尝试不同的参数进行装袋法估计,例如以下的例子

bag.fit <- randomForest(medv~.,data=Boston,subset=train,mtry=13,ntree=1000,
nodesize=10)

其中参数“ntree=1000”表示种1000棵树(默认值为500);参数nodesize=10,表示将终节点的最小规模设为10个观测值(默认值为5)。

2.随机森林估计

下面估计随机森林模型,如下所示

set.seed(123)
forest.fit <- randomForest(medv~.,data=Boston,subset=train)
forest.fit
#Call:
 randomForest(formula = medv ~ ., data = Boston, subset = train) 
               Type of random forest: regression
                     Number of trees: 500
No. of variables tried at each split: 4

          Mean of squared residuals: 10.33118
                    % Var explained: 88.67

forest.pred <- predict(forest.fit,newdata=Boston[-train,])
mean((forest.pred-y.test)^2)
#[1] 14.65405

对于回归问题,函数randomForest()默认“mtry=p/3“,故在此使用“mtry=4”进行估计(p=13)。计算随机森林的测试误差,为14.65,比装袋法有较大提升。

下面考察随机森林测试误差与决策树数目(B)的关系,以B=100为例,展示如下

MSE.forest <- numeric(100)  # 创建100个空值数字
set.seed(123)
for(i in 1:100)
  fit <- randomForest(medv~.,data=Boston,subset=train,ntree=i)
  pred <- predict(fit,newdata=Boston[-train,])
  y.test <- Boston[-train,"medv"]
  MSE.forest[i] <- mean((pred-y.test)^2)
    #查看决策树数目从1到100,测试误差的数值变化

下面再查看装袋法测试误差与决策树数目的关系:

MSE.bag <- numeric(100)
set.seed(123)
for(i in 1:100)
  fit <- randomForest(medv~.,data=Boston,subset=train,ntree=i,mtry=13)   #这里与随机森林不同
  pred <- predict(fit,newdata=Boston[-train,])
  y.test <- Boston[-train,"medv"]
  MSE.bag[i] <- mean((pred-y.test)^2)

作为对比,计算单颗决策树的测试误差:

library(rpart)
set.seed(123)
tree.fit <- rpart(medv~.,Boston,subset=train)  
min_cp <-  tree.fit$cptable[which.min(tree.fit$cptable[,"xerror"]),"CP"]
tree.prune <- prune(tree.fit, cp = min_cp)
tree.pred <- predict(tree.prune,newdata=Boston[-train,])
mse <- mean((tree.pred-y.test)^2)   
MSE.tree <- rep(mse,100)

最后,通过画图的形式,展示随机森林、单棵决策树、装袋法的测试误差变化,结果如下:

plot(1:100,MSE.forest,type="l",col="blue",ylab="MSE",xlab="Number of Trees",
      main="Test Error",ylim=c(10,55))
lines(1:100,MSE.bag,type="l")
lines(1:100,MSE.tree,type="l",col="black",lty=2)
legend("topright",lty=c(2,1,1),col=c("black","black","blue"),legend=c("Best Single Tree",
       "Bagging","Random Forest"))    #图标,区分不同的线所代表的方法

由图可见,装袋法的测试误差低于最优的单棵树,而随机森林的测试误差比装袋法还更低。随机森林的一个重要调节参数为mtry,即每次用于节点分裂的变量个数,这可以通过最小化袋外误差或交叉验证误差来确定,首先考虑最小化袋外误差:

可用R包random forest中的tuneRF()函数,达到上述的目的,该函数需要设定参数“step—Factor”表示随机选择变量个数的缩放倍数,并不考虑mtry的所有可能取值,下面通过计算寻找使袋外误差最小的mtry:

MSE <- numeric(13)  #mtry最多可以取到13因为有13个特征变量
set.seed(123)
for(i in 1:13)
  fit <- randomForest(medv~.,data=Boston,subset=train,mtry=i)
  MSE[i] <- mean(fit$mse[500])

MSE
# [1] 19.557467 12.717293 10.658755  9.903552 10.026058  9.815894
 [7]  9.899590 10.344245 10.561024 10.875071 11.038252 11.606371
[13] 11.963906

min(MSE)
which.min(MSE)   #找到哪个mtry值使得MSE最小
plot(1:13,MSE,type="b",xlab = "mtry",main="OOB Errors")
abline(v=which.min(MSE),lty=2)

结果显示,当mtry=6时,袋外误差达到最小,仅为9.81589,不过mtry=4~7之间的结果差别不大。

下面使用另一种方式——交叉验证误差,来选择mtry的最优值,可使用rfcv()函数,但该函数同样不考虑所有mtry取值,因此还是通过计算找出。

首先将将训练数据随机分为大致相等的5折(训练数据为354个,10折的话就很小,会造成结果不够准确)

Boston_train <- Boston[train,]
set.seed(12345)
foldid <- sample(1:5,size=354,replace=TRUE) # use the same folds 
head(foldid)
#[1] 3 2 4 2 5 3

其中’训练集定义为Boston_train。通过从1:5中有放回地抽取354次,可得到训练集中每个观测值的分组归属。

其次,初始化MSE为一个13×5的矩阵,其中MSE(i,j)元素用于记录当mtry=i,而以第j折作为验证集的均方误差:

MSE <- matrix(rep(0,65),ncol=5)   # initialize CV error for mtry 
for (i in 1:13)
  for (j in 1:5)
    train_cv <- Boston_train[foldid!=j,]
    holdout <- Boston_train[foldid==j,]
    fit <- randomForest(medv~.,data=train_cv,mtry=i)
    pred <- predict(fit,newdata=holdout)
    y.test <- holdout[,"medv"]
    MSE[i,j] <- mean((pred-y.test)^2)
  

cv.error <- apply(MSE,1,mean)
min(cv.error)
#[1] 16.21452
which.min(cv.error)
#[1] 8

其中,在外面的for循环,考察mtry=1:13的不同情形。给定mtry取值后,在里面的for循环,则依次以第j折作为验证集,计算相应的均方误差。最后,使用apply()函数计算矩阵MSE每行的平均值,即为对应于不同mtry取值的交叉验证误差。

结果显示’在mtry=8时,交叉验证误差达到最小值,但交叉验证误差的最小值明显高于袋外误差的最小值,由于在进行交叉验证时,每次仅使用训练集的4/5进行估计,故可能高估测试误差.更直观地,画交叉验证误差图,如下所示:

plot(1:13,cv.error,type="b",xlab="mtry",main="Cross-Validation Error")
abline(v=which.min(cv.error),lty=2)

最后,通过for循环,通过测试集误差来选择最优mtry:

MSE <- numeric(13)
set.seed(123)
for(i in 1:13)
  fit <- randomForest(medv~.,data=Boston,subset=train,mtry=i)
  pred <- predict(fit,newdata=Boston[-train,])
  y.test <- Boston[-train,"medv"]
  MSE[i] <- mean((pred-y.test)^2)

min(MSE)
#[1] 14.65984
which.min(MSE)
#[1] 4
plot(1:13,MSE,type="b",xlab = "mtry",main="Test Error")
abline(v=which.min(MSE),lty=2)

严格来说,如果使用测试集来选择调节参数,则无法再使用测试集估计测试误差,因为测

试集的信息已经通过选中的调节参数而提前“泄露”。

更为专业的做法为’将全样本一分为三,其中一部分作为训练集,—部分作为验证集,而另一部分作为测试集。其中,训练集用于训练数据,验证集用于选择调节参数,而测试集则仅用于测试。

这就是关于回归的随机森林方法,接下来讨论分类的随机森林。

二 分类问题的随机森林

在讨论分类问题时,使用R包mlbench的声呐数据Sonar来演示,它包含208个观测值与61个变量,其中响应变量为因子class,表示声呐的回音来自“金属筒”(M)还是“岩石”(R),特征变量共60个(V1~V60),表示不同角度与频道下声呐反射信号的能量。研究的目的在于区分声呐信号来自于金属还是岩石。

首先导入数据集,考察数据的基本特征,并选取训练集和测试集

library(mlbench)
data(Sonar)
dim(Sonar)    #考察数据的维度
#[1] 208  61
table(Sonar$Class)  #考察响应变量的分布情况
# M   R 
111  97 

set.seed(1)
train <- sample(208,158)   #随机选取70%数据作为训练集

其次估计决策树与逻辑回归算法,作为比较随机森林算法的基准

#决策树
library(rpart)
set.seed(123)
fit <- rpart(Class~.,data=Sonar,subset=train)  
min_cp <-  fit$cptable[which.min(fit$cptable[,"xerror"]),"CP"]
min_cp
fit_best <- prune(fit, cp = min_cp)
pred <- predict(fit_best,newdata=Sonar[-train,],type="class")
y.test <- Sonar[-train,"Class"]
(table <- table(pred,y.test))   #混淆矩阵
#    y.test
pred  M  R
   M 24 15
   R  4 22
(error_rate <- 1-sum(diag(table))/sum(table))  #错误率
#[1] 0.2923077

通过单颗修枝后的决策树结果可得出,预测的错误率为28%,其次考虑逻辑回归的预测结果:

#Logit
fit <- glm(Class~.,data=Sonar,subset=train,family=binomial)
prob <- predict(fit,newdata=Sonar[-train,],type="response")
pred <- prob >= 0.5
(table <- table(pred,y.test))
#       y.test
pred     M  R
  FALSE  20  9
  TRUE   6 15
(error_rate <- 1-sum(diag(table))/sum(table))
#[1] 0.3

通过逻辑回归的结果可得出,预测的错误率为30%,下面进行随机森林的估计

#随机森林
fit <- randomForest(Class~.,data=Sonar,subset=train,importance=TRUE)
fit
#Call:
 randomForest(formula = Class ~ ., data = Sonar, importance = TRUE,      subset = train) 
               Type of random forest: classification
                     Number of trees: 500
No. of variables tried at each split: 7

        OOB estimate of  error rate: 17.09%
Confusion matrix:
   M  R class.error
M 78  7  0.08235294
R 20 53  0.27397260

结果显示,函数randomForest()默认使用mtry=7个变量作为候选分裂变量,因为

,袋外误差为18.99%,但金属类的袋外误差为9.41%,而岩石类的袋外误差高达30.14%。使用plot()函数即可同时画这三个袋外误差:

plot(fit,main="OOB Errors",col=c(4,1,1))
legend("topright", colnames(fit$err.rate),lty=1:3,col=c(4,1,1))

在上图中,蓝色实线为整个样本的OOB误差,而另外两条虚线则分别为金属(M类)与岩石(R类)样例的袋外误差。下面查看变量重要性以及影响最大的V11变量的偏依赖图,如下所示

varImpPlot(fit,main="Variable Importance Plot")
partialPlot(fit,Sonar[train,],x.var=V11)

最后考察随机森林的预测效果,如下:

pred <- predict(fit,newdata=Sonar[-train,])
(table <- table(pred, y.test))
#    y.test
pred  M  R
   M 25  7
   R  1 17
(error_rate <- 1-sum(diag(table))/sum(table))
#[1] 0.16

结果显示,随机森林的预测错误率为14%,仅是单棵决策树测错误率的一半,因此随机森林算法在此例的预测效果要优于另外两种方法。

r语言︱决策树族——随机森林算法

R语言︱决策树族——随机森林算法笔者寄语:有一篇《有监督学习选择深度学习还是随机森林或支持向量机?》(作者Bio:SebastianRaschka)中提到,在日常机器学习工作或学习中,当我们遇到有监督学习相关问题时,不妨考虑下先... 查看详情

随机森林算法怎么提高预测数据的准确率

参考技术A不了解什么是随机森林。感觉应该是一种算法。如果做计算机视觉建议你用OpenCV,R语言主要用在统计分析、机器学习领域。你找几篇这方面的文献看看别人跟你做类似课题时是用C++还是R。 查看详情

《机器学习技法》---随机森林

1随机森林bagging的好处是降低各个子分类器的variance,而决策树又是对数据敏感的算法,variance比较大。因此我们很自然地就把bagging用到了决策树。也就是基本的随机森林算法:随机森林的好处是:(1)每棵树并行化学习,非常... 查看详情

机器学习算法整理集成算法—随机森林模型

随机:数据采样随机,特征选择随机(数据采样,有放回)  查看详情

机器学习——随机森林

基础概念随机森林是用随机的方式建立一个森林,森林里面有很多的决策树,并且每一棵决策树之间没有关联。也可说随机森林是决策树的组合模型,其中决策树的组合形式采用的是bagging的方式。Bagging和Boosting(补充理解)Baggi... 查看详情

为机器学习分类器提供深度特征(随机森林)

】为机器学习分类器提供深度特征(随机森林)【英文标题】:FeedDeepFeaturestoMachinelearningClassifiers(Randomforest)【发布时间】:2019-06-2315:21:17【问题描述】:我想将我的CNN深度特征提供给传统分类器,即随机森林,我不想使用MLP(... 查看详情

机器学习(十三)集成学习和随机森林(下)

五、随机森林和Extra-Trees六、AdaBoosting和GradientBoosting七、Stacking       八、学习scikit-learn文档,官方学习文档:http://scikit-learn.org http://scikit-learn.org/stable/user_guide.htm 查看详情

机器学习之随机森林

如果大家想学人工智能的话,那么就一定不能够忽视有关机器学习的内容。这时候就会有人问,什么是机器学习?所谓机器学习就是一门多领域交叉学科,涉及概率论、统计学、逼近论等多门学科。机器学习是专门研究计算机怎... 查看详情

集成学习之随机森林案例专题python机器学习系列(十七)(代码片段)

集成学习之随机森林案例专题【Python机器学习系列(十七)】文章目录1.Bagging与随机森林简介2.随机森林--分类任务2.1准备数据2.2python实现随机森林--分类任务2.3绘制ROC曲线与计算AUC2.4绘制决策树3.随机森林--回归任务集成... 查看详情

简单的机器学习问题(SVM,随机森林

】简单的机器学习问题(SVM,随机森林【英文标题】:Simplemachinelearningproblem(SVM,randomforest【发布时间】:2019-10-0512:42:18【问题描述】:我正在尝试解决机器学习任务,但遇到了一些问题。任何提示将非常感谢。我的一个问题是,... 查看详情

机器学习-决策树和随机森林

随机森林用法:  1.样本的相似度,认为在一个叶子节点的两个样本是相似的,来计算样本相似度矩阵。  2.特征选择:修改节点的特征选择,看预测的结果有没有显著变化,有的话,说明被替换的特征比较重要,反之,不... 查看详情

机器学习(十三)集成学习和随机森林(上)

一、什么是集成学习  二、SoftVotingClassifier 更合理的投票,应该有的权值      三、Bagging和Pasting 四、oob(Out-of-Bag)和关于Bagging的更多讨论     查看详情

r语言随机森林回归(randomforest)模型构建

R语言随机森林回归(randomforest)模型构建目录R语言随机森林回归(randomforest)模型构建 查看详情

机器学习集成学习代码练习(随机森林gbdtxgboostlightgbm等)

代码修改并注释:黄海广importwarningswarnings.filterwarnings("ignore")importpandasaspdfromsklearn.model_selectionimporttrain_test_split生成数据生成12000行的数据,训练集和测试集按照3:1划分fromsklearn.datasetsimportmake_hastie_10_2data, 查看详情

机器学习中的过拟合问题

机器学习中的过拟合问题相关内容:1、 R语言︱ROC曲线——分类器的性能表现评价 2、机器学习中的过拟合问题3、R语言︱机器学习模型评估方案(以随机森林算法为例)  ——————————————————... 查看详情

机器学习知识点查漏补缺(随机森林和extratrees)

随机森林对数据样本及特征随机抽取,进行多个决策树训练,防止过拟合,提高泛化能力 一般随机森林的特点:1、有放回抽样(所以生成每棵树的时候,实际数据集会有重复),2、以最优划分分裂GivenastandardtrainingsetDofsizen,... 查看详情

r语言基于随机森林进行特征选择(featureselection)

R语言基于随机森林进行特征选择(featureselection)目录R语言基于随机森林进行特征选择(featureselection) 查看详情

机器学习集成学习(bagging)——随机森林(randomforest)(理论+图解+公式推导)

...创作者,带你从入门到精通,该博客每天更新,逐渐完善机器学习各个知识体系的文章,帮助大 查看详情