Skip to content

Combining BenchmarkAggr objects #39

Description

@jemus42

I have a use case where a bmr is aggregated using many measures, and it may be easier to parallelize over measures to speed up overall aggregating.

Here's an example including an experimental combination function I wrote for testing:

library(mlr3)
library(mlr3proba)
library(mlr3benchmark)
lgr::get_logger("mlr3")$set_threshold("warn")

measures = list(
  msr("surv.cindex",      id = "harrell_c",                                 label = "Harrell's C"),
  msr("surv.cindex",      id = "uno_c",                 weight_meth = "G2", label = "Uno's C"),

  msr("surv.rcll",        id = "rcll",                  ERV = FALSE,        label = "Right-Censored Log Loss"),
  msr("surv.rcll",        id = "rcll_erv",              ERV = TRUE,         label = "Right-Censored Log Loss (ERV)"),

  msr("surv.logloss",     id = "logloss",               ERV = FALSE,        label = "Log Loss"),
  msr("surv.logloss",     id = "logloss_erv",           ERV = TRUE,         label = "Log Loss (ERV)"),

  msr("surv.intlogloss",  id = "intlogloss_proper",     ERV = FALSE, proper = TRUE, label = "Integrated Log Loss (Proper)"),
  msr("surv.intlogloss",  id = "intlogloss_proper_erv", ERV = TRUE,  proper = TRUE, label = "Integrated Log Loss (Proper, ERV)"),

  msr("surv.calib_alpha", id = "caliba",                label = "Van Houwelingen's Alpha"),
  msr("surv.dcalib",      id = "dcalib", truncate = 10, label = "D-Calibration (truncated)"),

  msr("surv.graf",        id = "graf_proper",       proper = TRUE,   ERV = FALSE, label = "Graf Score (Proper)"),
  msr("surv.graf",        id = "graf_proper_erv",   proper = TRUE,   ERV = TRUE,  label = "Graf Score (Proper, ERV)"),
  msr("surv.graf",        id = "graf_improper",     proper = FALSE,  ERV = FALSE, label = "Graf Score (Improper)"),
  msr("surv.graf",        id = "graf_improper_erv", proper = FALSE,  ERV = TRUE,  label = "Graf Score (Improper, ERV)")
)
names(measures) = mlr3misc::ids(measures)

# Example bmr
bmr = benchmark(benchmark_grid(
  tasks = tsks(c("rats", "gbcs", "grace")),
  learners = lrns(c("surv.kaplan", "surv.coxph")),
  resamplings = rsmp("holdout")
), store_backends = TRUE)

bmr
#> <BenchmarkResult> of 6 rows with 6 resampling runs
#>  nr task_id  learner_id resampling_id iters warnings errors
#>   1    rats surv.kaplan       holdout     1        0      0
#>   2    rats  surv.coxph       holdout     1        0      0
#>   3    gbcs surv.kaplan       holdout     1        0      0
#>   4    gbcs  surv.coxph       holdout     1        0      0
#>   5   grace surv.kaplan       holdout     1        0      0
#>   6   grace  surv.coxph       holdout     1        0      0

# Score separately, hold resulting bmas in list
bmalist = mlr3misc::named_list(mlr3misc::ids(measures))
for (measure in measures) {
  bmalist[[measure$id]] = mlr3benchmark::as_benchmark_aggr(bmr, measures = measure)
}

bmalist[1:3]
#> $harrell_c
#> <BenchmarkAggr> of 6 rows with 3 tasks, 2 learners and 1 measure
#>    task_id learner_id harrell_c
#> 1:    rats     kaplan 0.5000000
#> 2:    rats      coxph 0.8183594
#> 3:    gbcs     kaplan 0.5000000
#> 4:    gbcs      coxph 0.7394313
#> 5:   grace     kaplan 0.5000000
#> 6:   grace      coxph 0.8564613
#> 
#> $uno_c
#> <BenchmarkAggr> of 6 rows with 3 tasks, 2 learners and 1 measure
#>    task_id learner_id     uno_c
#> 1:    rats     kaplan 0.5000000
#> 2:    rats      coxph 0.8372653
#> 3:    gbcs     kaplan 0.5000000
#> 4:    gbcs      coxph 0.7217345
#> 5:   grace     kaplan 0.5000000
#> 6:   grace      coxph 0.8505907
#> 
#> $rcll
#> <BenchmarkAggr> of 6 rows with 3 tasks, 2 learners and 1 measure
#>    task_id learner_id     rcll
#> 1:    rats     kaplan 3.180493
#> 2:    rats      coxph 3.124062
#> 3:    gbcs     kaplan 7.258260
#> 4:    gbcs      coxph 7.199384
#> 5:   grace     kaplan 3.770636
#> 6:   grace      coxph 3.445030

My experimental function works on a list with n > 1 BenchmarkAggr objects, which I assume to be more useful than e.g a $combine() method that would only join 2 objects, but I'm not sure about the API.

#' Combine a list of bma objects to a single bma
#' 
#' Joins respective $data fields on “learner_id”, “task_id”.
#' @param bmalist List of `BenchmarkAggr` objects.
#' @return An object of class `BenchmarkAggr`.

combine_bma = function(bmalist) {
  sapply(bmalist, \(x) checkmate::assert_class(x, classes = "BenchmarkAggr"))

  # Initial dt for consecutive joins, needs factor vars
  dt = data.table::data.table(task_id = factor(1), learner_id = factor(1))

  # Joining $data fields containing scores as dt
  for (aggr in seq_along(bmalist)) {
    # print(names(bmalist[aggr]))
    dt = dt[bmalist[[aggr]]$data, on = c("learner_id", "task_id")]
  }

  # Converting to bma again
  mlr3benchmark::as_benchmark_aggr(dt)
}

combine_bma(bmalist)
#> <BenchmarkAggr> of 6 rows with 3 tasks, 2 learners and 14 measures
#>    task_id learner_id harrell_c     uno_c     rcll    rcll_erv   logloss
#> 1:    rats     kaplan 0.5000000 0.5000000 3.180493 0.000000000 21.752574
#> 2:    rats      coxph 0.8183594 0.8372653 3.124062 0.017742667 21.377039
#> 3:    gbcs     kaplan 0.5000000 0.5000000 7.258260 0.000000000 32.781586
#> 4:    gbcs      coxph 0.7394313 0.7217345 7.199384 0.008111614 32.787356
#> 5:   grace     kaplan 0.5000000 0.5000000 3.770636 0.000000000  9.926067
#> 6:   grace      coxph 0.8564613 0.8505907 3.445030 0.086353110  9.055365
#>      logloss_erv intlogloss_proper intlogloss_proper_erv    caliba     dcalib
#> 1:  0.0000000000         0.1525563            0.00000000 1.0072800 0.01037591
#> 2:  0.0172639721         0.1224677            0.19722946 1.0026337 0.43158202
#> 3:  0.0000000000         0.2403609            0.00000000 0.7743133 3.84231309
#> 4: -0.0001759957         0.2238057            0.06887646 0.9429916 0.71061424
#> 5:  0.0000000000         0.4261547            0.00000000 1.1657555 5.85295235
#> 6:  0.0877187299         0.2423848            0.43122818 1.1925903 4.79665437
#>    graf_proper graf_proper_erv graf_improper graf_improper_erv
#> 1:  0.04949192       0.0000000    0.05400789         0.0000000
#> 2:  0.04157216       0.1600213    0.04723149         0.1254706
#> 3:  0.08935573       0.0000000    0.13500880         0.0000000
#> 4:  0.08019706       0.1024968    0.10572968         0.2168683
#> 5:  0.16694804       0.0000000    0.21295790         0.0000000
#> 6:  0.08578223       0.4861741    0.09824500         0.5386647
combine_bma(c(bmalist$harrell_c, bmalist$uno_c))
#> <BenchmarkAggr> of 6 rows with 3 tasks, 2 learners and 2 measures
#>    task_id learner_id harrell_c     uno_c
#> 1:    rats     kaplan 0.5000000 0.5000000
#> 2:    rats      coxph 0.8183594 0.8372653
#> 3:    gbcs     kaplan 0.5000000 0.5000000
#> 4:    gbcs      coxph 0.7394313 0.7217345
#> 5:   grace     kaplan 0.5000000 0.5000000
#> 6:   grace      coxph 0.8564613 0.8505907

Created on 2024-01-24 with reprex v2.1.0

Session info
sessioninfo::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.3.2 (2023-10-31)
#>  os       macOS Sonoma 14.2.1
#>  system   aarch64, darwin20
#>  ui       X11
#>  language (EN)
#>  collate  en_US.UTF-8
#>  ctype    en_US.UTF-8
#>  tz       Europe/Berlin
#>  date     2024-01-24
#>  pandoc   3.1.1 @ /System/Volumes/Data/Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/ (via rmarkdown)
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────
#>  package        * version     date (UTC) lib source
#>  backports        1.4.1       2021-12-13 [1] CRAN (R 4.3.0)
#>  checkmate        2.3.1       2023-12-04 [1] CRAN (R 4.3.1)
#>  cli              3.6.2       2023-12-11 [1] CRAN (R 4.3.1)
#>  codetools        0.2-19      2023-02-01 [2] CRAN (R 4.3.2)
#>  colorspace       2.1-0       2023-01-23 [1] CRAN (R 4.3.0)
#>  crayon           1.5.2       2022-09-29 [1] CRAN (R 4.3.0)
#>  data.table       1.14.10     2023-12-08 [1] CRAN (R 4.3.1)
#>  dictionar6       0.1.3       2021-09-13 [1] CRAN (R 4.3.0)
#>  digest           0.6.34      2024-01-11 [1] CRAN (R 4.3.1)
#>  distr6           1.8.4       2023-11-13 [1] Github (xoopR/distr6@1854b22)
#>  dplyr            1.1.4       2023-11-17 [1] CRAN (R 4.3.1)
#>  evaluate         0.23        2023-11-01 [1] CRAN (R 4.3.1)
#>  fansi            1.0.6       2023-12-08 [1] CRAN (R 4.3.1)
#>  fastmap          1.1.1       2023-02-24 [1] CRAN (R 4.3.0)
#>  fs               1.6.3       2023-07-20 [1] CRAN (R 4.3.0)
#>  future           1.33.1      2023-12-22 [1] CRAN (R 4.3.1)
#>  future.apply     1.11.1      2023-12-21 [1] CRAN (R 4.3.1)
#>  generics         0.1.3       2022-07-05 [1] CRAN (R 4.3.0)
#>  ggplot2          3.4.4       2023-10-12 [1] CRAN (R 4.3.1)
#>  globals          0.16.2      2022-11-21 [1] CRAN (R 4.3.0)
#>  glue             1.7.0       2024-01-09 [1] CRAN (R 4.3.1)
#>  gtable           0.3.4       2023-08-21 [1] CRAN (R 4.3.0)
#>  htmltools        0.5.7       2023-11-03 [1] CRAN (R 4.3.1)
#>  knitr            1.45        2023-10-30 [1] CRAN (R 4.3.1)
#>  lattice          0.21-9      2023-10-01 [1] CRAN (R 4.3.1)
#>  lgr              0.4.4       2022-09-05 [1] CRAN (R 4.3.0)
#>  lifecycle        1.0.4       2023-11-07 [1] CRAN (R 4.3.1)
#>  listenv          0.9.0       2022-12-16 [1] CRAN (R 4.3.0)
#>  magrittr         2.0.3       2022-03-30 [1] CRAN (R 4.3.0)
#>  Matrix           1.6-1.1     2023-09-18 [1] CRAN (R 4.3.1)
#>  mlr3           * 0.17.2      2024-01-09 [1] CRAN (R 4.3.1)
#>  mlr3benchmark  * 0.1.6       2023-05-30 [1] CRAN (R 4.3.0)
#>  mlr3misc         0.13.0-9000 2023-10-17 [1] Github (mlr-org/mlr3misc@43c0ffa)
#>  mlr3pipelines    0.5.0-2     2023-12-08 [1] CRAN (R 4.3.1)
#>  mlr3proba      * 0.5.8       2024-01-24 [1] Github (mlr-org/mlr3proba@930d8b0)
#>  mlr3viz          0.7.0.9000  2023-12-22 [1] Github (mlr-org/mlr3viz@73aa4ec)
#>  munsell          0.5.0       2018-06-12 [1] CRAN (R 4.3.0)
#>  ooplah           0.2.0       2022-01-21 [1] CRAN (R 4.3.0)
#>  palmerpenguins   0.1.1       2022-08-15 [1] CRAN (R 4.3.0)
#>  paradox          0.11.1      2023-03-17 [1] CRAN (R 4.3.0)
#>  parallelly       1.36.0      2023-05-26 [1] CRAN (R 4.3.0)
#>  param6           0.2.4       2023-07-24 [1] Github (xoopR/param6@0fa3577)
#>  pillar           1.9.0       2023-03-22 [1] CRAN (R 4.3.0)
#>  pkgconfig        2.0.3       2019-09-22 [1] CRAN (R 4.3.0)
#>  purrr            1.0.2       2023-08-10 [1] CRAN (R 4.3.0)
#>  R.cache          0.16.0      2022-07-21 [1] CRAN (R 4.3.0)
#>  R.methodsS3      1.8.2       2022-06-13 [1] CRAN (R 4.3.0)
#>  R.oo             1.26.0      2024-01-24 [1] CRAN (R 4.3.1)
#>  R.utils          2.12.3      2023-11-18 [1] CRAN (R 4.3.1)
#>  R6               2.5.1       2021-08-19 [1] CRAN (R 4.3.0)
#>  Rcpp             1.0.12      2024-01-09 [1] CRAN (R 4.3.1)
#>  reprex           2.1.0       2024-01-11 [1] CRAN (R 4.3.1)
#>  RhpcBLASctl      0.23-42     2023-02-11 [1] CRAN (R 4.3.0)
#>  rlang            1.1.3       2024-01-10 [1] CRAN (R 4.3.1)
#>  rmarkdown        2.25        2023-09-18 [1] CRAN (R 4.3.1)
#>  rstudioapi       0.15.0      2023-07-07 [1] CRAN (R 4.3.0)
#>  scales           1.3.0       2023-11-28 [1] CRAN (R 4.3.1)
#>  sessioninfo      1.2.2       2021-12-06 [1] CRAN (R 4.3.0)
#>  set6             0.2.6       2023-10-16 [1] Github (xoopR/set6@a901255)
#>  styler           1.10.2.9000 2024-01-24 [1] Github (r-lib/styler@ffe79c1)
#>  survival         3.5-7       2023-08-14 [1] CRAN (R 4.3.0)
#>  survivalmodels   0.1.18      2023-11-21 [1] Github (RaphaelS1/survivalmodels@79b913f)
#>  tibble           3.2.1       2023-03-20 [1] CRAN (R 4.3.0)
#>  tidyselect       1.2.0       2022-10-10 [1] CRAN (R 4.3.0)
#>  utf8             1.2.4       2023-10-22 [1] CRAN (R 4.3.1)
#>  uuid             1.2-0       2024-01-14 [1] CRAN (R 4.3.1)
#>  vctrs            0.6.5       2023-12-01 [1] CRAN (R 4.3.1)
#>  withr            3.0.0       2024-01-16 [1] CRAN (R 4.3.1)
#>  xfun             0.41        2023-11-01 [1] CRAN (R 4.3.1)
#>  yaml             2.3.8       2023-12-11 [1] CRAN (R 4.3.1)
#> 
#>  [1] /Users/Lukas/Library/R/arm64/4.3/library
#>  [2] /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/library
#> 
#> ──────────────────────────────────────────────────────────────────────────────

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions