【问题标题】:How to use expand.grid values to run various model hyperparameter combinations for ranger in R如何使用 expand.grid 值在 R 中运行 Ranger 的各种模型超参数组合
【发布时间】:2020-07-11 16:12:03
【问题描述】:

我看过各种帖子,介绍如何使用 expand.grid 为模型选择自变量,然后根据该选择创建公式。但是,我事先准备好输入表并将它们存储在列表中。

library(ranger)
data(iris)
Input_list <- list(iris1 = iris, iris2 = iris)  # let's assume these are different input tables

我很想为我的输入表列表尝试给定算法的所有可能超参数组合(此处:使用ranger 的随机森林)。我执行以下操作来设置网格:

hyper_grid <- expand.grid(
  Input_table = names(Input_list),
  Trees = c(10, 20),
  Importance = c("none", "impurity"),
  Classification = TRUE,
  Repeats = 1:5,
  Target = "Species")

> head(hyper_grid)
  Input_table Trees Importance Classification Repeats  Target
1       iris1    10       none           TRUE       1 Species
2       iris2    10       none           TRUE       1 Species
3       iris1    20       none           TRUE       1 Species
4       iris2    20       none           TRUE       1 Species
5       iris1    10   impurity           TRUE       1 Species
6       iris2    10   impurity           TRUE       1 Species

我的问题是,将这些值传递给模型的最佳方式是什么?目前我正在使用for loop

for (i in 1:nrow(hyper_grid)) {
  RF_train <- ranger(
    dependent.variable.name = hyper_grid[i, "Target"], 
    data = Input_list[[hyper_grid[i, "Input_table"]]],  # referring to the named object in the list
    num.trees = hyper_grid[i, "Trees"], 
    importance = hyper_grid[i, "Importance"], 
    classification = hyper_grid[i, "Classification"])  # otherwise regression is performed
  print(RF_train)
}

遍历网格的每一行。但是一方面,我现在必须告诉模型它是分类还是回归。我假设因子Species 被转换为数字因子水平,因此默认情况下会发生回归。有没有办法防止这种情况并使用例如apply 这个角色?这种迭代方式也会导致函数调用混乱:

Call:
 ranger(dependent.variable.name = hyper_grid[i, "Target"], data = Input_list[[hyper_grid[i,      "Input_table"]]], num.trees = hyper_grid[i, "Trees"], importance = hyper_grid[i,      "Importance"], classification = hyper_grid[i, "Classification"])

第二:实际上,模型的输出显然没有打印出来,但我立即捕获了重要的结果(主要是RF_train$confusion.matrix)并将结果写入同一行的hyper_grid的扩展版本与输入参数。这种性能是否明智但代价高昂?因为如果我存储游侠对象,我会在某些时候遇到内存问题。

谢谢!

【问题讨论】:

    标签: r grid-search


    【解决方案1】:

    我认为将你需要的值的训练和提取包装到一个函数中是最干净的。点 (...) 需要用于下面的 purrr::pmap 函数。

    fit_and_extract_metrics <- function(Target, Input_table, Trees, Importance, Classification, ...) {
      RF_train <- ranger(
        dependent.variable.name = Target, 
        data = Input_list[[Input_table]],  # referring to the named object in the list
        num.trees = Trees, 
        importance = Importance, 
        classification = Classification)  # otherwise regression is performed
    
      data.frame(Prediction_error = RF_train$prediction.error,
                 True_positive = RF_train$confusion.matrix[1])
    }
    

    然后您可以通过使用例如purrr::pmap 映射行来将结果添加为列:

    hyper_grid$res <- purrr::pmap(hyper_grid, fit_and_extract_metrics)
    

    通过这种方式映射,函数是逐行应用的,所以你应该不会遇到内存问题。

    purrr::pmap 的结果是一个列表,这意味着res 列包含每一行的列表。这可以使用tidyr::unnest 取消嵌套,以便将该列表的元素分布到您的数据框中。

    tidyr::unnest(hyper_grid, res)
    

    我认为这种方法非常优雅,但它需要一些tidyverse 知识。如果您想了解更多信息,我强烈推荐this book。第 25 章(许多模型)描述了一种类似于我在这里采用的方法。

    【讨论】:

    • 这是一个很好的方法,谢谢。由于 confusion.matrix 不是单个值,而是 3x3 表,它不适合 data.frames 行,我应该在那里更精确。是否可以将 RF_train 对象中的多个值返回到 hyper_grid data.frame 的同一行中?例如hyper_grid$True_positive &lt;- RF_train$confusion.matrix[1]; hyper_grid$Prediction_error &lt;- RF_train$prediction.error?
    • 哦,哇,这太棒了,而且很奇怪;-)。我不知道您可以将列表添加到 data.frame。几个月以来,我一直在为这种工作流程开发代码,人们推荐purrr,但我无法让它工作或与结果相处。这真的是一个很大的帮助
    • 嗯,参数的传递方式似乎有些问题,您知道如何处理吗? stackoverflow.com/questions/60956516/…
    猜你喜欢
    • 2020-09-24
    • 2016-09-27
    • 2013-10-07
    • 1970-01-01
    • 1970-01-01
    • 2021-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多