title: Tuning Tidymodels’ Recipe and Model Parameters Simultaneously
body: <p>We can use Tidymodels to tune both recipe parameters and model parameters simultaneously, right?  I'm struggling to understand what corrective action I should take based on the message, <em>Error: Some tuning parameters require finalization but there are recipe parameters that require tuning. Please use <code>parameters()</code> to finalize the parameter ranges.”</em>  Any help would be most appreciated.</p>
  <pre class="lang-r prettyprint-override"><code>suppressPackageStartupMessages(library(tidyverse))
  suppressPackageStartupMessages(library(tidymodels))
  suppressPackageStartupMessages(library(themis))
  suppressPackageStartupMessages(library(finetune))
  suppressPackageStartupMessages(library(doParallel))
  suppressPackageStartupMessages(library(titanic))
  
  registerDoParallel()
  
  set.seed(123)
  
  
  train.df &lt;- titanic_train %&gt;% 
    mutate(Survived = factor(ifelse(Survived == 1, 'Y', 'N')),
           Pclass = factor(Pclass, ordered = TRUE),
           Sex = factor(Sex),
           Embarked = factor(ifelse(Embarked == '', NA, Embarked))) %&gt;% 
    select(-c(Name, Ticket, Cabin))
  
  
  summary(train.df)
  #&gt;   PassengerId    Survived Pclass      Sex           Age            SibSp      
  #&gt;  Min.   :  1.0   N:549    1:216   female:314   Min.   : 0.42   Min.   :0.000  
  #&gt;  1st Qu.:223.5   Y:342    2:184   male  :577   1st Qu.:20.12   1st Qu.:0.000  
  #&gt;  Median :446.0            3:491                Median :28.00   Median :0.000  
  #&gt;  Mean   :446.0                                 Mean   :29.70   Mean   :0.523  
  #&gt;  3rd Qu.:668.5                                 3rd Qu.:38.00   3rd Qu.:1.000  
  #&gt;  Max.   :891.0                                 Max.   :80.00   Max.   :8.000  
  #&gt;                                                NA's   :177                    
  #&gt;      Parch             Fare        Embarked  
  #&gt;  Min.   :0.0000   Min.   :  0.00   C   :168  
  #&gt;  1st Qu.:0.0000   1st Qu.:  7.91   Q   : 77  
  #&gt;  Median :0.0000   Median : 14.45   S   :644  
  #&gt;  Mean   :0.3816   Mean   : 32.20   NA's:  2  
  #&gt;  3rd Qu.:0.0000   3rd Qu.: 31.00             
  #&gt;  Max.   :6.0000   Max.   :512.33             
  #&gt; 
  
  
  cv.folds &lt;- vfold_cv(train.df, v = 4, strata = Survived)
  
  cv.folds
  #&gt; #  4-fold cross-validation using stratification 
  #&gt; # A tibble: 4 x 2
  #&gt;   splits            id   
  #&gt;   &lt;list&gt;            &lt;chr&gt;
  #&gt; 1 &lt;split [667/224]&gt; Fold1
  #&gt; 2 &lt;split [668/223]&gt; Fold2
  #&gt; 3 &lt;split [669/222]&gt; Fold3
  #&gt; 4 &lt;split [669/222]&gt; Fold4
  
  #########################################################
  
  # Logistic Regression Model -- This Works
  #   Tuning Recipe Parameters: Yes
  #   Tuning Model Hyperparameters: No
    
  recipe.logistic.regression &lt;- 
    recipe(Survived ~ ., data = train.df) %&gt;% 
    update_role(PassengerId, new_role = 'ID') %&gt;% 
    step_dummy(all_nominal(), -all_outcomes()) %&gt;% 
    step_impute_knn(all_predictors(), neighbors = tune()) %&gt;% 
    step_normalize(all_predictors()) %&gt;% 
    step_downsample(Survived, seed = 456)
  
  spec.logistic.regression &lt;- 
    logistic_reg() %&gt;% 
    set_engine(&quot;glm&quot;)
  
  wf.logistic.regression &lt;- 
    workflow() %&gt;% 
    add_recipe(recipe.logistic.regression) %&gt;% 
    add_model(spec.logistic.regression)
  
  wf.logistic.regression
  #&gt; == Workflow ====================================================================
  #&gt; Preprocessor: Recipe
  #&gt; Model: logistic_reg()
  #&gt; 
  #&gt; -- Preprocessor ----------------------------------------------------------------
  #&gt; 4 Recipe Steps
  #&gt; 
  #&gt; * step_dummy()
  #&gt; * step_impute_knn()
  #&gt; * step_normalize()
  #&gt; * step_downsample()
  #&gt; 
  #&gt; -- Model -----------------------------------------------------------------------
  #&gt; Logistic Regression Model Specification (classification)
  #&gt; 
  #&gt; Computational engine: glm
  
  rs.logistic.regression &lt;- tune_race_anova(
    wf.logistic.regression,
    resamples = cv.folds,
    grid = 25,
    metrics = metric_set(accuracy),
    control = control_race(verbose = TRUE, verbose_elim = TRUE,
                           parallel_over = &quot;everything&quot;,
                           save_pred = TRUE,
                           save_workflow = TRUE)
  )
  #&gt; i Racing will maximize the accuracy metric.
  #&gt; i Resamples are analyzed in a random order.
  #&gt; i Fold4:  1 eliminated;  9 candidates remain.
  
  show_best(rs.logistic.regression)
  #&gt; # A tibble: 5 x 7
  #&gt;   neighbors .metric  .estimator  mean     n std_err .config              
  #&gt;       &lt;int&gt; &lt;chr&gt;    &lt;chr&gt;      &lt;dbl&gt; &lt;int&gt;   &lt;dbl&gt; &lt;chr&gt;                
  #&gt; 1         9 accuracy binary     0.791     4  0.0193 Preprocessor01_Model1
  #&gt; 2         2 accuracy binary     0.788     4  0.0186 Preprocessor08_Model1
  #&gt; 3         4 accuracy binary     0.788     4  0.0190 Preprocessor09_Model1
  #&gt; 4         1 accuracy binary     0.787     4  0.0205 Preprocessor05_Model1
  #&gt; 5        10 accuracy binary     0.787     4  0.0205 Preprocessor10_Model1
  
  #########################################################
    
  # Random Forest Model A -- This Works
  #   Tuning Recipe Parameters: No
  #   Tuning Model Hyperparameters: Yes
    
  recipe.random.forest.a &lt;- 
    recipe(Survived ~ ., data = train.df) %&gt;% 
    update_role(PassengerId, new_role = 'ID') %&gt;% 
    step_impute_knn(all_predictors(), 
                    neighbors = 5) %&gt;%  # &lt;-- Manually setting value for neighbors
    step_downsample(Survived, seed = 456)
  
  spec.random.forest.a &lt;-
    rand_forest(mtry = tune(),
                min_n = tune(),
                trees = tune()) %&gt;% 
    set_mode(&quot;classification&quot;) %&gt;% 
    set_engine(&quot;ranger&quot;)
  
  wf.random.forest.a &lt;- 
    workflow() %&gt;% 
    add_recipe(recipe.random.forest.a) %&gt;% 
    add_model(spec.random.forest.a)
  
  wf.random.forest.a
  #&gt; == Workflow ====================================================================
  #&gt; Preprocessor: Recipe
  #&gt; Model: rand_forest()
  #&gt; 
  #&gt; -- Preprocessor ----------------------------------------------------------------
  #&gt; 2 Recipe Steps
  #&gt; 
  #&gt; * step_impute_knn()
  #&gt; * step_downsample()
  #&gt; 
  #&gt; -- Model -----------------------------------------------------------------------
  #&gt; Random Forest Model Specification (classification)
  #&gt; 
  #&gt; Main Arguments:
  #&gt;   mtry = tune()
  #&gt;   trees = tune()
  #&gt;   min_n = tune()
  #&gt; 
  #&gt; Computational engine: ranger
  
  rs.random.forest.a &lt;- tune_race_anova(
    wf.random.forest.a,
    resamples = cv.folds,
    grid = 25,
    metrics = metric_set(accuracy),
    control = control_race(verbose = TRUE, verbose_elim = TRUE,
                           parallel_over = &quot;everything&quot;,
                           save_pred = TRUE,
                           save_workflow = TRUE)
  )
  #&gt; i Creating pre-processing data to finalize unknown parameter: mtry
  #&gt; i Racing will maximize the accuracy metric.
  #&gt; i Resamples are analyzed in a random order.
  #&gt; i Fold4:  4 eliminated; 21 candidates remain.
  
  show_best(rs.random.forest.a)
  #&gt; # A tibble: 5 x 9
  #&gt;    mtry trees min_n .metric  .estimator  mean     n std_err .config             
  #&gt;   &lt;int&gt; &lt;int&gt; &lt;int&gt; &lt;chr&gt;    &lt;chr&gt;      &lt;dbl&gt; &lt;int&gt;   &lt;dbl&gt; &lt;chr&gt;               
  #&gt; 1     4   837    18 accuracy binary     0.818     4 0.00685 Preprocessor1_Model~
  #&gt; 2     4  1968    16 accuracy binary     0.817     4 0.00738 Preprocessor1_Model~
  #&gt; 3     4  1439    25 accuracy binary     0.817     4 0.00664 Preprocessor1_Model~
  #&gt; 4     3  1769    10 accuracy binary     0.816     4 0.0130  Preprocessor1_Model~
  #&gt; 5     3  1478    13 accuracy binary     0.816     4 0.0109  Preprocessor1_Model~
  
  #########################################################
    
  # Random Forest Model B -- This Does Not Work
  #   Tuning Recipe Parameters: Yes
  #   Tuning Model Hyperparameters: Yes
    
  recipe.random.forest.b &lt;- 
    recipe(Survived ~ ., data = train.df) %&gt;% 
    update_role(PassengerId, new_role = 'ID') %&gt;% 
    step_impute_knn(all_predictors(), 
                    neighbors = tune()) %&gt;%  # &lt;-- Tuning neighbors
    step_downsample(Survived, seed = 456)
  
  spec.random.forest.b &lt;-
    rand_forest(mtry = tune(),
                min_n = tune(),
                trees = tune()) %&gt;% 
    set_mode(&quot;classification&quot;) %&gt;% 
    set_engine(&quot;ranger&quot;)
  
  wf.random.forest.b &lt;- 
    workflow() %&gt;% 
    add_recipe(recipe.random.forest.b) %&gt;% 
    add_model(spec.random.forest.b)
  
  wf.random.forest.b
  #&gt; == Workflow ====================================================================
  #&gt; Preprocessor: Recipe
  #&gt; Model: rand_forest()
  #&gt; 
  #&gt; -- Preprocessor ----------------------------------------------------------------
  #&gt; 2 Recipe Steps
  #&gt; 
  #&gt; * step_impute_knn()
  #&gt; * step_downsample()
  #&gt; 
  #&gt; -- Model -----------------------------------------------------------------------
  #&gt; Random Forest Model Specification (classification)
  #&gt; 
  #&gt; Main Arguments:
  #&gt;   mtry = tune()
  #&gt;   trees = tune()
  #&gt;   min_n = tune()
  #&gt; 
  #&gt; Computational engine: ranger
  
  rs.random.forest.b &lt;- tune_race_anova(
    wf.random.forest.b,
    resamples = cv.folds,
    grid = 25,
    metrics = metric_set(accuracy),
    control = control_race(verbose = TRUE, verbose_elim = TRUE,
                           parallel_over = &quot;everything&quot;,
                           save_pred = TRUE,
                           save_workflow = TRUE)
  )
  #&gt; Error: Some tuning parameters require finalization but there are recipe parameters that require tuning. Please use `parameters()` to finalize the parameter ranges.
  
  #########################################################
  
  sessionInfo()
  #&gt; R version 4.1.0 (2021-05-18)
  #&gt; Platform: x86_64-w64-mingw32/x64 (64-bit)
  #&gt; Running under: Windows 10 x64 (build 19041)
  #&gt; 
  #&gt; Matrix products: default
  #&gt; 
  #&gt; locale:
  #&gt; [1] LC_COLLATE=English_United States.1252 
  #&gt; [2] LC_CTYPE=English_United States.1252   
  #&gt; [3] LC_MONETARY=English_United States.1252
  #&gt; [4] LC_NUMERIC=C                          
  #&gt; [5] LC_TIME=English_United States.1252    
  #&gt; 
  #&gt; attached base packages:
  #&gt; [1] parallel  stats     graphics  grDevices utils     datasets  methods  
  #&gt; [8] base     
  #&gt; 
  #&gt; other attached packages:
  #&gt;  [1] titanic_0.1.0      doParallel_1.0.16  iterators_1.0.13   foreach_1.5.1     
  #&gt;  [5] finetune_0.1.0     themis_0.1.4       yardstick_0.0.8    workflowsets_0.1.0
  #&gt;  [9] workflows_0.2.3    tune_0.1.6         rsample_0.1.0      recipes_0.1.16    
  #&gt; [13] parsnip_0.1.7      modeldata_0.1.1    infer_0.5.4        dials_0.0.9       
  #&gt; [17] scales_1.1.1       broom_0.7.9        tidymodels_0.1.3   forcats_0.5.1     
  #&gt; [21] stringr_1.4.0      dplyr_1.0.7        purrr_0.3.4        readr_2.0.0       
  #&gt; [25] tidyr_1.1.3        tibble_3.1.3       ggplot2_3.3.5      tidyverse_1.3.1   
  #&gt; 
  #&gt; loaded via a namespace (and not attached):
  #&gt;  [1] minqa_1.2.4        colorspace_2.0-2   ellipsis_0.3.2     class_7.3-19      
  #&gt;  [5] fs_1.5.0           rstudioapi_0.13    listenv_0.8.0      furrr_0.2.3       
  #&gt;  [9] ParamHelpers_1.14  prodlim_2019.11.13 fansi_0.5.0        lubridate_1.7.10  
  #&gt; [13] ranger_0.13.1      xml2_1.3.2         codetools_0.2-18   splines_4.1.0     
  #&gt; [17] knitr_1.33         jsonlite_1.7.2     nloptr_1.2.2.2     pROC_1.17.0.1     
  #&gt; [21] dbplyr_2.1.1       compiler_4.1.0     httr_1.4.2         backports_1.2.1   
  #&gt; [25] assertthat_0.2.1   Matrix_1.3-4       cli_3.0.1          htmltools_0.5.1.1 
  #&gt; [29] tools_4.1.0        gtable_0.3.0       glue_1.4.2         RANN_2.6.1        
  #&gt; [33] parallelMap_1.5.1  fastmatch_1.1-3    Rcpp_1.0.7         cellranger_1.1.0  
  #&gt; [37] styler_1.5.1       DiceDesign_1.9     vctrs_0.3.8        nlme_3.1-152      
  #&gt; [41] timeDate_3043.102  mlr_2.19.0         gower_0.2.2        xfun_0.25         
  #&gt; [45] globals_0.14.0     lme4_1.1-27.1      rvest_1.0.1        lifecycle_1.0.0   
  #&gt; [49] future_1.21.0      MASS_7.3-54        ipred_0.9-11       hms_1.1.0         
  #&gt; [53] BBmisc_1.11        yaml_2.2.1         rpart_4.1-15       stringi_1.7.3     
  #&gt; [57] highr_0.9          checkmate_2.0.0    lhs_1.1.1          boot_1.3-28       
  #&gt; [61] hardhat_0.1.6      lava_1.6.9         rlang_0.4.11       pkgconfig_2.0.3   
  #&gt; [65] evaluate_0.14      lattice_0.20-44    tidyselect_1.1.1   parallelly_1.27.0 
  #&gt; [69] plyr_1.8.6         magrittr_2.0.1     R6_2.5.0           generics_0.1.0    
  #&gt; [73] DBI_1.1.1          pillar_1.6.2       haven_2.4.3        withr_2.4.2       
  #&gt; [77] survival_3.2-11    nnet_7.3-16        ROSE_0.0-4         modelr_0.1.8      
  #&gt; [81] crayon_1.4.1       unbalanced_2.0     utf8_1.2.2         tzdb_0.1.2        
  #&gt; [85] rmarkdown_2.10     grid_4.1.0         readxl_1.3.1       data.table_1.14.0 
  #&gt; [89] FNN_1.1.3          reprex_2.0.1       digest_0.6.27      munsell_0.5.0     
  #&gt; [93] GPfit_1.0-8
  </code></pre>
  <p><sup>Created on 2021-08-07 by the <a href="https://reprex.tidyverse.org" rel="nofollow noreferrer">reprex package</a> (v2.0.1)</sup></p>