【问题标题】:Set tuning parameter range a priori先验设置调整参数范围
【发布时间】:2021-08-17 14:36:49
【问题描述】:

我知道在tidymodels 中,您可以通过直接与工作流对象交互来设置自定义可调参数空间,如下所示:

library(tidymodels)

model <- linear_reg(
  mode = "regression", 
  engine = "glmnet", 
  penalty = tune()
  )

rec_cars <- recipe(mpg ~ ., data = mtcars)
 
wkf <- workflow() %>% 
  add_recipe(rec_cars) %>% 
  add_model(model) 

wkf_new_param_space <- wkf %>%
  parameters() %>%
  update(penalty = penalty(range = c(0.9, 1)))

但有时在我指定配方或模型时正确执行此操作更有意义。

有人知道实现此目的的方法吗?

【问题讨论】:

    标签: r tidymodels


    【解决方案1】:

    参数范围本质上与 tidymodels 中的模型规范和配方规范分开。当您设置 tune() 时,您正在向 tune 函数发出一个信号,表明此参数将采用多个值并且应该进行调整。

    因此,作为一个简短的回答,您不能在指定配方或模型时指定参数范围,但您可以像之前一样立即创建参数对象。

    最后,您需要参数集来构建用于超参数调整的网格值,并且您可以通过至少 4 种方式创建这些 gid 值。

    第一种方法是按照自己的方式进行操作,将所需的参数从工作流程中提取出来并在需要时进行修改。

    第二种方法是创建一个参数对象来匹配您需要使用的参数。此选项和其余选项要求您确保为正在调整的所有参数创建值。

    第三种方法是完全跳过参数对象并使用您的grid_*()函数和拨号函数创建网格。

    第四种方式是完全跳过拨号功能,自己创建数据框。我发现tidyr::crossing()grid_regular() 的有用替代品。当您使用整数参数和不受益于转换的参数时,这种方式会容易得多。

    library(tidymodels)
    
    model <- linear_reg(
      mode = "regression", 
      engine = "glmnet", 
      penalty = tune()
      )
    
    rec_cars <- recipe(mpg ~ ., data = mtcars)
     
    wkf <- workflow() %>% 
      add_recipe(rec_cars) %>% 
      add_model(model) 
    
    # Option 1: using parameters() on workflow
    wkf_new_param_space <- wkf %>%
      parameters() %>%
      update(penalty = penalty(range = c(-5, 5)))
    
    wkf_new_param_space %>%
      grid_regular(levels = 10)
    #> # A tibble: 10 × 1
    #>          penalty
    #>            <dbl>
    #>  1      0.00001 
    #>  2      0.000129
    #>  3      0.00167 
    #>  4      0.0215  
    #>  5      0.278   
    #>  6      3.59    
    #>  7     46.4     
    #>  8    599.      
    #>  9   7743.      
    #> 10 100000
    
    # Option 2: Using parameters() on list
    my_params <- parameters(
      list(
        penalty(range = c(-5, 5))
      )
    )
    
    my_params %>%
      grid_regular(levels = 10)
    #> # A tibble: 10 × 1
    #>          penalty
    #>            <dbl>
    #>  1      0.00001 
    #>  2      0.000129
    #>  3      0.00167 
    #>  4      0.0215  
    #>  5      0.278   
    #>  6      3.59    
    #>  7     46.4     
    #>  8    599.      
    #>  9   7743.      
    #> 10 100000
    
    # Option 3: Use grid_*() with dials objects directly
    grid_regular(
      penalty(range = c(-5, 5)),
      levels = 10
    )
    #> # A tibble: 10 × 1
    #>          penalty
    #>            <dbl>
    #>  1      0.00001 
    #>  2      0.000129
    #>  3      0.00167 
    #>  4      0.0215  
    #>  5      0.278   
    #>  6      3.59    
    #>  7     46.4     
    #>  8    599.      
    #>  9   7743.      
    #> 10 100000
    
    
    
    # Option 4: Create grid values manually
    tidyr::crossing(
      penalty = 10 ^ seq(-5, 5, length.out = 10)
    )
    #> # A tibble: 10 × 1
    #>          penalty
    #>            <dbl>
    #>  1      0.00001 
    #>  2      0.000129
    #>  3      0.00167 
    #>  4      0.0215  
    #>  5      0.278   
    #>  6      3.59    
    #>  7     46.4     
    #>  8    599.      
    #>  9   7743.      
    #> 10 100000
    

    reprex package (v2.0.1) 于 2021-08-17 创建

    【讨论】:

    • 非常感谢埃米尔!我之所以问这个问题是因为我使用的是drake,并且我在管道中创建了工作流,但模型是在外部指定的,以利用静态分支。也许根据您写的内容,我最好回顾一下我的管道。如果您有任何建议或文章,我很高兴听到/阅读。
    【解决方案2】:

    似乎这是一个老问题,但我很难尝试在我的工作流程中插入这种方法(选项 1)。

    应该如何继续?

    wkf_new_param_space 是作为网格还是作为调整模型中的对象使用?

    model_tuned <-
      tune::tune_grid(
        object = wkf_new_param_space, ?
        resamples = cv_folds,
        grid = wkf_new_param_space, ?
        metrics = model_metrics,
        control = tune::control_grid(save_pred = TRUE, save_workflow = TRUE)
      )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-29
      • 2022-10-15
      • 2023-04-05
      • 2010-10-14
      相关资源
      最近更新 更多