--- title: "Basic Examples" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Basic Examples} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ```{r setup} library(nadir) ``` Let's start with an extremely simple example: a prediction problem on a continuous outcome, where we want to use cross-validation to minimize the expected risk/loss on held out data across a few different models. We'll use the `penguins` dataset to do this. `nadir::super_learner()` strives to keep the syntax simple, so the simplest call to `super_learner()` might look something like this: ```{r} library(dplyr) penguins <- penguins[complete.cases(penguins), ] sl <- super_learner( data = penguins, formula = flipper_len ~ bill_dep + bill_len + species + body_mass, learners = list( lnr_lm, lnr_earth, lnr_mean, lnr_rf, lnr_xgboost, lnr_cvglmnet, lnr_gbm ) ) sl ``` Notice what it returns: A function of `newdata` that predicts across the learners, sums up according to the learned weights, and returns the ensemble predictions. We can store that learned predictor function and use it: ```{r} # We recommend storing the list of learners and formulas to simplify # calls to super_learner() penguins_formula <- flipper_len ~ bill_dep + bill_len + species + body_mass learners <- list( lnr_lm, lnr_mean, lnr_rf, lnr_xgboost, lnr_cvglmnet, lnr_gbm ) sl <- super_learner( data = penguins, formula = penguins_formula, learners = learners ) plot(sl) plot(sl, type = "fitted") ``` In particular, we can use it to predict on the same dataset, ```{r} predict(sl, penguins) |> head() # equivalently, predict(sl) |> head() ``` On a random sample of it, ```{r} predict(sl, penguins[sample.int(size = 10, n = nrow(penguins)), ]) |> head() ``` Or on completely new data. ```{r} fake_penguins_data <- penguins[1:10, ] fake_penguins_data$flipper_len <- rnorm(n = 10) fake_penguins_data$bill_len <- rexp(n = 10) predict(sl, fake_penguins_data) |> head() ``` ## Getting More Information Out If we want to know a lot more about the `super_learner()` process, how it weighted the candidate learners, what the candidate learners predicted on the held-out data, etc., then we will want to look at the other metadata contained in the `nadir_sl_model` object produced: option. ```{r} sl summary(sl) nobs(sl) sl$holdout_predictions |> head() |> knitr::kable() sl_model_penguins <- super_learner( data = penguins, formula = penguins_formula, learners = learners ) str(sl_model_penguins, max.level = 1) ``` To put some description to what's contained in the output from `super_learner()`: * A prediction function, `$predict()` that takes `newdata` * Each of the fit learners as prediction functions: a list of functions `$fit_learners` which also take `newdata`. * Some character fields like `$y_variable` and `$outcome_type` to provide some context to the learning task that was performed. * `$learner_weights` that indicate what weight the different candidate learners were given * `$holdout_predictions`: A data.frame of predictions from each of the candidate learners, along with the actual outcome from the held-out data. We can call `compare_learners()` on the verbose output from `super_learner()` if we want to assess how the different learners performed. We can also call `cv_super_learner()` with the same arguments as `super_learner()` to wrap the `super_learner()` call in another layer of cross-validation to assess how `super_learner()` performs on held-out data. ```{r} compare_learners(sl) cv_sl <- cv_super_learner( data = penguins, formula = penguins_formula, learners = learners ) cv_sl cv_sl$cv_loss ``` We can, of course, do anything with a super learned model that we would do with a conventional prediction model, like calculating performance statistics like $R^2$. ```{r} var_residuals <- var(penguins$flipper_len - predict(sl, penguins)) total_variance <- var(penguins$flipper_len) variance_explained <- total_variance - var_residuals rsquared <- variance_explained / total_variance print(rsquared) ``` In the causal inference literature, there is a commonly used way to avoid restrictive Donsker conditions on model complexity, and that is to use something that is known as crossfitting. We provide a crossfit super learner implementation as well. ```{r} cf <- crossfit_super_learner( data = penguins, learners = learners, formula = penguins_formula ) cf summary(cf) ``` Find more examples and documentation on the `{nadir}` website: