R语言随机森林分析全流程

R语言随机森林全流程分析

引言

再2023年6月,如果你以Random Forest为关键词在Google Scholar检索,时间降序。

image-20230626173703705

你会发现这些方法用于各个领域的研究:GIS、环境、遥感(只要有大数据)

发表的期刊水平也参差不齐,有Frontiers、Remote Sensing(MDPI)、总环。

除了很少有顶尖期刊,但也不乏还不错的期刊,从一区到四区。为何这个方法一直在使用?这就引出了随机森林的几个优点。

随机森林是集成学习(Ensemble Learning),集成学习的基本思想就是将多个分类器组合,从而实现一个预测效果更好的集成分类器。

随机森林既可以胜任分类任务又可以胜任回归任务。机器学习中有两种任务,回归和分类,而随机森林可以同时胜任这两种任务。其中分类任务是对离散值进行预测(比如将一景图像中的植被,建筑,水体等地物类型分类);回归任务是对连续值进行预测(比如根据已有的数据预测明天的气温是多少度,预测明天某基金的价格)。

随机森林能评估特征的相对重要性。集成学习模型的一大特点是可以输出特征重要性,特征重要性能够在一定程度上辅助我们对特征进行筛选,从而使得模型的鲁棒性更好。在实际研究中,也能提供一定的物理意义。

代码实现

借助于R语言的高效数据分析,我们使用R的randomForest包实现这一效果

数据集载入

首先加载数据集:

library(tidyverse)
data(airquality)
airquality <- airquality %>% na.omit()
airquality
image-20230626174902091

airquality数据集中,Ozone是臭氧变量,其它太阳辐射Solar.R、风速Wind和温度Temp等等对臭氧的影响。

数据训练

这里首先把数据集划分训练集(70%)测试集(30%)

使用randomForest开始训练,其中Ozone~代表臭氧Ozone为因变量,其它数据为自变量。

# To evaluate the performance of RF
# split traning data (70%) and validation data (30%)
set.seed(123)
train <- sample(nrow(airquality), nrow(airquality)*0.7)
ozo_train <- airquality[train, ]
ozo_test <- airquality[-train, ]
 
# randomForest
library(randomForest)
 
# Random forest calculation(default 500 tress),please see ?randomForest
set.seed(123)
ozo_train.forest <- randomForest(Ozone~., data = ozo_train, importance = TRUE)
ozo_train.forest

结果如图:

  • 结果中,% Var explained体现了预测变量(太阳辐射,温度,降水和时间变量)对响应变量(臭氧)有关方差的整体解释率。

  • 解释了约70.44%的总方差,可以理解为该回归的R2=70.44,相当可观的一个数值,表明臭氧与这些变量密切相关

可视化结果

接下来可视化随机森林的回归效果:

# Scatterplot
library(ggplot2)
library(ggExtra)
library(ggpmisc)
library(ggpubr)

g <- ggplot(train_test, aes(obs, pre)) + 
  geom_point() + 
  geom_smooth(method="lm", se=F) +
  geom_abline(slope = 1,intercept = 0,lty="dashed") +
  stat_poly_eq(
    aes(label =paste( ..adj.rr.label.., sep = '~~')),
    formula = y ~ x,  parse = TRUE,
      family="serif",
      size = 6.4,
      color="black",
      label.x = 0.1,  #0-1之间的比例确定位置
      label.y = 1)

g1 <- ggMarginal(g, type = "histogram", fill="transparent")
g <- ggplot(predict_test, aes(obs, pre)) + 
  geom_point() + 
  geom_smooth(method="lm", se=F) +
  geom_abline(slope = 1,intercept = 0,lty="dashed") +
  stat_poly_eq(
    aes(label =paste( ..adj.rr.label.., sep = '~~')),
    formula = y ~ x,  parse = TRUE,
      family="serif",
      size = 6.4,
      color="black",
      label.x = 0.1,  #0-1之间的比例确定位置
      label.y = 1)

g2 <- ggMarginal(g, type = "histogram", fill="transparent")
ggarrange(g1, g2, ncol = 2)
# ggMarginal(g, type = "boxplot", fill="transparent")
# ggMarginal(g, type = "density", fill="transparent")

如图所示,在训练集的拟合效果很好,R2可达0.94

在测试集上表现也较好,R2可达0.71

重要性评估

接下来查看变量重要性

##Ozo 的重要性评估
importance_ozo <- ozo_train.forest$importance
importance_ozo
importance_plot <- tibble(var = rownames(importance_ozo), 
                          IncMSE = importance_ozo[,1],
                          IncNodePurity = importance_ozo[,2])

%IncMSE即increase in mean squared error,通过对每一个预测变量随机赋值,如果该预测变量更为重要,那么其值被随机替换后模型预测的误差会增大。因此,该值越大表示该变量的重要性越大;

IncNodePurity即increase in node purity,通过残差平方和来度量,代表了每个变量对分类树每个节点上观测值的异质性的影响,从而比较变量的重要性。该值越大表示该变量的重要性越大。

对于%IncMSEIncNodePurity,二选一作为判断预测变量重要性的指标。需注意的是,二者的排名存在一定的差异。

image-20230626175657726

对重要性排序进行可视化:

p1 <- ggplot(importance_plot, aes(x=var, y=IncMSE)) +
  geom_segment( aes(x=var, xend=var, y=0, yend=IncMSE), color="skyblue") +
  geom_point( color="blue", size=4, alpha=0.6) +
  theme_light() +
  coord_flip() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank()
  )
  p2 <- ggplot(importance_plot, aes(x=var, y=IncNodePurity)) +
  geom_segment( aes(x=var, xend=var, y=0, yend=IncNodePurity), color="skyblue") +
  geom_point( color="blue", size=4, alpha=0.6) +
  theme_light() +
  coord_flip() +
  theme(
    panel.grid.major.y = element_blank(),
    panel.border = element_blank(),
    axis.ticks.y = element_blank()
  )
ggarrange(p1, p2, ncol = 2)

可以看到,温度Temp是臭氧的一个主要因素

交叉验证

接下来进行五折交叉验证,来选取超参数(这里是变量个数):

  • replicate用于重复n次所需语句,这里进行5次五折交叉验证
  • rfcv通过嵌套交叉验证程序显示模型的交叉验证预测性能,模型的预测器数量按顺序减少(按变量重要性排序)。
  • step如果log=TRUE,则为每个步骤要删除的变量的分数,否则一次删除这么多变量
  • cv.fold为折数
#5 次重复五折交叉验证
set.seed(111)
ozo_train.cv <- replicate(5, rfcv(ozo_train[-ncol(ozo_train)], ozo_train$Ozone, cv.fold = 5, step = 0.8), simplify = FALSE)
#ozo_train.cv
ozo_train.cv <- data.frame(sapply(ozo_train.cv, '[[', 'error.cv'))
ozo_train.cv$vars <- rownames(ozo_train.cv)
ozo_train.cv <- reshape2::melt(ozo_train.cv, id = 'vars')
ozo_train.cv$vars <- as.numeric(as.character(ozo_train.cv$vars))
 
ozo_train.cv.mean <- aggregate(ozo_train.cv$value, by = list(ozo_train.cv$vars), FUN = mean)
ozo_train.cv.mean

可视化误差结果

ggplot(ozo_train.cv.mean, aes(Group.1, x)) +
    geom_line() +
    labs(title = '',x = 'Number of vars', y = 'Cross-validation error')

根据交叉验证曲线,提示保留1个重要的变量(或前四个重要的变量)获得理想的回归结果,因为此时的误差达到最小。

因此,根据计算得到的各ozone重要性的值(如“IncNodePurity”),将重要性由高往低排序后,最后大约选择前4个变量就可以了。

#首先根据某种重要性的高低排个序,例如根据“IncNodePurity”指标
importance_ozo <- importance_plot[order(importance_plot$IncNodePurity, decreasing = TRUE), ]
 
#然后取出排名靠前的因素
importance_ozo.select <- importance_ozo[1:4, ]
vars <- c(pull(importance_ozo.select, var), 'Ozone')
ozo.select <- airquality[ ,vars]
ozo.select <- reshape2::melt(ozo.select, id = 'Ozone')

# 查看下这些重要的 vars 与Ozone的关系
ggplot(ozo.select, aes(x = Ozone, y = value)) +
    geom_point() +
    geom_smooth() +
    facet_wrap(~variable, ncol = 2, scale = 'free_y') +
    labs(title = '',x = 'Ozone', y = 'Relative abundance')

这就是R语言进行随机森林分析的全流程了,希望对大家的科研有所帮助。

本文由mdnice多平台发布

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容