前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >生信小课堂(3) R中执行并行运算

生信小课堂(3) R中执行并行运算

作者头像
R语言数据分析指南
发布2023-10-08 15:47:13
6070
发布2023-10-08 15:47:13
举报
文章被收录于专栏:R语言数据分析指南

欢迎关注R语言数据分析指南

❝今天有朋友询问如何在R中进行并行运算,那本节就来简单介绍下,并行运算的方式有很多,在此主要介绍「foreach & doParallel」。下面小编通过几个小例子及对penguins数据集进行随机森林分析的具体例子来进行介绍,过程仅供参考。 ❞

加载R包

代码语言:javascript
复制
install.packages("foreach")
install.packages("doParallel")
install.packages("randomForest")
library(foreach)
library(doParallel)
library(randomForest)
library(palmerpenguins)
library(tidyverse)
library(ranger)

循环计算

代码语言:javascript
复制
x <- vector()
for(i in 1:10){
  x[i] <- sqrt(i)}
x

foreach构建循环

代码语言:javascript
复制
x <- foreach(
  i = 1:10000, 
  .combine = 'c') %do% {sqrt(i)}
x

❝foreach使用运算符%do%,会按顺序处理任务。要并行运行任务可以使用运算符%dopar%,该运算符必须得到并行后端的支持。不然会产生警告信息 ❞

代码语言:javascript
复制
x <- foreach(
  i = 1:10000, 
  .combine = 'c') %dopar% {
  sqrt(i)
}
代码语言:javascript
复制
Warning message:
executing %dopar% sequentially: no parallel backend registered

设置并行计算

代码语言:javascript
复制
parallel::detectCores() # 检测可用的CPU核心数量
# 设置核心数量为总核心数减一
n.cores <- parallel::detectCores() - 1
# 创建一个集群
my.cluster <- parallel::makeCluster(n.cores, type = "PSOCK")
# 使用doParallel包注册这个集群方便后续使用
doParallel::registerDoParallel(cl = my.cluster)

foreach::getDoParRegistered() # 检查并行设置
foreach::getDoParWorkers()   # 返回线程数

经过上面的设置在执行并行计算就不会出现警告信息

代码语言:javascript
复制
x <- foreach(
  i = 1:10000, 
  .combine = 'c') %dopar% {
  sqrt(i)
}

penguins数据集进行随机森林分析

构建数据
代码语言:javascript
复制
penguins <- penguins %>%
  select(species, bill_length_mm, bill_depth_mm,
  flipper_length_mm, body_mass_g) %>% 
  drop_na()
使用ranger包计算特征的重要性
  • 使用ranger函数从ranger包中拟合随机森林模型。
  • 设置importance参数为permutation,以计算基于排列的特征重要性。
代码语言:javascript
复制
m <- ranger::ranger(
  data = penguins,                       # 使用penguins数据
  dependent.variable.name = "species",   # 设置因变量为species
  importance = "permutation"             # 设置importance参数为permutation
)

# 打印模型的特征重要性
m$variable.importance
创建超参数的组合
代码语言:javascript
复制
sensitivity.df <- expand.grid(
  num.trees = c(500, 1000, 1500),        # 考虑三种不同的num.trees值
  mtry = 2:4,                            # 考虑三种mtry值
  min.node.size = c(1, 10, 20)           # 考虑三种min.node.size值
)
使用foreach函数并行地为每种超参数组合拟合模型
代码语言:javascript
复制
prediction.error <- foreach(
  num.trees = sensitivity.df$num.trees,      # 设置num.trees的值
  mtry = sensitivity.df$mtry,                # 设置mtry的值
  min.node.size = sensitivity.df$min.node.size, # 设置min.node.size的值
  .combine = 'c',                            # 结果合并方式为连接
  .packages = "ranger"                       # 加载ranger包
) %dopar% {
  
  # 使用ranger函数拟合随机森林模型
  m.i <- ranger::ranger(
    data = penguins,                       # 使用penguins数据
    dependent.variable.name = "species",   # 设置因变量为species
    num.trees = num.trees,                 # 设置num.trees的值
    mtry = mtry,                           # 设置mtry的值
    min.node.size = min.node.size          # 设置min.node.size的值
  )
  
  # 返回模型的预测误差(百分比)
  return(m.i$prediction.error * 100)
  
}
将预测误差添加到sensitivity.df数据框
代码语言:javascript
复制
sensitivity.df$prediction.error <- prediction.error
选择最佳组合
代码语言:javascript
复制
best.hyperparameters <- sensitivity.df %>% 
  dplyr::arrange(prediction.error) %>% 
  dplyr::slice(1)

# 定义一个函数将模型的特征重要性转换为数据框
importance_to_df <- function(model){
  x <- as.data.frame(model$variable.importance) # 将特征重要性转换为数据框
  x$variable <- rownames(x)                    # 添加变量名列
  colnames(x)[1] <- "importance"               # 重命名第一列为"importance"
  rownames(x) <- NULL                          # 删除行名
  return(x)                                    # 返回数据框
}
并行计算特征的重要性
代码语言:javascript
复制
system.time(
  importance.scores <- foreach(i = 1:1000,    # 进行1000次迭代
    .combine = 'rbind',                    
    .packages = "ranger"     # 加载ranger包
  ) %dopar% {
    # 使用ranger函数拟合随机森林模型
    m.i <- ranger::ranger(
      data = penguins,                       # 使用penguins数据
      dependent.variable.name = "species",   # 设置因变量为species
      importance = "permutation",            # 设置importance参数为permutation
      mtry = best.hyperparameters$mtry,      # 使用最佳的mtry值
      num.trees = best.hyperparameters$num.trees, # 使用最佳的num.trees值
      min.node.size = best.hyperparameters$min.node.size # 使用最佳的min.node.size值
    )

    # 使用importance_to_df函数转换特征重要性为数据框
    m.importance.i <- importance_to_df(model = m.i)
    return(m.importance.i)
    
  }
  
)
代码语言:javascript
复制
# user  system elapsed 
# 0.151   0.026   3.805 
for循环计算特征的重要性
代码语言:javascript
复制
importance.scores.list <- list()

system.time(
  for(i in 1:1000){
    m.i <- ranger::ranger(
      data = penguins,                       # 使用penguins数据
      dependent.variable.name = "species",   # 设置因变量为species
      importance = "permutation",            # 设置importance参数为permutation
            seed = i,                              # 设置随机种子以确保每次迭代的结果是可重复的
      num.threads = parallel::detectCores() - 1 # 使用所有可用的核心进行计算,除了一个
    )
    importance.scores.list[[i]] <- importance_to_df(model = m.i)
    
  }
)
代码语言:javascript
复制
##    user  system elapsed 
##  43.663   2.815  12.948

代码语言:javascript
复制
parallel::stopCluster(cl = my.cluster)

可以看到并行计算香对于多核串行计算在提高效率方面说有大的提高,本节内容介绍到此结束过程仅供参考;

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-10-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 R语言数据分析指南 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 欢迎关注R语言数据分析指南
  • 加载R包
  • 循环计算
  • foreach构建循环
  • 设置并行计算
  • penguins数据集进行随机森林分析
    • 构建数据
      • 使用ranger包计算特征的重要性
        • 创建超参数的组合
          • 使用foreach函数并行地为每种超参数组合拟合模型
            • 将预测误差添加到sensitivity.df数据框
              • 选择最佳组合
                • 并行计算特征的重要性
                  • for循环计算特征的重要性
                  相关产品与服务
                  GPU 云服务器
                  GPU 云服务器(Cloud GPU Service,GPU)是提供 GPU 算力的弹性计算服务,具有超强的并行计算能力,作为 IaaS 层的尖兵利器,服务于生成式AI,自动驾驶,深度学习训练、科学计算、图形图像处理、视频编解码等场景。腾讯云随时提供触手可得的算力,有效缓解您的计算压力,提升业务效率与竞争力。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档