glmnettidymodels

How to tune the penalty term on a range of manual mixtures for elastic net in glmnet using tidy models?


I am trying to fit an elastic net using glmnet in tidymodels for a range of mixtures. Now, I know how to run this when I tune both the penalty and mixture terms (i.e. my code runs without errors). However, I want to just try some mixture values in the interest of time. I have never done this before and, when I try the following, R throws me an error saying "Only one value of 'mixture' is allowed".

elastic_spec <- linear_reg(engine = "glmnet",
                           penalty = tune(),
                           mixture = c(0.25, 0.5, 0.75))
elastic_wf <- workflow(preprocessor = linear_rec,
                       spec = elastic_spec)
elastic_tune <- tune_grid(elastic_wf,
                          resamples = folds,
                          metrics = metric_set(mae, rmse, rsq),
                          grid = grid_regular(penalty(range = c(-4, -2)), levels = 100))

Thus, my question is, is it possible to manually tune the penalty term for a specified range of mixtures?

I also apologise in advance for not attaching an MWE as I think the data is irrelevant here; I would just like to know whether it is possible to do what I've asked above!

Any intuitive explanations or suggestions will be greatly appreciated :)


Solution

  • To do this, you need to set mixture = tune() in linear_reg() and then you can add your specific values of mixture to your grid values by using expand_grid() on the output you got from grid_regular()

    library(tidymodels)
    
    folds <- bootstraps(mtcars, times = 5)
    
    linear_rec <- recipe(mpg ~ ., data = mtcars)
    
    elastic_spec <- linear_reg(engine = "glmnet",
                               penalty = tune(),
                               mixture = tune())
    
    elastic_wf <- workflow(preprocessor = linear_rec,
                           spec = elastic_spec)
    
    grid_values <- grid_regular(penalty(range = c(-4, -2)), levels = 100) %>%
      expand_grid(mixture = c(0.25, 0.5, 0.75))
    
    grid_values
    #> # A tibble: 300 × 2
    #>     penalty mixture
    #>       <dbl>   <dbl>
    #>  1 0.0001      0.25
    #>  2 0.0001      0.5 
    #>  3 0.0001      0.75
    #>  4 0.000105    0.25
    #>  5 0.000105    0.5 
    #>  6 0.000105    0.75
    #>  7 0.000110    0.25
    #>  8 0.000110    0.5 
    #>  9 0.000110    0.75
    #> 10 0.000115    0.25
    #> # … with 290 more rows
    
    elastic_tune <- tune_grid(
      elastic_wf,
      resamples = folds,
      metrics = metric_set(mae, rmse, rsq),
      grid = grid_values
    )
    
    elastic_tune
    #> # Tuning results
    #> # Bootstrap sampling 
    #> # A tibble: 5 × 4
    #>   splits          id         .metrics           .notes          
    #>   <list>          <chr>      <list>             <list>          
    #> 1 <split [32/12]> Bootstrap1 <tibble [900 × 6]> <tibble [0 × 3]>
    #> 2 <split [32/12]> Bootstrap2 <tibble [900 × 6]> <tibble [0 × 3]>
    #> 3 <split [32/10]> Bootstrap3 <tibble [900 × 6]> <tibble [0 × 3]>
    #> 4 <split [32/11]> Bootstrap4 <tibble [900 × 6]> <tibble [0 × 3]>
    #> 5 <split [32/12]> Bootstrap5 <tibble [900 × 6]> <tibble [0 × 3]>