title: Can tidymodels deal with the retransformation problem?
body: <p>I was getting acquainted with <code>tidymodels</code> by reading the <a href="https://www.tmwr.org/performance.html" rel="nofollow noreferrer">book</a> and this line in section 9.2 kept me thinking about retransformation.</p>
  <blockquote>
  <p>It is best practice to analyze the predictions on the transformed
  scale (if one were used) even if the predictions are reported using
  the original units.</p>
  </blockquote>
  <p>But I found it confusing that the examples in the book use a log transformation on the outcome, but they do not use a recipe for this (the recipe has not been introduced at this point, but later when they introduce recipe, still they do not use <code>step_log</code> for the outcome but just for the predictors). So I wanted to try that and found something puzzling, illustrated with the reprex below:</p>
  <pre class="lang-r prettyprint-override"><code># So let's use most of the code from the examples in the book
  
  library(tidymodels)
  tidymodels_prefer()
  
  set.seed(501)
  
  # data budget
  data(ames)    
  ames_split &lt;- initial_split(ames, prop = 0.80, strata = Sale_Price)
  ames_train &lt;- training(ames_split)
  ames_test  &lt;-  testing(ames_split)    
  ames_folds &lt;- vfold_cv(ames_train, v = 10, strata = Sale_Price)
  
  # IJALM    
  lm_model &lt;- 
    linear_reg(penalty = 0) |&gt; 
    set_engine(&quot;glmnet&quot;) 
  
  # And use a recipe, 
  # but Instead of manually transforming the outcome like this ...
  # `ames &lt;- ames %&gt;% mutate(Sale_Price = log10(Sale_Price))`
  # let's include the outcome transformation into the recipe
  simple_ames &lt;- 
    recipe(
      Sale_Price ~ Neighborhood + Gr_Liv_Area + Year_Built + Bldg_Type,
      data = ames_train
    ) |&gt; 
    step_log(Gr_Liv_Area, base = 10) |&gt; 
    step_dummy(all_nominal_predictors()) |&gt; 
    step_log(Sale_Price, base = 10, skip = TRUE)
  
  lm_wflow &lt;- 
    workflow() |&gt; 
    add_model(lm_model) |&gt; 
    add_recipe(simple_ames)
  
  lm_res &lt;- fit_resamples(
    lm_wflow,
    resamples = ames_folds, 
    control = control_resamples(save_pred = TRUE, save_workflow = TRUE),
    metrics = metric_set(rmse)
  )
  
  collect_metrics(lm_res)
  #&gt; # A tibble: 1 x 6
  #&gt;   .metric .estimator    mean     n std_err .config             
  #&gt;   &lt;chr&gt;   &lt;chr&gt;        &lt;dbl&gt; &lt;int&gt;   &lt;dbl&gt; &lt;chr&gt;               
  #&gt; 1 rmse    standard   197264.    10   1362. Preprocessor1_Model1
  
  # Now, I wanted to double-check how rmse was calculated
  # It should be the mean of the rmse for each fold 
  # (individual values stored in this list lm_res$.metrics, 
  # with one element for each fold)
  # and each rmse should have been calculated with the predictions of each fold
  # (stored in lm_res$.predictions)
  
  # So, this rmse corresponding to the first fold
  lm_res$.metrics[[1]]
  #&gt; # A tibble: 1 x 4
  #&gt;   .metric .estimator .estimate .config             
  #&gt;   &lt;chr&gt;   &lt;chr&gt;          &lt;dbl&gt; &lt;chr&gt;               
  #&gt; 1 rmse    standard     196074. Preprocessor1_Model1
  
  # Should have been calculated with this data
  lm_res$.predictions[[1]]
  #&gt; # A tibble: 236 x 4
  #&gt;    .pred  .row Sale_Price .config             
  #&gt;    &lt;dbl&gt; &lt;int&gt;      &lt;int&gt; &lt;chr&gt;               
  #&gt;  1  5.09     2     126000 Preprocessor1_Model1
  #&gt;  2  4.92    33     105900 Preprocessor1_Model1
  #&gt;  3  5.06    34     125500 Preprocessor1_Model1
  #&gt;  4  5.18    44     121500 Preprocessor1_Model1
  #&gt;  5  5.14    51     127000 Preprocessor1_Model1
  #&gt;  6  5.13    53     114000 Preprocessor1_Model1
  #&gt;  7  4.90    57      84900 Preprocessor1_Model1
  #&gt;  8  5.13    62     113000 Preprocessor1_Model1
  #&gt;  9  5.02    74      83500 Preprocessor1_Model1
  #&gt; 10  5.02    76      88250 Preprocessor1_Model1
  #&gt; # ... with 226 more rows
  #&gt; # i Use `print(n = ...)` to see more rows
  
  # But here's the issue!
  # The predictions are in the log-scale while the observed values
  # are in the original units.
  
  # This is just a quick-check to make sure the rmse reported above 
  # (calculated by yardstick) does in fact involve mixing-up the log-scale 
  # (predictions) and the original units (observed values)
  yhat &lt;- lm_res$.predictions[[1]]$.pred
  yobs &lt;- lm_res$.predictions[[1]]$Sale_Price
  sqrt(mean((yhat - yobs)^2))
  #&gt; [1] 196073.6
  
  # So, apparently, for cross-validation tidymodels does not `bake` the folds
  # with the recipe to calculate the metrics
  </code></pre>
  <p>And here’s where I got it (at least I think so), after spending half
  an hour writing this reprex. So, to not feel I wasted my time, I decided
  to post it anyway, and put what I think is going on as an answer.
  Perhaps someone finds it useful, because it was not evident to me at the
  first time. Or perhaps someone can explain if there is something else going on.</p>
  <p><sup>Created on 2022-08-07 by the <a href="https://reprex.tidyverse.org" rel="nofollow noreferrer">reprex package</a> (v2.0.1)</sup></p>