随机森林算法介绍及多分类预测的R实现

news2024/9/23 9:31:55

随机森林(Random Forest)是一种经典的机器学习算法,是数据科学家中最受欢迎和常用的算法之一,最早由Leo Breiman和Adele Cutler于2001年提出。它是基于集成学习(Ensemble Learning)的一种方法,通过组合多个决策树来进行预测和分类,在回归问题中则取平均值。其最重要的特点之一是能够处理包含连续变量和分类变量的数据集。在本文中,我们将详细了解随机森林的工作原理,介绍其在R中的实现及其优缺点。

1. 算法基本原理

1) 随机抽样:在随机森林中,每个决策树的训练样本都是通过随机抽样得到的。随机抽样是指从原始训练集中有放回地抽取一部分样本,构成一个新的训练集。这样做的目的是使得每个决策树的训练样本略有差异,增加决策树之间的多样性。

2) 随机特征选择:在每个决策树的节点上,随机森林算法会从所有特征中随机选择一部分特征进行分割。这样做的目的是增加每个决策树之间的差异性,防止某些特征过于主导整个随机森林的决策过程。

3) 决策树构建:使用随机采样的数据和随机选择的特征,构建多个决策树。决策树的构建过程中,采用通常的决策树算法(如ID3、CART等)。

4) 随机森林的预测:当新的样本输入到随机森林中时,它会经过每个决策树的预测过程,最后根据决策集成的方式得到最终的预测结果。对于分类问题,最常见的集成方式是采用多数投票,即根据每个决策树的分类结果进行投票,选择获得最多票数的类别作为最终的预测结果。对于回归问题,可以采用平均预测的方式,即将每个决策树的预测值取平均作为最终的预测结果。n

通过随机抽样和随机特征选择,随机森林算法能够减少过拟合风险,提高模型的泛化能力。同时,通过集成多个决策树的预测结果,随机森林能够获得更稳定和准确的预测。

2. 随机森林算法的R实现

以鸢尾花数据集为例,加载需要的包及数据集,未安装的需要先安装。

 

library(randomForest)
library(datasets)
library(caret)

data<-iris
str(data)

数据集包含150个观测值和5个变量。物种被视为响应变量,为因子变量。

data$Species <- as.factor(data$Species)
table(data$Species)

可以看到结局变量各个分类分布平衡。

1)首先进行随机抽样。

set.seed(222)
ind <- sample(2, nrow(data), replace = TRUE, prob = c(0.7, 0.3))
train <- data[ind==1,]
test <- data[ind==2,]

其中测试集中有106个sample,训练集中有44个sample。

2)然后进行模型构建,这里使用默认参数拟合随机森林模型。

rf <- randomForest(Species~., data=train, proximity=TRUE)

3)参数调整

参数调整是优化随机森林模型性能的重要步骤。下面是一些常用的参数调整方法:

树的数量(ntree):增加树的数量可以提高模型的稳定性和准确性,但也会增加计算时间。一般来说,增加树的数量直到模型性能趋于稳定为止。

特征数(mtry):mtry参数控制每个决策树在分裂节点时随机选择的特征数。较小的mtry值会增加树之间的差异性,但可能会降低模型的准确性。较大的mtry值会增加模型的稳定性,但可能会导致模型过度拟合。一般推荐使用默认值sqrt(p),其中p是特征的总数。

决策树的最大深度(max_depth):限制决策树的最大深度可以防止过度拟合。通过限制最大深度,可以控制模型的复杂度并提高泛化能力。

节点分割的最小样本数(min_samples_split):限制节点分割所需的最小样本数可以控制决策树的生长。较小的值会增加模型的复杂性,可能导致过度拟合。较大的值会限制模型的生长,可能导致欠拟合。选择合适的值需要根据数据集的大小和特征的分布进行调整。

节点分割的最小准则(criterion):决定节点分割的准则,常用的有基尼系数(gini)和信息增益(entropy)。这两个准则在大多数情况下表现相似,通常选择默认值基尼系数。

其他参数:还有其他一些参数可以调整,如样本权重、叶节点最小样本数等,根据具体问题进行调整。

# 如果需要调整参数,可以使用tuneRF()函数进行自动调参。

tuned_rf_model <- tuneRF(train[, -5], train[, 5], ntreeTry = 500,

                       stepFactor = 1.5, improve = 0.01, trace = TRUE,

                       plot = TRUE)

 

可以看到mtry=3时,OOBerror最小,因此模型中应该设置mtry=3。

在进行参数调整时,可以使用交叉验证来评估模型性能,并选择表现最好的参数组合。例如,可以使用k折交叉验证,将训练集分成k个子集,每次使用其中k-1个子集作为训练数据,剩余一个子集作为验证数据,重复进行k次并计算平均性能指标。

R中的caret包为调整机器学习算法的参数提供了一个很好的工具。但并非所有的机器学习算法都可以在caret中进行调整。只有那些影响较大的算法参数才可以在caret中进行调整。因此,caret中只有mtry参数可供调谐。原因是它对最终准确度的影响,而且它必须根据经验为一个数据集找到。ntree参数则不同,它可以随心所欲地放大,并在一定程度上继续提高精度。它的调整不那么困难或关键,而且可能更多的是受到可用计算时间的限制。

R中实现方式如下:

# 定义参数网格
rf_grid <- expand.grid(mtry = seq(2, 6, by = 1))

# 设置交叉验证方案
control <- trainControl(method = "cv", number = 10)

# 运行交叉验证
rf_model <- train(Species ~ ., data = train, method = "rf", trControl = control, tuneGrid = rf_grid, importance = TURE

# 输出最佳参数组合和性能指标
print(rf_model$bestTune)

print(rf_model$results)

可以看到在mtry=3时,Accuracy最高。

best_model <- rf_model$finalModel

将调优后的参数赋值给best_model。

在上面的代码中,我们首先将数据集划分为训练集和测试集。然后定义了一个包含参数范围(mtry)的网格。接下来,使用trainControl()函数设置了一个十折折交叉验证方案,并运行train()函数来进行模型拟合和性能评估。最后,输出了最佳参数组合和各个参数组合下的性能指标。需要注意的是,在实际应用中,可能需要尝试多个不同的参数网格,并对每个网格进行交叉验证以选择最优参数组合。

3)接下来在测试集中进行预测。

# 预测测试集数据
predictions <- predict(best_model, newdata = test)

# 绘制混淆矩阵
result_matrix<-confusionMatrix(table(predictions, test$Species))
result_matrix

混淆矩阵中显示了预测各个类别的敏感性,特异性等指标,总体Accuracy为0.9388,具有很好的预测效能。

#模型的各个类别预测效能

result_matrix$byClass

#预测各个类别概率

rf_pred <- predict(best_model, test, type = 'prob')
rf_pred <- data.frame(rf_pred)
colnames(rf_pred) <- paste0(colnames(rf_pred), "_pred_RF")

构建绘图数据,该部分在我前面的博客里也讲过做法,详情见http://t.csdn.cn/Z8yGi,这里再呈现一下。

Library(multiROC)
true_label <- dummies::dummy(test_df$Species, sep = ".")
true_label <- data.frame(true_label)
colnames(true_label) <- gsub(".*?\\.", "", colnames(true_label))
colnames(true_label) <- paste(colnames(true_label), "_true")
final_df <- cbind(true_label, rf_pred)
roc_res <- multi_roc(final_df, force_diag=F)
pr_res <- multi_pr(final_df, force_diag=F)
plot_roc_df <- plot_roc_data(roc_res)
plot_pr_df <- plot_pr_data(pr_res)
##AUC值
auc_value<-roc_res_value$AUC
auc_num<-unlist(auc_value)

# 绘制ROC曲线
require(ggplot2)
ggplot(plot_roc_df, aes(x = 1-Specificity, y=Sensitivity)) +
 geom_path(aes(color = Group), size=1.5) +
 geom_segment(aes(x = 0, y = 0, xend = 1, yend = 1),
              colour='grey', linetype = 'dotdash') +
 theme_bw() +
  theme(plot.title = element_text(hjust = 0.5),
       legend.justification=c(1, 0), legend.position=c(.95, .05),
       legend.title=element_blank(),
       legend.background = element_rect(fill=NULL, size=0.5,
                                      linetype="solid", colour ="black"))

评估变量重要性

Importance(best_model)

此处“Mean Decrease Accuracy”和“Mean Decrease Gini”为随机森林模型中的两个重要指标。其中,“mean decrease accuracy”表示随机森林预测准确性的降低程度,该值越大表示该变量的重要性越大;“mean decrease gini”计算每个变量对分类树每个节点上观测值的异质性的影响,从而比较变量的重要性。该值越大表示该变量的重要性越大。

3. 算法优缺点

1)随机森林算法相比于其他机器学习算法具有以下优势

高准确性:通过组合多个决策树,利用集成学习的方式提高了预测的准确性。它能够处理大量的训练数据,并且对于噪声和缺失数据具有较好的鲁棒性。

可扩展性:可以有效地处理具有大量特征的数据集,并且能够处理高维度的输入。它可以在较短的时间内对大规模数据集进行训练,并且具有较快的预测速度。

特征选择:可以通过计算特征的重要性来评估每个特征对于预测的贡献程度。这可以帮助我们识别出对于问题最为重要的特征,从而进行特征选择和降维,提高模型的效率和性能。

抗过拟合:通过随机选择训练样本和特征的方式,降低了单个决策树过拟合的风险。同时,随机森林中的多个决策树进行投票或平均预测,可以减少模型的方差,提高了泛化能力。

处理非线性关系:能够有效地处理非线性关系,不需要对数据进行过多的预处理或进行特征工程。它可以捕捉到特征之间的复杂非线性关系,从而更好地拟合数据。

鲁棒性:对于缺失值和噪声具有较好的鲁棒性。它可以处理具有缺失值的数据,并且对于噪声和异常值的影响较小。

总的来说,随机森林算法在准确性、可扩展性、特征选择、抗过拟合、处理非线性关系和鲁棒性等方面都具有优势,因此在许多实际应用中被广泛采用。

2)缺点

决策边界的不连续性:由于随机森林是由多个决策树组成的,因此它的决策边界是由决策树的集合构成的。这可能导致决策边界出现不连续的情况,对于某些问题可能不够精细。

训练时间较长:相比于一些简单的线性模型,随机森林的训练时间可能较长。因为它需要构建多个决策树并进行集成,每个决策树的构建都需要消耗时间。

难以解释性:算法的预测结果可能较难以解释。由于它是由多个决策树集成而成,决策树之间的复杂关系可能使得解释模型的预测过程变得困难。

对于高维稀疏数据不太适用:在处理高维稀疏数据时可能表现不佳。由于决策树在高维空间中容易出现过拟合问题,而随机森林的集成学习也无法完全克服这个问题。

超参数调优的挑战:有多个超参数需要调优,如决策树数量、最大深度等。在实际应用中,选择合适的超参数可能需要一定的经验和调试,增加了调优的难度。

需要注意的是,随机森林算法的优势和缺点是相对于其他机器学习算法而言的,不同的算法在不同的问题和数据集上可能具有不同的表现。在实际应用中,选择合适的算法要根据具体问题的特点和需求进行综合考量。

Reference:

https://linuxcpp.0voice.com/?id=89171

https://stackoverflow.com/questions/34169774/plot-roc-for-multiclass-roc-in-proc-package

http://t.csdn.cn/T6mFJ

更多信息与交流,欢迎关注公众号:单细胞学会

直接扫描下方二维码:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/713638.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库选型sql和nosql

一、数据库选型sql和nosql&#xff1a; 1.1关系型数据库sql和非关系型数据库nosql 1.2关系型数据库特点&#xff1a; 数据结构化存储在二维表中 支持事务的原子性A,一致性C,隔离性I持久性D 特性 支持使用SQL语言对存储在其中的数据进行操作 1.3关系型数据库的适用场景&…

pwn(7.3)

Nc 通过nc&#xff0c;我们可以链接到对方的服务器 再用过Linux的命令可以查找到我们想要的信息 Ret2txt 先查壳 没开任何保护&#xff0c;拿IDA看看 很明显的栈溢出&#xff0c;看到/bin/sh地址 解释&#xff0c;通过汇编语言我们知道调用函数使用call命名&#xff0c;c…

HNU-小学期工训-STC-B案例测试作业

对于一些案例&#xff0c;这里列举一些 流水灯 八位数码管动态扫描 八位数码管流水灯(有BSP版本) 八位数码管滚动显示(有BSP版本) 可变亮度的数码管显示(有BSP版本) 扫描频率可改变的电子钟 按键消抖计数(有BSP版本) 三按键测试(有BSP版本) 霍尔磁场检测(有BSP版本) 数…

精通ES+ES大数据查询常见的疑难杂症的解决与实现

目录 什么是BoolQueryBuilder&#xff1f; 简单的复合查询 RestHighLevelClient中的matchQuery与matchPhraseQuery与termQuery的在实际使用中的不同 ES是否能在类型为text的字段的内部使用keyword&#xff0c;如果能这样做的含义是什么&#xff1f; 什么是ES多字段&#xf…

BES 的BLE MTU设置

1 BES BLE MTU 一个默认的MTU大小&#xff0c;通常为23字节&#xff0c;通过协商&#xff0c;可以使用更大的MTU&#xff0c;最高可达512字节&#xff0c; 2 协商方法

leetcode146.手撸 LRU 算法(java)

LRU 缓存 LRU 缓存题目描述LRU 介绍LRU 算法设计代码实现 单调栈算法 LRU 缓存 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/lru-cache 题目描述 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实…

HNU-小学期工训-STC-B测试记录表

说明1“分类I”为检测电路板硬件测试案例&#xff0c;“分类ⅡI、Ⅲ、IV”为不同层次综合应用案例。"分类1、Ⅱ、Ⅲ”必做&#xff0c;“分类TV”选做。 说明2:“测试/故障现象记录”栏:记录实际测量效果并与案例说明对比&#xff0c;并记录;有故障时&#xff0c;记录所见…

《AutoSar实战》读写DID之一:CDD准备

文章目录 前言一、1.新建DID1&#xff0c;使用 **CANdelaStudio** 软件打开工程中的CDD文件并创建DID1) 创建DID2) 详细配置DID3&#xff09;配置读写服务权限 二、同步更新工具链配置1 更新文件并检查1&#xff09; 更新CDD文件2&#xff09;检查更新结果 总结 前言 本章节主…

大型语言模型与知识图谱协同研究综述:两大技术优势互补

机器之心报道 编辑&#xff1a;杜伟 多图综述理清当前研究现状&#xff0c;这篇 29 页的论文值得一读。 大型语言模型&#xff08;LLM&#xff09;已经很强了&#xff0c;但还可以更强。通过结合知识图谱&#xff0c;LLM 有望解决缺乏事实知识、幻觉和可解释性等诸多问题&am…

记录一下kibana启动连接报错问题(kibana server is not ready yet)

记录一下kibana启动连接报错问题(kibana server is not ready yet) 今天启动kibana出现该问题 先去看了看是否是elasticsearch连接出错 启动了容器 docker start elasticsearch docker start kibana进入了kibana容器 docker exec -it kibana bash进行了下面的操作&#xf…

注册微信小程序平台安装微信小程序开发工具(详细教程)

首先我们先去微信小程序平台注册账号&#xff0c;下面是网址 首页 | 微信开放社区 进入后&#xff0c;使用手机扫描登录&#xff0c;然后&#xff0c;选择小程序&#xff0c;选择个体——填写个人信息——进入到开发者平台&#xff08;相信这里对一个开发者很简单了吧&#xff…

API安全测试检查项小结

现如今开发基本上都是前后端分离&#xff0c;相比前端&#xff0c;后端的测试是最容易发现一些底层bug, 修复成本也低。今天主要聊聊接口的安全测试&#xff0c;以及常见的漏洞。 一、逻辑越权类 可以分为两类&#xff1a;平行越权&#xff1a;权限类型不变&#xff0c;权限对…

单线程JavaScript为何如此高效

什么是js执行机制 JavaScript 的执行机制指的是 JavaScript 代码在运行时的工作方式和顺序。它涉及以下几个关键概念&#xff1a; 单线程&#xff1a;JavaScript 是一门单线程的编程语言&#xff0c;意味着它只有一个主线程用于执行代码。这意味着 JavaScript 中的代码是按顺序…

编程(43)----------ConcurrentHashMap

在多线程中使用哈希表, 首先是不能使用HashMap的. 因为其本身并非线程安全. 与其相反HashTable则是安全的. 其原因在于本身给关键的方法加了锁. 但即便如此, 与HashTable相比, 更推荐使用ConcurrentHashMap. 其原因在于, 它在HashTable的基础上做了较多的优化: 上述提到, Hash…

自从前端用上了低代码,开发速度直接起飞

作为前端工作人员&#xff0c;我们都深知在这个快速发展的时代里&#xff0c;不断学习和掌握前沿技术是至关重要的。随着互联网的不断革新和新兴技术的崛起&#xff0c;我们需要保持敏锐的触角&#xff0c;紧跟潮流&#xff0c;才能在竞争激烈的市场中保持领先地位。 一直以来&…

MAC电脑垃圾好用的文件清理软件CleanMyMac X

古语云&#xff1a;“工欲善其事&#xff0c;必先利其器。”因此&#xff0c;一个运行流畅的Mac更能使我们的工作事半功倍。但又是什么导致电脑的运行不流畅呢&#xff1f; 其实这大多还是缓存垃圾过多、内存不足的原因。尝试安装了许多的垃圾文件清理软件&#xff0c;垃圾没有…

HashMap 为什么不能一边遍历一遍删除

前段时间&#xff0c;同事在代码中 KW 扫描的时候出现这样一条&#xff1a; 上面出现这样的原因是在使用 foreach 对 HashMap 进行遍历时&#xff0c;同时进行 put 赋值操作会有问题&#xff0c;异常 ConcurrentModificationException。 于是帮同简单的看了一下&#xff0c;印象…

为什么Qt成为工业软件开发的首选框架?

工业软件开发中使用Qt的主要原因有以下几点&#xff1a; 跨平台性&#xff1a;Qt是一个跨平台的C应用程序开发框架&#xff0c;可以在多个操作系统上运行&#xff0c;包括Windows、macOS、Linux等。这种跨平台性使得开发人员能够使用相同的代码库创建适用于不同操作系统的应用程…

Github-Readme-Stats 简明教程

注&#xff1a;本篇文章首发于 博客园sarexpine 为保持阅读的舒适性&#xff0c;可以选择移步至 博客园sarexpine 阅读&#xff0c;日后的文章将首发于 博客园sarexpine 平台&#xff0c;谢谢&#xff01; 1. 更新 Readme 文件 在你想要放置 Readme-WakaTime 的位置中放置以下…

Nginx【Nginx场景实践(动静分离、动静分离实战、缓存机制)】(十)-全面详解(学习总结---从入门到深化)

目录 Nginx场景实践_动静分离 Nginx场景实践_动静分离实战 Nginx场景实践_缓存机制 Nginx场景实践_动静分离 Nginx动静分离简单来说就是把动态和静态请求分开&#xff0c;不能理解成只是单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求和静态请求分开&…