LOOCV vs. k-fold CV porta agli stessi risultati

Aug 18 2020

Costruisco un modello di regressione lineare e lo utilizzo per prevedere l'out-of-sample. In questo contesto, utilizzo LOOCV e k-fold CV (5). Tuttavia, entrambi i metodi sembrano portare agli stessi risultati. L'unica piccola differenza tra questi due metodi sono valori leggermente diversi per le misure di accuratezza per le stime nel campione (vedere i risultati di seguito).

Cosa sta succedendo qui; mi manca un punto?

library(mlbench)
library(caret)
data(BostonHousing)
df <- BostonHousing

######
set.seed(12345)
train.index <- createDataPartition(df$medv, p = 0.75, list = FALSE)
train <- df[train.index, ]
test <- df[-train.index, ]

#####
fitControl <- trainControl(method = "LOOCV")

mod1 <- train(medv ~ crim + zn + rm,
              data = train,
              method = "lm",
              trControl = fitControl)

preds1 <- predict(mod1, newdata = test)

#####
fitControl2 <- trainControl(method = "repeatedcv", number = 5, repeats = 10)

mod2 <- train(medv ~ crim + zn + rm,
              data = train,
              method = "lm",
              trControl = fitControl2)

preds2 <- predict(mod2, newdata = test)

I risultati sono i seguenti:

Coefficienti:

coef(summary(mod1)) 
coef(summary(mod2))

             LOOCV         k-fold
(Intercept) -28.74077696  -28.74077696
crim         -0.23736504   -0.23736504
zn            0.04259996    0.04259996
rm            8.21720224    8.21720224

Vestibilità nel campione:

mod1$results mod2$results

              LOOCV         k-fold
RMSE          6.16378       6.083234
Rsquared      0.5437839     0.5727744
MAE           4.176978      4.174368

Vestibilità fuori campione:

postResample(preds1, obs = test$medv) postResample(preds2, obs = test$medv)

              LOOCV         k-fold
RMSE          4.1298679     4.1298679
Rsquared      0.5489697     0.5489697
MAE           4.1298679     4.1298679

Risposte

1 cbeleitesunhappywithSX Aug 19 2020 at 16:56

Prima di tutto, i modelli finali ( mod1$finalModele mod1$finalModel) sono gli stessi, nel tuo caso particolare per due motivi:

  1. In realtà non si sintonizza, si allena un singolo modello che è il modello lineare con intercept = TRUE).

    La linea rivelatrice è l'output di print(mod2):

    Il parametro di sintonizzazione "intercetta" è stato mantenuto costante su un valore TRUE

    Puoi anche guardare mod2$results:

      intercept     RMSE  Rsquared      MAE    RMSESD RsquaredSD     MAESD  
    1      TRUE 6.121066 0.5568386 4.187102 0.9087823  0.1089092 0.4691107
    

    Confronta questo con:

    mod3 <- train(medv ~ crim + zn + rm,
               data = train,
               method = "lm",
               tuneGrid = data.frame (intercept = c(FALSE, TRUE)),
               trControl = fitControl)
    mod3
    # [...snip...]
    # Resampling results across tuning parameters:
    # 
    #   intercept  RMSE      Rsquared   MAE     
    #   FALSE      6.818821  0.4592127  4.844369
    #    TRUE      6.163780  0.5437839  4.176978
    # 
    # RMSE was used to select the optimal model using the smallest value.
    # The final value used for the model was intercept = TRUE.
    
    mod3$results
    #   intercept     RMSE  Rsquared      MAE
    # 1     FALSE 6.818821 0.4592127 4.844369
    # 2      TRUE 6.163780 0.5437839 4.176978
    
  2. La convalida incrociata interna durante l'ottimizzazione risulta in un set di iperparametri, ma non ancora nel modello finale. Il modello finale si ottiene addestrando con questo set di iperparametri e tutti i dati a cui sono stati consegnati train().

    Indipendentemente dalla routine di convalida incrociata / bootstrap scelta, a condizione che il set di iperparametri sintonizzati sia lo stesso, anche il modello finale sarà lo stesso (almeno per le routine di allenamento deterministiche come lm()).

    Quindi, anche se tu fossi sintonizzato, risulterebbe sempre lo stesso modello: quello con intercept = TRUE.