tidymodels-tree5

statlearning
trees
tidymodels
speed
string
Published

November 8, 2023

Aufgabe

Berechnen Sie folgendes einfache Modell:

  1. Random Forest mit trees=50

Modellformel: body_mass_g ~ . (Datensatz palmerpenguins::penguins)

Hier geht es darum, die Geschwindigkeit (und den Ressourcenverbrauch) beim Fitten zu verringern. Benutzen Sie dazu folgende Methoden

  • Auslassen gering performanter Tuningparameterwerte
  • Verwenden Sie ein Anova-Grid-Search!
  • Parallelisieren Sie auf mehrere Kerne (wenn möglich).

Hinweise:

  • Tunen Sie alle Parameter (die der Engine anbietet).
  • Verwenden Sie Defaults, wo nicht anders angegeben.
  • Beachten Sie die üblichen Hinweise.











Lösung

Setup

library(tidymodels)
── Attaching packages ────────────────────────────────────── tidymodels 1.1.1 ──
✔ broom        1.0.5     ✔ recipes      1.0.8
✔ dials        1.2.0     ✔ rsample      1.2.0
✔ dplyr        1.1.3     ✔ tibble       3.2.1
✔ ggplot2      3.4.4     ✔ tidyr        1.3.0
✔ infer        1.0.5     ✔ tune         1.1.2
✔ modeldata    1.2.0     ✔ workflows    1.1.3
✔ parsnip      1.1.1     ✔ workflowsets 1.0.1
✔ purrr        1.0.2     ✔ yardstick    1.2.0
── Conflicts ───────────────────────────────────────── tidymodels_conflicts() ──
✖ purrr::discard() masks scales::discard()
✖ dplyr::filter()  masks stats::filter()
✖ dplyr::lag()     masks stats::lag()
✖ recipes::step()  masks stats::step()
• Use tidymodels_prefer() to resolve common conflicts.
data("penguins", package = "palmerpenguins")
library(tictoc)  # Zeitmessung
library(finetune)  # tune_race_anova
library(doParallel)  # mehrere CPUs nutzen 
Loading required package: foreach

Attaching package: 'foreach'
The following objects are masked from 'package:purrr':

    accumulate, when
Loading required package: iterators
Loading required package: parallel
set.seed(42)

Entfernen wir Fälle mit fehlenden Werten:

d <-
  penguins %>% 
  drop_na()

Daten teilen

set.seed(42)
d_split <- initial_split(d)
d_train <- training(d_split)
d_test <- testing(d_split)

Modell(e)

mod_rf <-
  rand_forest(mode = "regression",
              mtry = tune())
mod_rf
Random Forest Model Specification (regression)

Main Arguments:
  mtry = tune()

Computational engine: ranger 

Rezept(e)

rec_plain <- 
  recipe(body_mass_g ~ ., data = d_train) %>% 
  step_dummy(all_nominal_predictors()) %>% 
  step_impute_knn(all_predictors())
d_train_baked <-
  bake(prep(rec_plain, d_train), new_data = NULL)

head(d_train_baked)
# A tibble: 6 × 10
  bill_length_mm bill_depth_mm flipper_length_mm  year body_mass_g
           <dbl>         <dbl>             <int> <int>       <int>
1           34.5          18.1               187  2008        2900
2           52.2          18.8               197  2009        3450
3           45.4          14.6               211  2007        4800
4           42.1          19.1               195  2008        4000
5           50            15.9               224  2009        5350
6           41.5          18.5               201  2009        4000
# ℹ 5 more variables: species_Chinstrap <dbl>, species_Gentoo <dbl>,
#   island_Dream <dbl>, island_Torgersen <dbl>, sex_male <dbl>

Keine fehlenden Werte mehr?

sum(is.na(d_train_baked))
[1] 0

Resampling

set.seed(42)
rsmpl <- vfold_cv(d_train)

Workflows

wf_rf <-
  workflow() %>%  
  add_recipe(rec_plain) %>% 
  add_model(mod_rf)

wf_rf
══ Workflow ════════════════════════════════════════════════════════════════════
Preprocessor: Recipe
Model: rand_forest()

── Preprocessor ────────────────────────────────────────────────────────────────
2 Recipe Steps

• step_dummy()
• step_impute_knn()

── Model ───────────────────────────────────────────────────────────────────────
Random Forest Model Specification (regression)

Main Arguments:
  mtry = tune()

Computational engine: ranger 

Ohne Speed-up

tic()
fit_rf <-
  tune_grid(
    object = wf_rf,
    resamples = rsmpl)
i Creating pre-processing data to finalize unknown parameter: mtry
toc()
13.061 sec elapsed

Die angegebene Rechenzeit bezieht sich auf einen 4-Kerne-MacBook Pro (2020).

Mit Speeed-up 1

tic()
fit_rf2 <-
  tune_race_anova(
    object = wf_rf,
    resamples = rsmpl)
toc()
17.925 sec elapsed

Mit Speeed-up 2

doParallel::registerDoParallel()

tic()
fit_tree2 <-
  tune_race_anova(
    object = wf_rf,
    metrics = metric_set(rmse),
    control = control_race(verbose = FALSE,
                           pkgs = c("tidymodels"),
                           save_pred = TRUE),
            resamples = rsmpl)
i Creating pre-processing data to finalize unknown parameter: mtry
toc()
12.339 sec elapsed

Mit Speeed-up 3

doParallel::registerDoParallel()

tic()
fit_tree2 <-
  tune_grid(object = wf_rf,
            metrics = metric_set(rmse),
            control = control_grid(verbose = FALSE,
                                   save_pred = TRUE),
            resamples = rsmpl)
i Creating pre-processing data to finalize unknown parameter: mtry
toc()
4.53 sec elapsed

Fazit

Mit Speed-up ist schneller also ohne. Ein Random-Forest ist ein Modelltyp, der von Parallelisierung gut profitiert.


Categories:

  • statlearning
  • trees
  • tidymodels
  • speed
  • string