├── .ignore
├── man-roxygen
├── param_task.R
├── param_ydt.R
├── param_fselector.R
├── param_id.R
├── param_extra.R
├── param_param_set.R
├── param_callbacks.R
├── param_store_models.R
├── param_learner.R
├── param_rush.R
├── param_terminator.R
├── param_measure.R
├── field_id.R
├── param_store_benchmark_result.R
├── param_term_evals.R
├── param_term_time.R
├── param_inst_async.R
├── param_check_values.R
├── param_label.R
├── param_measures.R
├── param_search_space.R
├── param_packages.R
├── section_dictionary_fselectors.R
├── param_properties.R
├── param_man.R
├── param_codomain.R
├── param_xdt.R
├── param_store_fselect_instance.R
├── param_resampling.R
├── param_ties_method.R
└── example.R
├── man
├── figures
│ └── logo.png
├── mlr3fselect.async_freeze_archive.Rd
├── mlr3fselect.internal_tuning.Rd
├── reexports.Rd
├── mlr3fselect.backup.Rd
├── assert_async_fselect_callback.Rd
├── mlr3fselect_assertions.Rd
├── faggregate.Rd
├── mlr3fselect.one_se_rule.Rd
├── mlr3fselect.svm_rfe.Rd
├── mlr3fselect-package.Rd
├── fs.Rd
├── mlr_fselectors.Rd
├── extract_inner_fselect_results.Rd
├── extract_inner_fselect_archives.Rd
├── ObjectiveFSelectAsync.Rd
├── ContextAsyncFSelect.Rd
├── ContextBatchFSelect.Rd
├── fselect_nested.Rd
├── mlr_fselectors_async_design_points.Rd
├── embedded_ensemble_fselect.Rd
├── mlr_fselectors_async_random_search.Rd
├── FSelectorBatchFromOptimizerBatch.Rd
├── FSelectorAsync.Rd
├── CallbackBatchFSelect.Rd
├── CallbackAsyncFSelect.Rd
├── mlr_fselectors_async_exhaustive_search.Rd
└── callback_batch_fselect.Rd
├── tests
├── testthat
│ ├── teardown.R
│ ├── test_FSelectorGeneticSearch.R
│ ├── helper.R
│ ├── test_FSelectorRandomSearch.R
│ ├── setup.R
│ ├── test_mlr_fselectors.R
│ ├── test_fselect_nested.R
│ ├── test_FSelectorBatchDesignPoints.R
│ ├── test_FSelectorAsyncRandomSearch.R
│ ├── test_FSelectorAsyncExhaustiveSearch.R
│ ├── test_FSelectorAsyncDesignPoints.R
│ ├── test_FSelectorExhaustiveSearch.R
│ ├── test_ArchiveAsyncFSelectFrozen.R
│ ├── test_FSelectorSequential.R
│ ├── test_fsi_async.R
│ ├── test_FSelectInstanceMultiCrit.R
│ ├── test_auto_fselector.R
│ ├── test_fsi.R
│ ├── test_fselect.R
│ ├── test_FSelectorShadowVariableSearch.R
│ └── test_embedded_ensemble_fselect.R
└── testthat.R
├── R
├── reexports.R
├── helper.R
├── FSelectorAsyncDesignPoints.R
├── FSelectorAsync.R
├── zzz.R
├── mlr_fselectors.R
├── auto_fselector.R
├── assertions.R
├── FSelectorAsyncRandomSearch.R
├── FSelectorBatchFromOptimizerBatch.R
├── FSelectorBatchGeneticSearch.R
├── FSelectorAsyncFromOptimizerAsync.R
├── FSelectorBatchExhaustiveSearch.R
├── FSelectorBatchDesignPoints.R
├── fselect_nested.R
├── ContextAsyncFSelect.R
├── ContextBatchFSelect.R
├── FSelectorAsyncExhaustiveSearch.R
├── ObjectiveFSelect.R
├── faggregate.R
├── FSelectorBatchRandomSearch.R
├── ObjectiveFSelectAsync.R
├── extract_inner_fselect_results.R
├── extract_inner_fselect_archives.R
├── FSelectorBatch.R
├── FSelectInstanceAsyncSingleCrit.R
├── FSelectInstanceAsyncMultiCrit.R
├── embedded_ensemble_fselect.R
└── FSelectorBatchSequential.R
├── .editorconfig
├── .Rbuildignore
├── mlr3fselect.Rproj
├── .lintr
├── inst
├── WORDLIST
└── testthat
│ ├── helper_expectations.R
│ ├── helper_fselector.R
│ └── helper_misc.R
├── pkgdown
└── _pkgdown.yml
├── .github
└── workflows
│ ├── pkgdown.yml
│ ├── r-cmd-check.yml
│ ├── no-suggest-cmd-check.yml
│ └── dev-cmd-check.yml
├── attic
└── test_FSelectorEvolutionary.R
├── NAMESPACE
├── DESCRIPTION
└── .gitignore
/.ignore:
--------------------------------------------------------------------------------
1 | man/
2 | docs/
3 | inst/doc/
4 | attic/
5 | vignettes/*.html
6 |
--------------------------------------------------------------------------------
/man-roxygen/param_task.R:
--------------------------------------------------------------------------------
1 | #' @param task ([mlr3::Task])\cr
2 | #' Task to operate on.
3 |
--------------------------------------------------------------------------------
/man-roxygen/param_ydt.R:
--------------------------------------------------------------------------------
1 | #' @param ydt ([data.table::data.table()])\cr
2 | #' Optimal outcome.
3 |
--------------------------------------------------------------------------------
/man/figures/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mlr-org/mlr3fselect/HEAD/man/figures/logo.png
--------------------------------------------------------------------------------
/man-roxygen/param_fselector.R:
--------------------------------------------------------------------------------
1 | #' @param fselector ([FSelector])\cr
2 | #' Optimization algorithm.
3 |
--------------------------------------------------------------------------------
/man-roxygen/param_id.R:
--------------------------------------------------------------------------------
1 | #' @param id (`character(1)`)\cr
2 | #' Identifier for the new instance.
3 |
--------------------------------------------------------------------------------
/man-roxygen/param_extra.R:
--------------------------------------------------------------------------------
1 | #' @param extra (`data.table::data.table()`)\cr
2 | #' Additional information.
3 |
--------------------------------------------------------------------------------
/man-roxygen/param_param_set.R:
--------------------------------------------------------------------------------
1 | #' @param param_set [paradox::ParamSet]\cr
2 | #' Set of control parameters.
3 |
--------------------------------------------------------------------------------
/man-roxygen/param_callbacks.R:
--------------------------------------------------------------------------------
1 | #' @param callbacks (list of [CallbackBatchFSelect])\cr
2 | #' List of callbacks.
3 |
--------------------------------------------------------------------------------
/man-roxygen/param_store_models.R:
--------------------------------------------------------------------------------
1 | #' @param store_models (`logical(1)`).
2 | #' Store models in benchmark result?
3 |
--------------------------------------------------------------------------------
/man-roxygen/param_learner.R:
--------------------------------------------------------------------------------
1 | #' @param learner ([mlr3::Learner])\cr
2 | #' Learner to optimize the feature subset for.
3 |
--------------------------------------------------------------------------------
/man-roxygen/param_rush.R:
--------------------------------------------------------------------------------
1 | #' @param rush (`Rush`)\cr
2 | #' If a rush instance is supplied, the optimization runs without batches.
3 |
--------------------------------------------------------------------------------
/man-roxygen/param_terminator.R:
--------------------------------------------------------------------------------
1 | #' @param terminator ([bbotk::Terminator])\cr
2 | #' Stop criterion of the feature selection.
3 |
--------------------------------------------------------------------------------
/man-roxygen/param_measure.R:
--------------------------------------------------------------------------------
1 | #' @param measure ([mlr3::Measure])\cr
2 | #' Measure to optimize. If `NULL`, default measure is used.
3 |
--------------------------------------------------------------------------------
/man-roxygen/field_id.R:
--------------------------------------------------------------------------------
1 | #' @field id (`character(1)`)\cr
2 | #' Identifier of the object.
3 | #' Used in tables, plot and text output.
4 |
--------------------------------------------------------------------------------
/man-roxygen/param_store_benchmark_result.R:
--------------------------------------------------------------------------------
1 | #' @param store_benchmark_result (`logical(1)`)\cr
2 | #' Store benchmark result in archive?
3 |
--------------------------------------------------------------------------------
/tests/testthat/teardown.R:
--------------------------------------------------------------------------------
1 | options(old_opts)
2 | lg_mlr3$set_threshold(old_threshold_mlr3)
3 | lg_rush$set_threshold(old_threshold_rush)
4 |
5 |
--------------------------------------------------------------------------------
/man-roxygen/param_term_evals.R:
--------------------------------------------------------------------------------
1 | #' @param term_evals (`integer(1)`)\cr
2 | #' Number of allowed evaluations.
3 | #' Ignored if `terminator` is passed.
4 |
--------------------------------------------------------------------------------
/man-roxygen/param_term_time.R:
--------------------------------------------------------------------------------
1 | #' @param term_time (`integer(1)`)\cr
2 | #' Maximum allowed time in seconds.
3 | #' Ignored if `terminator` is passed.
4 |
--------------------------------------------------------------------------------
/man-roxygen/param_inst_async.R:
--------------------------------------------------------------------------------
1 | #' @param inst ([FSelectInstanceAsyncSingleCrit] | [FSelectInstanceAsyncMultiCrit] )\cr
2 | #' The feature selection instance.
3 |
--------------------------------------------------------------------------------
/man-roxygen/param_check_values.R:
--------------------------------------------------------------------------------
1 | #' @param check_values (`logical(1)`)\cr
2 | #' Check the parameters before the evaluation and the results for
3 | #' validity?
4 |
--------------------------------------------------------------------------------
/man-roxygen/param_label.R:
--------------------------------------------------------------------------------
1 | #' @param label (`character(1)`)\cr
2 | #' Label for this object.
3 | #' Can be used in tables, plot and text output instead of the ID.
4 |
--------------------------------------------------------------------------------
/man-roxygen/param_measures.R:
--------------------------------------------------------------------------------
1 | #' @param measures (list of [mlr3::Measure])\cr
2 | #' Measures to optimize.
3 | #' If `NULL`, \CRANpkg{mlr3}'s default measure is used.
4 |
--------------------------------------------------------------------------------
/man-roxygen/param_search_space.R:
--------------------------------------------------------------------------------
1 | #' @param search_space ([paradox::ParamSet])\cr
2 | #' Search space.
3 | #' Internally created from provided [mlr3::Task] by instance.
4 |
5 |
--------------------------------------------------------------------------------
/tests/testthat.R:
--------------------------------------------------------------------------------
1 | if (requireNamespace("testthat", quietly = TRUE)) {
2 | library(testthat)
3 | library(checkmate)
4 | library(mlr3fselect)
5 | test_check("mlr3fselect")
6 | }
7 |
--------------------------------------------------------------------------------
/tests/testthat/test_FSelectorGeneticSearch.R:
--------------------------------------------------------------------------------
1 | skip_if_not_installed("genalg")
2 |
3 | test_that("default parameters work", {
4 | test_fselector("genetic_search", term_evals = 10)
5 | })
6 |
--------------------------------------------------------------------------------
/man-roxygen/param_packages.R:
--------------------------------------------------------------------------------
1 | #' @param packages (`character()`)\cr
2 | #' Set of required packages.
3 | #' Note that these packages will be loaded via [requireNamespace()], and are not attached.
4 |
--------------------------------------------------------------------------------
/man-roxygen/section_dictionary_fselectors.R:
--------------------------------------------------------------------------------
1 | #' @section Dictionary:
2 | #' This [FSelector] can be instantiated with the associated sugar function [fs()]:
3 | #' ```
4 | #' fs("<%= id %>")
5 | #' ```
6 |
--------------------------------------------------------------------------------
/man-roxygen/param_properties.R:
--------------------------------------------------------------------------------
1 | #' @param properties (`character()`)\cr
2 | #' Set of properties of the fselector.
3 | #' Must be a subset of [`mlr_reflections$fselect_properties`][mlr3::mlr_reflections].
4 |
--------------------------------------------------------------------------------
/man-roxygen/param_man.R:
--------------------------------------------------------------------------------
1 | #' @param man (`character(1)`)\cr
2 | #' String in the format `[pkg]::[topic]` pointing to a manual page for this object.
3 | #' The referenced help package can be opened via method `$help()`.
4 |
--------------------------------------------------------------------------------
/R/reexports.R:
--------------------------------------------------------------------------------
1 | #' @export
2 | bbotk::mlr_terminators
3 |
4 | #' @export
5 | bbotk::trm
6 |
7 | #' @export
8 | bbotk::trms
9 |
10 | #' @export
11 | mlr3misc::mlr_callbacks
12 |
13 | #' @export
14 | mlr3misc::clbk
15 |
16 | #' @export
17 | mlr3misc::clbks
18 |
--------------------------------------------------------------------------------
/man-roxygen/param_codomain.R:
--------------------------------------------------------------------------------
1 | #' @param codomain ([paradox::ParamSet])\cr
2 | #' Specifies codomain of function.
3 | #' Most importantly the tags of each output "Parameter" define whether it should
4 | #' be minimized or maximized. The default is to minimize each component.
5 |
--------------------------------------------------------------------------------
/man-roxygen/param_xdt.R:
--------------------------------------------------------------------------------
1 | #' @param xdt (`data.table::data.table()`)\cr
2 | #' x values as `data.table`. Each row is one point. Contains the value in
3 | #' the *search space* of the [FSelectInstanceBatchMultiCrit] object. Can contain
4 | #' additional columns for extra information.
5 |
--------------------------------------------------------------------------------
/man-roxygen/param_store_fselect_instance.R:
--------------------------------------------------------------------------------
1 | #' @param store_fselect_instance (`logical(1)`)\cr
2 | #' If `TRUE` (default), stores the internally created [FSelectInstanceBatchSingleCrit] with all intermediate results in slot `$fselect_instance`.
3 | #' Is set to `TRUE`, if `store_models = TRUE`
4 |
--------------------------------------------------------------------------------
/man-roxygen/param_resampling.R:
--------------------------------------------------------------------------------
1 | #' @param resampling ([mlr3::Resampling])\cr
2 | #' Resampling that is used to evaluated the performance of the feature subsets.
3 | #' Uninstantiated resamplings are instantiated during construction so that all feature subsets are evaluated on the same data splits.
4 | #' Already instantiated resamplings are kept unchanged.
5 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # See http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | end_of_line = lf
7 | insert_final_newline = true
8 | indent_style = space
9 | trim_trailing_whitespace = true
10 |
11 | [*.{r,R,md,Rmd}]
12 | indent_size = 2
13 |
14 | [*.{c,h}]
15 | indent_size = 4
16 |
17 | [*.{cpp,hpp}]
18 | indent_size = 4
19 |
20 | [{NEWS.md,DESCRIPTION,LICENSE}]
21 | max_line_length = 80
22 |
--------------------------------------------------------------------------------
/tests/testthat/helper.R:
--------------------------------------------------------------------------------
1 | # nolint start
2 | library(mlr3)
3 | library(mlr3misc)
4 | library(paradox)
5 | library(R6)
6 | library(data.table)
7 |
8 | lapply(list.files(system.file("testthat", package = "mlr3"), pattern = "^helper.*\\.[rR]", full.names = TRUE), source)
9 | lapply(list.files(system.file("testthat", package = "mlr3fselect"), pattern = "^helper.*\\.[rR]", full.names = TRUE), source)
10 | # nolint end
11 |
--------------------------------------------------------------------------------
/.Rbuildignore:
--------------------------------------------------------------------------------
1 |
2 | ^README\.Rmd$
3 | ^README\.html$
4 | ^LICENSE$
5 | ^\.github$
6 | ^codecov\.yml$
7 | ^tic\.R$
8 | ^appveyor\.yml$
9 | ^\.travis\.yml$
10 | ^.*\.Rproj$
11 | ^\.Rproj\.user$
12 | ^\.editorconfig$
13 | ^\.ignore$
14 | ^docs$
15 | ^pkgdown$
16 | ^renv$
17 | ^renv\.lock$
18 | ^\.ccache$
19 | ^clang-.*
20 | man-roxygen
21 | ^\.lintr$
22 | ^\.vscode$
23 | ^attic$
24 | ^cran-comments\.md$
25 | ^CRAN-RELEASE$
26 | ^CRAN-SUBMISSION$
27 | ^revdep$
28 |
--------------------------------------------------------------------------------
/tests/testthat/test_FSelectorRandomSearch.R:
--------------------------------------------------------------------------------
1 | test_that("default parameters work", {
2 | test_fselector("random_search", batch_size = 5, term_evals = 10)
3 | })
4 |
5 | test_that("max_features parameter work", {
6 | z = test_fselector("random_search", max_features = 1, term_evals = 10)
7 | a = z$inst$archive$data
8 | expect_feature_number(a[, 1:4], n = 1)
9 | })
10 |
11 | test_that("multi-crit works", {
12 | test_fselector_2D("random_search", batch_size = 5, term_evals = 10)
13 | })
14 |
--------------------------------------------------------------------------------
/man/mlr3fselect.async_freeze_archive.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/mlr_callbacks.R
3 | \name{mlr3fselect.async_freeze_archive}
4 | \alias{mlr3fselect.async_freeze_archive}
5 | \title{Freeze Archive Callback}
6 | \description{
7 | This \link{CallbackAsyncFSelect} freezes the \link{ArchiveAsyncFSelect} to \link{ArchiveAsyncFSelectFrozen} after the optimization has finished.
8 | }
9 | \examples{
10 | clbk("mlr3fselect.async_freeze_archive")
11 | }
12 |
--------------------------------------------------------------------------------
/mlr3fselect.Rproj:
--------------------------------------------------------------------------------
1 | Version: 1.0
2 | ProjectId: 525fdb42-84c9-412c-ab6a-7ca5904c3d37
3 |
4 | RestoreWorkspace: No
5 | SaveWorkspace: No
6 | AlwaysSaveHistory: Default
7 |
8 | EnableCodeIndexing: Yes
9 | UseSpacesForTab: Yes
10 | NumSpacesForTab: 2
11 | Encoding: UTF-8
12 |
13 | RnwWeave: Sweave
14 | LaTeX: pdfLaTeX
15 |
16 | AutoAppendNewline: Yes
17 | StripTrailingWhitespace: Yes
18 | LineEndingConversion: Posix
19 |
20 | BuildType: Package
21 | PackageUseDevtools: Yes
22 | PackageRoxygenize: rd,collate,namespace
23 |
--------------------------------------------------------------------------------
/man-roxygen/param_ties_method.R:
--------------------------------------------------------------------------------
1 | #' @param ties_method (`character(1)`)\cr
2 | #' The method to break ties when selecting sets while optimizing and when selecting the best set.
3 | #' Can be `"least_features"` or `"random"`.
4 | #' The option `"least_features"` (default) selects the feature set with the least features.
5 | #' If there are multiple best feature sets with the same number of features, one is selected randomly.
6 | #' The `random` method returns a random feature set from the best feature sets.
7 | #' Ignored if multiple measures are used.
8 |
--------------------------------------------------------------------------------
/man/mlr3fselect.internal_tuning.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/mlr_callbacks.R
3 | \name{mlr3fselect.internal_tuning}
4 | \alias{mlr3fselect.internal_tuning}
5 | \title{Internal Tuning Callback}
6 | \description{
7 | This callback runs internal tuning alongside the feature selection.
8 | The internal tuning values are aggregated and stored in the results.
9 | The final model is trained with the best feature set and the tuned value.
10 | }
11 | \examples{
12 | clbk("mlr3fselect.internal_tuning")
13 | }
14 |
--------------------------------------------------------------------------------
/.lintr:
--------------------------------------------------------------------------------
1 | linters: linters_with_defaults(
2 | # lintr defaults: https://github.com/jimhester/lintr#available-linters
3 | # the following setup changes/removes certain linters
4 | assignment_linter = NULL, # do not force using <- for assignments
5 | object_name_linter = object_name_linter(c("snake_case", "CamelCase")), # only allow snake case and camel case object names
6 | cyclocomp_linter = NULL, # do not check function complexity
7 | commented_code_linter = NULL, # allow code in comments
8 | line_length_linter = NULL
9 | )
10 |
11 |
--------------------------------------------------------------------------------
/tests/testthat/setup.R:
--------------------------------------------------------------------------------
1 | library("mlr3")
2 | library("checkmate")
3 |
4 | old_opts = options(
5 | warnPartialMatchArgs = TRUE,
6 | warnPartialMatchAttr = TRUE,
7 | warnPartialMatchDollar = TRUE
8 | )
9 |
10 | # https://github.com/HenrikBengtsson/Wishlist-for-R/issues/88
11 | old_opts = lapply(old_opts, function(x) if (is.null(x)) FALSE else x)
12 |
13 | lg_mlr3 = lgr::get_logger("mlr3")
14 | lg_rush = lgr::get_logger("rush")
15 |
16 | old_threshold_mlr3 = lg_mlr3$threshold
17 | old_threshold_rush = lg_rush$threshold
18 |
19 | lg_mlr3$set_threshold(0)
20 | lg_rush$set_threshold(0)
21 |
22 |
23 |
--------------------------------------------------------------------------------
/tests/testthat/test_mlr_fselectors.R:
--------------------------------------------------------------------------------
1 | test_that("mlr_fselectors", {
2 | expect_dictionary(mlr_fselectors, min_items = 1L)
3 | keys = mlr_fselectors$keys()
4 |
5 | for (key in keys) {
6 | fselector = fs(key)
7 | expect_r6(fselector, "FSelector")
8 | }
9 | })
10 |
11 | test_that("mlr_fselectors sugar", {
12 | expect_class(fs("random_search"), "FSelector")
13 | expect_class(fss(c("random_search", "random_search")), "list")
14 | })
15 |
16 | test_that("as.data.table objects parameter", {
17 | tab = as.data.table(mlr_fselectors, objects = TRUE)
18 | expect_data_table(tab)
19 | expect_list(tab$object, "FSelector", any.missing = FALSE)
20 | })
21 |
--------------------------------------------------------------------------------
/tests/testthat/test_fselect_nested.R:
--------------------------------------------------------------------------------
1 | test_that("fselect_nested function works", {
2 | rr = fselect_nested(fselector = fs("random_search"), task = tsk("pima"), learner = lrn("classif.rpart"),
3 | inner_resampling = rsmp ("holdout"), outer_resampling = rsmp("cv", folds = 3), measure = msr("classif.ce"),
4 | term_evals = 2)
5 |
6 | expect_resample_result(rr)
7 | expect_equal(rr$resampling$id, "cv")
8 | expect_equal(rr$resampling$iters, 3)
9 | expect_data_table(extract_inner_fselect_results(rr), nrows = 3)
10 | expect_class(rr$learners[[1]], "AutoFSelector")
11 | expect_equal(rr$learners[[1]]$fselect_instance$objective$resampling$id, "holdout")
12 | })
13 |
--------------------------------------------------------------------------------
/tests/testthat/test_FSelectorBatchDesignPoints.R:
--------------------------------------------------------------------------------
1 | test_that("default parameters work", {
2 | design = data.table(
3 | x1 = c(TRUE, FALSE),
4 | x2 = c(TRUE, FALSE),
5 | x3 = c(FALSE, TRUE),
6 | x4 = c(FALSE, TRUE))
7 |
8 | z = test_fselector("design_points", design = design)
9 | a = z$inst$archive$data
10 | expect_equal(a[, 1:4], design)
11 | })
12 |
13 | test_that("multi-crit works", {
14 | design = data.table(
15 | x1 = c(TRUE, FALSE),
16 | x2 = c(TRUE, FALSE),
17 | x3 = c(FALSE, TRUE),
18 | x4 = c(FALSE, TRUE))
19 |
20 | z = test_fselector_2D("design_points", design = design)
21 | a = z$inst$archive$data
22 | expect_equal(a[, 1:4], design)
23 | })
24 |
--------------------------------------------------------------------------------
/man/reexports.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/reexports.R
3 | \docType{import}
4 | \name{reexports}
5 | \alias{reexports}
6 | \alias{mlr_terminators}
7 | \alias{trm}
8 | \alias{trms}
9 | \alias{mlr_callbacks}
10 | \alias{clbk}
11 | \alias{clbks}
12 | \title{Objects exported from other packages}
13 | \keyword{internal}
14 | \description{
15 | These objects are imported from other packages. Follow the links
16 | below to see their documentation.
17 |
18 | \describe{
19 | \item{bbotk}{\code{\link[bbotk]{mlr_terminators}}, \code{\link[bbotk]{trm}}, \code{\link[bbotk:trm]{trms}}}
20 |
21 | \item{mlr3misc}{\code{\link[mlr3misc]{clbk}}, \code{\link[mlr3misc:clbk]{clbks}}, \code{\link[mlr3misc]{mlr_callbacks}}}
22 | }}
23 |
24 |
--------------------------------------------------------------------------------
/inst/WORDLIST:
--------------------------------------------------------------------------------
1 | ArchiveBatchFSelect
2 | AutoFSelector
3 | BenchmarkResult
4 | Bengio
5 | Bergstra
6 | CallbackBatchFSelect
7 | CallbackBatchFSelects
8 | Codomain
9 | ContextBatchFSelect
10 | ContextBatch
11 | FSelect
12 | FSelectInstanceBatchMultiCrit
13 | FSelectInstanceBatchSingleCrit
14 | FSelector
15 | FSelectorBatchFromOptimizerBatch
16 | FSelectorBatchSequential
17 | FSelectorBatchShadowVariableSearch
18 | FSelectors
19 | Hepp
20 | Mattermost
21 | Mayr
22 | ORCID
23 | ObjectiveFSelect
24 | ParamSet
25 | Pseudovariables
26 | RFE
27 | ResampleResult
28 | StackOverflow
29 | Stefanski
30 | Uninstantiated
31 | bbotk
32 | cheatsheet
33 | cloneable
34 | cmd
35 | codomain
36 | dev
37 | fselect
38 | fselector
39 | fselectors
40 | getters
41 | iteratively
42 | mlr
43 | parallelize
44 | permutated
45 | saveRDS
46 | th
47 |
--------------------------------------------------------------------------------
/tests/testthat/test_FSelectorAsyncRandomSearch.R:
--------------------------------------------------------------------------------
1 | test_that("FSelectorAsyncRandomSearch works", {
2 | skip_on_cran()
3 | skip_if_not_installed("rush")
4 | flush_redis()
5 |
6 | fselector = fs("async_random_search")
7 | expect_class(fselector, "FSelectorAsync")
8 |
9 | on.exit(mirai::daemons(0))
10 | mirai::daemons(2)
11 | rush::rush_plan(n_workers = 2, worker_type = "remote")
12 | instance = fsi_async(
13 | task = TEST_MAKE_TSK(),
14 | learner = lrn("regr.rpart"),
15 | resampling = rsmp("holdout"),
16 | measures = msr("dummy"),
17 | terminator = trm("evals", n_evals = 5L)
18 | )
19 |
20 | expect_data_table(fselector$optimize(instance), nrows = 1)
21 | expect_data_table(instance$archive$data, min.rows = 5)
22 |
23 | expect_rush_reset(instance$rush, type = "kill")
24 | })
25 |
--------------------------------------------------------------------------------
/inst/testthat/helper_expectations.R:
--------------------------------------------------------------------------------
1 | expect_fselector = function(fselector) {
2 | expect_r6(fselector, "FSelector",
3 | public = c("optimize", "param_set", "properties", "packages"),
4 | private = c(".optimize", ".assign_result"))
5 | }
6 |
7 | expect_best_features = function(res, features) {
8 | expect_set_equal(names(res)[as.logical(res)], features)
9 | }
10 |
11 | expect_feature_number = function(features, n) {
12 | res = rowSums(features)
13 | expect_set_equal(res, n)
14 | }
15 |
16 | expect_max_features = function(features, n) {
17 | res = max(rowSums(features))
18 | expect_set_equal(res, n)
19 | }
20 |
21 | expect_features = function(res, identical_to = NULL, must_include = NULL) {
22 | expect_names(names(res)[as.logical(res)], must.include = must_include, identical.to = identical_to)
23 | }
24 |
--------------------------------------------------------------------------------
/man/mlr3fselect.backup.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/mlr_callbacks.R
3 | \name{mlr3fselect.backup}
4 | \alias{mlr3fselect.backup}
5 | \title{Backup Benchmark Result Callback}
6 | \description{
7 | This \link{CallbackBatchFSelect} writes the \link[mlr3:BenchmarkResult]{mlr3::BenchmarkResult} after each batch to disk.
8 | }
9 | \examples{
10 | clbk("mlr3fselect.backup", path = "backup.rds")
11 |
12 | # Run feature selection on the Palmer Penguins data set
13 | instance = fselect(
14 | fselector = fs("random_search"),
15 | task = tsk("pima"),
16 | learner = lrn("classif.rpart"),
17 | resampling = rsmp ("holdout"),
18 | measures = msr("classif.ce"),
19 | term_evals = 4,
20 | callbacks = clbk("mlr3fselect.backup", path = tempfile(fileext = ".rds")))
21 | }
22 |
--------------------------------------------------------------------------------
/tests/testthat/test_FSelectorAsyncExhaustiveSearch.R:
--------------------------------------------------------------------------------
1 | test_that("FSelectorAsyncExhaustiveSearch works", {
2 | skip_on_cran()
3 | skip_if_not_installed("rush")
4 | flush_redis()
5 |
6 | fselector = fs("async_exhaustive_search")
7 | expect_class(fselector, "FSelectorAsync")
8 |
9 | on.exit(mirai::daemons(0))
10 | mirai::daemons(2)
11 | rush::rush_plan(n_workers = 2, worker_type = "remote")
12 | instance = fsi_async(
13 | task = TEST_MAKE_TSK(),
14 | learner = lrn("regr.rpart"),
15 | resampling = rsmp("holdout"),
16 | measures = msr("dummy"),
17 | terminator = trm("evals", n_evals = 15)
18 | )
19 |
20 | expect_data_table(fselector$optimize(instance), nrows = 1)
21 | expect_data_table(instance$archive$data, nrows = 15)
22 |
23 | expect_rush_reset(instance$rush, type = "kill")
24 | })
25 |
--------------------------------------------------------------------------------
/man/assert_async_fselect_callback.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/CallbackAsyncFSelect.R
3 | \name{assert_async_fselect_callback}
4 | \alias{assert_async_fselect_callback}
5 | \alias{assert_async_fselect_callbacks}
6 | \title{Assertions for Callbacks}
7 | \usage{
8 | assert_async_fselect_callback(callback, null_ok = FALSE)
9 |
10 | assert_async_fselect_callbacks(callbacks)
11 | }
12 | \arguments{
13 | \item{callback}{(\link{CallbackAsyncFSelect}).}
14 |
15 | \item{null_ok}{(\code{logical(1)})\cr
16 | If \code{TRUE}, \code{NULL} is allowed.}
17 |
18 | \item{callbacks}{(list of \link{CallbackAsyncFSelect}).}
19 | }
20 | \value{
21 | [CallbackAsyncFSelect | List of \link{CallbackAsyncFSelect}s.
22 | }
23 | \description{
24 | Assertions for \link{CallbackAsyncFSelect} class.
25 | }
26 |
--------------------------------------------------------------------------------
/R/helper.R:
--------------------------------------------------------------------------------
1 | task_to_domain = function(task) {
2 | params = rep(list(p_lgl()), length(task$feature_names))
3 | names(params) = task$feature_names
4 | do.call(ps, params)
5 | }
6 |
7 | measures_to_codomain = function(measures) {
8 | measures = as_measures(measures)
9 | domains = map(measures, function(s) {
10 | if ("set_id" %in% names(ps())) {
11 | # old paradox
12 | get("ParamDbl")$new(id = s$id, tags = ifelse(s$minimize, "minimize", "maximize"))
13 | } else {
14 | p_dbl(tags = ifelse(s$minimize, "minimize", "maximize"))
15 | }
16 | })
17 | names(domains) = ids(measures)
18 | Codomain$new(domains)
19 | }
20 |
21 | extract_runtime = function(resample_result) {
22 | runtimes = map_dbl(get_private(resample_result)$.data$learner_states(get_private(resample_result)$.view), function(state) {
23 | state$train_time + state$predict_time
24 | })
25 | sum(runtimes)
26 | }
27 |
--------------------------------------------------------------------------------
/man-roxygen/example.R:
--------------------------------------------------------------------------------
1 | <% if (id == "genetic_search") { -%>
2 | #' @examplesIf mlr3misc::require_namespaces("genalg", quietly = TRUE)
3 | <% } else { -%>
4 | #' @examples
5 | <% } -%>
6 | #' # Feature Selection
7 | #' \donttest{
8 | #'
9 | #' # retrieve task and load learner
10 | #' task = tsk("penguins")
11 | #' learner = lrn("classif.rpart")
12 | #'
13 | #' # run feature selection on the Palmer Penguins data set
14 | #' instance = fselect(
15 | #' fselector = fs("<%= id %>"),
16 | #' task = task,
17 | #' learner = learner,
18 | #' resampling = rsmp("holdout"),
19 | #' measure = msr("classif.ce"),
20 | #' term_evals = 10
21 | #' )
22 | #'
23 | #' # best performing feature set
24 | #' instance$result
25 | #'
26 | #' # all evaluated feature sets
27 | #' as.data.table(instance$archive)
28 | #'
29 | #' # subset the task and fit the final model
30 | #' task$select(instance$result_feature_set)
31 | #' learner$train(task)
32 | #' }
33 |
--------------------------------------------------------------------------------
/tests/testthat/test_FSelectorAsyncDesignPoints.R:
--------------------------------------------------------------------------------
1 | test_that("FSelectorAsyncDesignPoints works", {
2 | skip_on_cran()
3 | skip_if_not_installed("rush")
4 | flush_redis()
5 |
6 | on.exit(mirai::daemons(0))
7 | mirai::daemons(2)
8 | rush::rush_plan(n_workers = 2, worker_type = "remote")
9 | instance = fsi_async(
10 | task = TEST_MAKE_TSK(),
11 | learner = lrn("regr.rpart"),
12 | resampling = rsmp("holdout"),
13 | measures = msr("dummy"),
14 | terminator = trm("evals", n_evals = 2),
15 | store_benchmark_result = FALSE
16 | )
17 |
18 | design = data.table(
19 | x1 = c(TRUE, FALSE),
20 | x2 = c(TRUE, FALSE),
21 | x3 = c(FALSE, TRUE),
22 | x4 = c(FALSE, TRUE))
23 |
24 | fselector = fs("async_design_points", design = design)
25 | expect_data_table(fselector$optimize(instance), nrows = 1)
26 |
27 | expect_data_table(instance$archive$data, nrows = 2)
28 | expect_rush_reset(instance$rush, type = "kill")
29 | })
30 |
--------------------------------------------------------------------------------
/R/FSelectorAsyncDesignPoints.R:
--------------------------------------------------------------------------------
1 | #' @title Feature Selection with Asynchronous Design Points
2 | #'
3 | #' @name mlr_fselectors_async_design_points
4 | #'
5 | #' @description
6 | #' Subclass for asynchronous design points feature selection.
7 | #'
8 | #' @templateVar id async_design_points
9 | #' @template section_dictionary_fselectors
10 | #'
11 | #' @inheritSection bbotk::OptimizerAsyncDesignPoints Parameters
12 | #'
13 | #' @family FSelectorAsync
14 | #' @export
15 | FSelectorAsyncDesignPoints = R6Class("FSelectorAsyncDesignPoints",
16 | inherit = FSelectorAsyncFromOptimizerAsync,
17 | public = list(
18 |
19 | #' @description
20 | #' Creates a new instance of this [R6][R6::R6Class] class.
21 | initialize = function() {
22 | super$initialize(
23 | optimizer = OptimizerAsyncDesignPoints$new(),
24 | man = "mlr3fselect::mlr_fselectors_async_design_points"
25 | )
26 | }
27 | )
28 | )
29 |
30 | mlr_fselectors$add("async_design_points", FSelectorAsyncDesignPoints)
31 |
--------------------------------------------------------------------------------
/pkgdown/_pkgdown.yml:
--------------------------------------------------------------------------------
1 | url: https://mlr3fselect.mlr-org.com
2 |
3 | template:
4 | bootstrap: 5
5 | light-switch: true
6 | math-rendering: mathjax
7 | package: mlr3pkgdowntemplate
8 |
9 | development:
10 | mode: auto
11 | version_label: default
12 | version_tooltip: "Version"
13 |
14 | toc:
15 | depth: 3
16 |
17 | navbar:
18 | structure:
19 | left: [reference, news, book]
20 | right: [search, github, mattermost, stackoverflow, rss, lightswitch]
21 | components:
22 | home: ~
23 | reference:
24 | icon: fa fa-file-alt
25 | text: Reference
26 | href: reference/index.html
27 | mattermost:
28 | icon: fa fa-comments
29 | href: https://lmmisld-lmu-stats-slds.srv.mwn.de/mlr_invite/
30 | book:
31 | text: mlr3book
32 | icon: fa fa-link
33 | href: https://mlr3book.mlr-org.com
34 | stackoverflow:
35 | icon: fab fa-stack-overflow
36 | href: https://stackoverflow.com/questions/tagged/mlr
37 | rss:
38 | icon: fa-rss
39 | href: https://mlr-org.com/
40 |
--------------------------------------------------------------------------------
/man/mlr3fselect_assertions.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/assertions.R
3 | \name{mlr3fselect_assertions}
4 | \alias{mlr3fselect_assertions}
5 | \alias{assert_fselectors}
6 | \alias{assert_fselector_async}
7 | \alias{assert_fselector_batch}
8 | \alias{assert_fselect_instance}
9 | \alias{assert_fselect_instance_async}
10 | \alias{assert_fselect_instance_batch}
11 | \title{Assertion for mlr3fselect objects}
12 | \usage{
13 | assert_fselectors(fselectors)
14 |
15 | assert_fselector_async(fselector)
16 |
17 | assert_fselector_batch(fselector)
18 |
19 | assert_fselect_instance(inst)
20 |
21 | assert_fselect_instance_async(inst)
22 |
23 | assert_fselect_instance_batch(inst)
24 | }
25 | \arguments{
26 | \item{fselectors}{(list of \link{FSelector}).}
27 |
28 | \item{fselector}{(\link{FSelectorBatch}).}
29 |
30 | \item{inst}{(\link{FSelectInstanceBatchSingleCrit} | \link{FSelectInstanceBatchMultiCrit}).}
31 | }
32 | \description{
33 | Most assertion functions ensure the right class attribute, and optionally additional properties.
34 | }
35 | \keyword{internal}
36 |
--------------------------------------------------------------------------------
/man/faggregate.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/faggregate.R
3 | \name{faggregate}
4 | \alias{faggregate}
5 | \title{Fast Aggregation of ResampleResults and BenchmarkResults}
6 | \usage{
7 | faggregate(obj, measure, conditions = FALSE)
8 | }
9 | \arguments{
10 | \item{obj}{(\link[mlr3:ResampleResult]{mlr3::ResampleResult} | \link[mlr3:BenchmarkResult]{mlr3::BenchmarkResult}).}
11 |
12 | \item{measure}{(\link[mlr3:Measure]{mlr3::Measure}).}
13 |
14 | \item{conditions}{(\code{logical(1)})\cr
15 | If \code{TRUE}, the function returns the number of warnings and the number of errors.}
16 | }
17 | \value{
18 | (\code{\link[data.table:data.table]{data.table::data.table()}})
19 | }
20 | \description{
21 | Aggregates a \link[mlr3:ResampleResult]{mlr3::ResampleResult} or \link[mlr3:BenchmarkResult]{mlr3::BenchmarkResult} for a single simple measure.
22 | Returns the aggregated score for each resample result.
23 | }
24 | \details{
25 | This function is faster than \verb{$aggregate()} because it does not reassemble the resampling results.
26 | It only works on simple measures which do not require the task, learner, model or train set to be available.
27 | }
28 |
--------------------------------------------------------------------------------
/tests/testthat/test_FSelectorExhaustiveSearch.R:
--------------------------------------------------------------------------------
1 | test_that("default parameters work", {
2 | z = test_fselector("exhaustive_search")
3 | a = z$inst$archive$data
4 |
5 | expect_feature_number(a[seq(4), list(x1, x2, x3, x4)], n = 1)
6 | expect_feature_number(a[6:10, list(x1, x2, x3, x4)], n = 2)
7 | expect_feature_number(a[11:14, list(x1, x2, x3, x4)], n = 3)
8 | expect_feature_number(a[15, list(x1, x2, x3, x4)], n = 4)
9 | r = z$inst$result_x_search_space
10 | expect_equal(r, data.table(x1 = TRUE, x2 = TRUE, x3 = TRUE, x4 = FALSE))
11 | })
12 |
13 | test_that("max_features parameter works", {
14 | z = test_fselector("exhaustive_search", max_features = 2)
15 | a = z$inst$archive$data
16 |
17 | expect_max_features(a[,list(x1, x2, x3, x4)], n = 2)
18 | r = z$inst$result_x_search_space
19 | expect_equal(r, data.table(x1 = TRUE, x2 = TRUE, x3 = FALSE, x4 = FALSE))
20 | })
21 |
22 | test_that("multi-crit works", {
23 | test_fselector_2D("exhaustive_search")
24 | })
25 |
26 | test_that("batch_size parameter works", {
27 | z = test_fselector("exhaustive_search", batch_size = 2)
28 | a = z$inst$archive$data
29 |
30 | expect_data_table(a[list(1), , on = "batch_nr"], nrows = 2)
31 | })
32 |
--------------------------------------------------------------------------------
/man/mlr3fselect.one_se_rule.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/mlr_callbacks.R
3 | \name{mlr3fselect.one_se_rule}
4 | \alias{mlr3fselect.one_se_rule}
5 | \title{One Standard Error Rule Callback}
6 | \source{
7 | Kuhn, Max, Johnson, Kjell (2013).
8 | \dQuote{Applied Predictive Modeling.}
9 | In chapter Over-Fitting and Model Tuning, 61--92.
10 | Springer New York, New York, NY.
11 | ISBN 978-1-4614-6849-3.
12 | }
13 | \description{
14 | Selects the smallest feature set within one standard error of the best as the result.
15 | If there are multiple such feature sets with the same number of features, the first one is selected.
16 | If the sets have exactly the same performance but different number of features,
17 | the one with the smallest number of features is selected.
18 | }
19 | \examples{
20 | clbk("mlr3fselect.one_se_rule")
21 |
22 | # Run feature selection on the pima data set with the callback
23 | instance = fselect(
24 | fselector = fs("random_search"),
25 | task = tsk("pima"),
26 | learner = lrn("classif.rpart"),
27 | resampling = rsmp ("cv", folds = 3),
28 | measures = msr("classif.ce"),
29 | term_evals = 10,
30 | callbacks = clbk("mlr3fselect.one_se_rule"))
31 | # Smallest feature set within one standard error of the best
32 | instance$result
33 | }
34 |
--------------------------------------------------------------------------------
/tests/testthat/test_ArchiveAsyncFSelectFrozen.R:
--------------------------------------------------------------------------------
1 | test_that("ArchiveAsyncTuningFrozen works", {
2 | skip_on_cran()
3 | skip_if_not_installed("rush")
4 | flush_redis()
5 |
6 | mirai::daemons(2)
7 | rush::rush_plan(n_workers = 2, worker_type = "remote")
8 |
9 | instance = fsi_async(
10 | task = tsk("pima"),
11 | learner = lrn("classif.rpart"),
12 | resampling = rsmp("cv", folds = 3),
13 | measures = msr("classif.ce"),
14 | terminator = trm("evals", n_evals = 20),
15 | store_benchmark_result = TRUE
16 | )
17 | fselector = fs("async_random_search")
18 | fselector$optimize(instance)
19 |
20 | archive = instance$archive
21 | frozen_archive = ArchiveAsyncFSelectFrozen$new(archive)
22 |
23 | expect_data_table(frozen_archive$data)
24 | expect_data_table(frozen_archive$queued_data)
25 | expect_data_table(frozen_archive$running_data)
26 | expect_data_table(frozen_archive$finished_data)
27 | expect_data_table(frozen_archive$failed_data)
28 | expect_number(frozen_archive$n_queued)
29 | expect_number(frozen_archive$n_running)
30 | expect_number(frozen_archive$n_finished)
31 | expect_number(frozen_archive$n_failed)
32 | expect_number(frozen_archive$n_evals)
33 | expect_benchmark_result(frozen_archive$benchmark_result)
34 |
35 | expect_data_table(as.data.table(frozen_archive))
36 | expect_rush_reset(instance$rush)
37 | })
38 |
--------------------------------------------------------------------------------
/.github/workflows/pkgdown.yml:
--------------------------------------------------------------------------------
1 | # pkgdown workflow of the mlr3 ecosystem v0.1.0
2 | # https://github.com/mlr-org/actions
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | branches:
9 | - main
10 | release:
11 | types:
12 | - published
13 | workflow_dispatch:
14 |
15 | name: pkgdown
16 |
17 | jobs:
18 | pkgdown:
19 | runs-on: ubuntu-latest
20 |
21 | concurrency:
22 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }}
23 | env:
24 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
25 | steps:
26 | - uses: actions/checkout@v3
27 |
28 | - uses: r-lib/actions/setup-pandoc@v2
29 |
30 | - uses: r-lib/actions/setup-r@v2
31 |
32 | - uses: r-lib/actions/setup-r-dependencies@v2
33 | with:
34 | extra-packages: any::pkgdown, local::.
35 | needs: website
36 |
37 | - name: Install template
38 | run: pak::pkg_install("mlr-org/mlr3pkgdowntemplate")
39 | shell: Rscript {0}
40 |
41 | - name: Build site
42 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE)
43 | shell: Rscript {0}
44 |
45 | - name: Deploy
46 | if: github.event_name != 'pull_request'
47 | uses: JamesIves/github-pages-deploy-action@v4.4.1
48 | with:
49 | clean: false
50 | branch: gh-pages
51 | folder: docs
52 |
--------------------------------------------------------------------------------
/R/FSelectorAsync.R:
--------------------------------------------------------------------------------
1 | #' @title Class for Asynchronous Feature Selection Algorithms
2 | #'
3 | #' @include mlr_fselectors.R
4 | #'
5 | #' @description
6 | #' The [FSelectorAsync] implements the asynchronous optimization algorithm.
7 | #'
8 | #' @details
9 | #' [FSelectorAsync] is an abstract base class that implements the base functionality each asynchronous fselector must provide.
10 | #'
11 | #' @inheritSection FSelector Resources
12 | #'
13 | #' @template param_id
14 | #' @template param_param_set
15 | #' @template param_properties
16 | #' @template param_packages
17 | #' @template param_label
18 | #' @template param_man
19 | #'
20 | #' @export
21 | FSelectorAsync = R6Class("FSelectorAsync",
22 | inherit = FSelector,
23 | public = list(
24 |
25 | #' @description
26 | #' Performs the feature selection on a [FSelectInstanceAsyncSingleCrit] or [FSelectInstanceAsyncMultiCrit] until termination.
27 | #' The single evaluations will be written into the [ArchiveAsyncFSelect] that resides in the [FSelectInstanceAsyncSingleCrit]/[FSelectInstanceAsyncMultiCrit].
28 | #' The result will be written into the instance object.
29 | #'
30 | #' @param inst ([FSelectInstanceAsyncSingleCrit] | [FSelectInstanceAsyncMultiCrit]).
31 | #'
32 | #' @return [data.table::data.table()]
33 | optimize = function(inst) {
34 | assert_fselect_instance_async(inst)
35 | optimize_async_default(inst, self)
36 | }
37 | )
38 | )
39 |
--------------------------------------------------------------------------------
/man/mlr3fselect.svm_rfe.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/mlr_callbacks.R
3 | \name{mlr3fselect.svm_rfe}
4 | \alias{mlr3fselect.svm_rfe}
5 | \title{SVM-RFE Callback}
6 | \source{
7 | Guyon I, Weston J, Barnhill S, Vapnik V (2002).
8 | \dQuote{Gene Selection for Cancer Classification using Support Vector Machines.}
9 | \emph{Machine Learning}, \bold{46}(1), 389--422.
10 | ISSN 1573-0565, \doi{10.1023/A:1012487302797}.
11 | }
12 | \description{
13 | Runs a recursive feature elimination with a \link[mlr3learners:mlr_learners_classif.svm]{mlr3learners::LearnerClassifSVM}.
14 | The SVM must be configured with \code{type = "C-classification"} and \code{kernel = "linear"}.
15 | }
16 | \examples{
17 | \dontshow{if (requireNamespace("mlr3learners", quietly = TRUE)) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf}
18 | clbk("mlr3fselect.svm_rfe")
19 |
20 | library(mlr3learners)
21 |
22 | # Create instance with classification svm with linear kernel
23 | instance = fsi(
24 | task = tsk("sonar"),
25 | learner = lrn("classif.svm", type = "C-classification", kernel = "linear"),
26 | resampling = rsmp("cv", folds = 3),
27 | measures = msr("classif.ce"),
28 | terminator = trm("none"),
29 | callbacks = clbk("mlr3fselect.svm_rfe"),
30 | store_models = TRUE
31 | )
32 |
33 | fselector = fs("rfe", feature_number = 5, n_features = 10)
34 |
35 | # Run recursive feature elimination on the Sonar data set
36 | fselector$optimize(instance)
37 | \dontshow{\}) # examplesIf}
38 | }
39 |
--------------------------------------------------------------------------------
/R/zzz.R:
--------------------------------------------------------------------------------
1 | #' @import data.table
2 | #' @import checkmate
3 | #' @import cli
4 | #' @import paradox
5 | #' @import mlr3misc
6 | #' @import mlr3
7 | #' @import bbotk
8 | #' @importFrom R6 R6Class
9 | #' @importFrom utils combn head tail packageVersion
10 | #' @importFrom stats sd
11 | "_PACKAGE"
12 |
13 | .onLoad = function(libname, pkgname) {
14 | # nocov start
15 | utils::globalVariables(c("super", "self", "n_features", "errors"))
16 |
17 | # reflections
18 | x = utils::getFromNamespace("bbotk_reflections", ns = "bbotk")
19 | x$optimizer_properties = c(x$optimizer_properties, "requires_model")
20 |
21 | x = utils::getFromNamespace("mlr_reflections", ns = "mlr3")
22 | walk(names(x$task_col_roles), function(task_type) {
23 | x$task_col_roles[[task_type]] = unique(c(x$task_col_roles[[task_type]], "always_included"))
24 | })
25 |
26 | x$loaded_packages = c(x$loaded_packages, "mlr3fselect")
27 |
28 | # callbacks
29 | x = utils::getFromNamespace("mlr_callbacks", ns = "mlr3misc")
30 | x$add("mlr3fselect.backup", load_callback_backup)
31 | x$add("mlr3fselect.svm_rfe", load_callback_svm_rfe)
32 | x$add("mlr3fselect.one_se_rule", load_callback_one_se_rule)
33 | x$add("mlr3fselect.internal_tuning", load_callback_internal_tuning)
34 | x$add("mlr3fselect.async_freeze_archive", load_callback_freeze_archive)
35 |
36 | assign("lg", lgr::get_logger("mlr3/bbotk"), envir = parent.env(environment()))
37 | if (Sys.getenv("IN_PKGDOWN") == "true") {
38 | lg$set_threshold("warn")
39 | }
40 | } # nocov end
41 |
42 | leanify_package()
43 |
--------------------------------------------------------------------------------
/man/mlr3fselect-package.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/zzz.R
3 | \docType{package}
4 | \name{mlr3fselect-package}
5 | \alias{mlr3fselect}
6 | \alias{mlr3fselect-package}
7 | \title{mlr3fselect: Feature Selection for 'mlr3'}
8 | \description{
9 | \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}}
10 |
11 | Feature selection package of the 'mlr3' ecosystem. It selects the optimal feature set for any 'mlr3' learner. The package works with several optimization algorithms e.g. Random Search, Recursive Feature Elimination, and Genetic Search. Moreover, it can automatically optimize learners and estimate the performance of optimized feature sets with nested resampling.
12 | }
13 | \seealso{
14 | Useful links:
15 | \itemize{
16 | \item \url{https://mlr3fselect.mlr-org.com}
17 | \item \url{https://github.com/mlr-org/mlr3fselect}
18 | \item Report bugs at \url{https://github.com/mlr-org/mlr3fselect/issues}
19 | }
20 |
21 | }
22 | \author{
23 | \strong{Maintainer}: Marc Becker \email{marcbecker@posteo.de} (\href{https://orcid.org/0000-0002-8115-0400}{ORCID})
24 |
25 | Authors:
26 | \itemize{
27 | \item Patrick Schratz \email{patrick.schratz@gmail.com} (\href{https://orcid.org/0000-0003-0748-6624}{ORCID})
28 | \item Michel Lang \email{michellang@gmail.com} (\href{https://orcid.org/0000-0001-9754-0393}{ORCID})
29 | \item Bernd Bischl \email{bernd_bischl@gmx.net} (\href{https://orcid.org/0000-0001-6002-6980}{ORCID})
30 | \item John Zobolas \email{bblodfon@gmail.com} (\href{https://orcid.org/0000-0002-3609-8674}{ORCID})
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/attic/test_FSelectorEvolutionary.R:
--------------------------------------------------------------------------------
1 | context("FSelectEvolutionary")
2 |
3 | test_that("FSelectEvolutionary", {
4 | z = test_fselector("evolutionary", mu = 4, lambda = 8, term_evals = 12)
5 | })
6 |
7 | test_that("FSelectEvolutionary - Initial solution", {
8 | z = test_fselector("evolutionary", mu = 4, lambda = 8,
9 | initial.solutions = list(c(1, 1, 1, 0)), term_evals = 12)
10 | r = z$inst$result_x_search_space
11 | expect_equal(r, data.table(x1 = TRUE,
12 | x2 = TRUE,
13 | x3 = TRUE,
14 | x4 = FALSE))
15 | })
16 |
17 | test_that("FSelectEvolutionary - Parent selector", {
18 | test_fselector("evolutionary", mu = 4, lambda = 8,
19 | parent.selector = "selRoulette", term_evals = 12)
20 | test_fselector("evolutionary", mu = 10, lambda = 8,
21 | parent.selector = "selGreedy", term_evals = 12)
22 | })
23 |
24 | test_that("FSelectEvolutionary - Survial selector", {
25 | test_fselector("evolutionary", mu = 4, lambda = 8,
26 | survival.selector = "selRoulette", term_evals = 12)
27 | })
28 |
29 | test_that("FSelectEvolutionary - Survial strategy", {
30 | test_fselector("evolutionary", mu = 4, lambda = 8, survival.strategy = "comma",
31 | n.elite = 1, term_evals = 12)
32 | })
33 |
34 | test_that("FSelectEvolutionary - Task with no features as inital solution", {
35 | test_fselector("evolutionary", mu = 4, lambda = 8,
36 | initial.solutions = list(c(0, 0, 0, 0)), term_evals = 10)
37 | })
38 |
39 | test_that("FSelectEvolutionary flips random bit if feature set is empty", {
40 | test_fselector("evolutionary", mu = 4, lambda = 8,
41 | initial.solutions = list(c(0, 0, 0, 0)), term_evals = 12)
42 | })
43 |
--------------------------------------------------------------------------------
/man/fs.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/sugar.R
3 | \name{fs}
4 | \alias{fs}
5 | \alias{fss}
6 | \title{Syntactic Sugar for Feature Selection Objects Construction}
7 | \usage{
8 | fs(.key, ...)
9 |
10 | fss(.keys, ...)
11 | }
12 | \arguments{
13 | \item{.key}{(\code{character(1)})\cr
14 | Key passed to the respective \link[mlr3misc:Dictionary]{dictionary} to retrieve the object.}
15 |
16 | \item{...}{(any)\cr
17 | Additional arguments.}
18 |
19 | \item{.keys}{(\code{character()})\cr
20 | Keys passed to the respective \link[mlr3misc:Dictionary]{dictionary} to retrieve multiple objects.}
21 | }
22 | \value{
23 | \link[R6:R6Class]{R6::R6Class} object of the respective type, or a list of \link[R6:R6Class]{R6::R6Class} objects for the plural versions.
24 | }
25 | \description{
26 | Functions to retrieve objects, set parameters and assign to fields in one go.
27 | Relies on \code{\link[mlr3misc:dictionary_sugar_get]{mlr3misc::dictionary_sugar_get()}} to extract objects from the respective \link[mlr3misc:Dictionary]{mlr3misc::Dictionary}:
28 | \itemize{
29 | \item \code{fs()} for a \link{FSelector} from \link{mlr_fselectors}.
30 | \item \code{fss()} for a list of \link[=FSelector]{FSelectors} from \link{mlr_fselectors}.
31 | \item \code{trm()} for a \link[bbotk:Terminator]{bbotk::Terminator} from \link{mlr_terminators}.
32 | \item \code{trms()} for a list of \link[bbotk:Terminator]{Terminators} from \link{mlr_terminators}.
33 | }
34 | }
35 | \examples{
36 | # random search fselector with batch size of 5
37 | fs("random_search", batch_size = 5)
38 |
39 | # run time terminator with 20 seconds
40 | trm("run_time", secs = 20)
41 | }
42 |
--------------------------------------------------------------------------------
/tests/testthat/test_FSelectorSequential.R:
--------------------------------------------------------------------------------
1 | test_that("default parameters works", {
2 | z = test_fselector("sequential")
3 | a = z$inst$archive$data
4 | expect_feature_number(a[batch_nr == 1, 1:4], n = 1)
5 | expect_feature_number(a[batch_nr == 2, 1:4], n = 2)
6 | expect_feature_number(a[batch_nr == 3, 1:4], n = 3)
7 | expect_feature_number(a[batch_nr == 4, 1:4], n = 4)
8 | })
9 |
10 | test_that("sbs strategy works", {
11 | z = test_fselector("sequential", strategy = "sbs")
12 | a = z$inst$archive$data
13 | expect_feature_number(a[batch_nr == 1, 1:4], n = 4)
14 | expect_feature_number(a[batch_nr == 2, 1:4], n = 3)
15 | expect_feature_number(a[batch_nr == 3, 1:4], n = 2)
16 | expect_feature_number(a[batch_nr == 4, 1:4], n = 1)
17 | })
18 |
19 | test_that("sfs strategy works with max_features parameter", {
20 | z = test_fselector("sequential", max_features = 2)
21 | a = z$inst$archive$data
22 | expect_max_features(a[, 1:4], n = 2)
23 | })
24 |
25 | test_that("sbs strategy works with max_features parameter", {
26 | z = test_fselector("sequential", max_features = 2, strategy = "sbs")
27 | a = z$inst$archive$data
28 | expect_max_features(a[, 1:4], n = 2)
29 | })
30 |
31 | test_that("optimization_path method works", {
32 | z = test_fselector("sequential")
33 | op = z$fselector$optimization_path(z$inst)
34 | expect_data_table(op, nrows = 4, ncols = 6)
35 | expect_equal(op$dummy, c(1, 2, 4, 3))
36 | })
37 |
38 | test_that("optimization_path method works with included uhash", {
39 | z = test_fselector("sequential")
40 | op = z$fselector$optimization_path(z$inst, include_uhash = TRUE)
41 | expect_data_table(op)
42 | expect_names(names(op), must.include = "uhash")
43 | expect_equal(op$dummy, c(1, 2, 4, 3))
44 | })
45 |
--------------------------------------------------------------------------------
/tests/testthat/test_fsi_async.R:
--------------------------------------------------------------------------------
1 | test_that("fsi_async function creates a FSelectInstanceAsyncSingleCrit", {
2 | skip_on_cran()
3 | skip_if_not_installed("rush")
4 | flush_redis()
5 |
6 | instance = fsi_async(
7 | task = tsk("pima"),
8 | learner = lrn("classif.rpart"),
9 | resampling = rsmp("holdout"),
10 | measures = msr("classif.ce"),
11 | terminator = trm("evals", n_evals = 2))
12 | expect_class(instance, "FSelectInstanceAsyncSingleCrit")
13 | })
14 |
15 | test_that("fsi_async function creates a FSelectInstanceAsyncMultiCrit", {
16 | skip_on_cran()
17 | skip_if_not_installed("rush")
18 | flush_redis()
19 |
20 | instance = fsi_async(
21 | task = tsk("pima"),
22 | learner = lrn("classif.rpart"),
23 | resampling = rsmp("holdout"),
24 | measures = msrs(c("classif.ce", "classif.acc")),
25 | terminator = trm("evals", n_evals = 2))
26 | expect_class(instance, "FSelectInstanceAsyncMultiCrit")
27 | })
28 |
29 | test_that("fsi_async interface is equal to FSelectInstanceAsyncSingleCrit", {
30 | skip_on_cran()
31 | skip_if_not_installed("rush")
32 | flush_redis()
33 |
34 | fsi_args = formalArgs(fsi_async)
35 | fsi_args[fsi_args == "measures"] = "measure"
36 | instance_args = formalArgs(FSelectInstanceAsyncSingleCrit$public_methods$initialize)
37 |
38 | expect_equal(fsi_args, instance_args)
39 | })
40 |
41 | test_that("fsi_async interface is equal to FSelectInstanceAsyncMultiCrit", {
42 | skip_on_cran()
43 | skip_if_not_installed("rush")
44 | flush_redis()
45 |
46 | fsi_args = formalArgs(fsi_async)
47 | fsi_args = fsi_args[fsi_args != "ties_method"]
48 | instance_args = formalArgs(FSelectInstanceAsyncMultiCrit$public_methods$initialize)
49 |
50 | expect_equal(fsi_args, instance_args)
51 | })
52 |
--------------------------------------------------------------------------------
/R/mlr_fselectors.R:
--------------------------------------------------------------------------------
1 | #' @title Dictionary of FSelectors
2 | #'
3 | #' @usage NULL
4 | #' @format [R6::R6Class] object inheriting from [mlr3misc::Dictionary].
5 | #'
6 | #' @description
7 | #' A [mlr3misc::Dictionary] storing objects of class [FSelector].
8 | #' Each fselector has an associated help page, see `mlr_fselectors_[id]`.
9 | #'
10 | #' For a more convenient way to retrieve and construct fselectors, see [fs()]/[fss()].
11 | #'
12 | #' @section Methods:
13 | #' See [mlr3misc::Dictionary].
14 | #'
15 | #' @section S3 methods:
16 | #' * `as.data.table(dict, ..., objects = FALSE)`\cr
17 | #' [mlr3misc::Dictionary] -> [data.table::data.table()]\cr
18 | #' Returns a [data.table::data.table()] with fields "key", "label", "properties" and "packages" as columns.
19 | #' If `objects` is set to `TRUE`, the constructed objects are returned in the list column named `object`.
20 | #'
21 | #' @family Dictionary
22 | #' @family FSelector
23 | #' @seealso
24 | #' Sugar functions: [fs()], [fss()]
25 | #'
26 | #' @export
27 | #' @examples
28 | #' as.data.table(mlr_fselectors)
29 | #' mlr_fselectors$get("random_search")
30 | #' fs("random_search")
31 | mlr_fselectors = R6Class("DictionaryFSelector",
32 | inherit = Dictionary,
33 | cloneable = FALSE
34 | )$new()
35 |
36 | #' @export
37 | as.data.table.DictionaryFSelector = function(x, ..., objects = FALSE) {
38 | assert_flag(objects)
39 |
40 | setkeyv(map_dtr(x$keys(), function(key) {
41 | t = withCallingHandlers(x$get(key),
42 | packageNotFoundWarning = function(w) invokeRestart("muffleWarning"))
43 | insert_named(
44 | list(key = key, label = t$label, properties = list(t$properties), packages = list(t$packages)),
45 | if (objects) list(object = list(t))
46 | )
47 | }, .fill = TRUE), "key")[]
48 | }
49 |
--------------------------------------------------------------------------------
/.github/workflows/r-cmd-check.yml:
--------------------------------------------------------------------------------
1 | # r cmd check workflow of the mlr3 ecosystem v0.4.0
2 | # https://github.com/mlr-org/actions
3 | # modified to use supercharge/redis-github-action@1.7.0
4 | on:
5 | workflow_dispatch:
6 | inputs:
7 | debug_enabled:
8 | type: boolean
9 | description: 'Run the build with tmate debugging enabled'
10 | required: false
11 | default: false
12 | push:
13 | branches:
14 | - main
15 | pull_request:
16 | branches:
17 | - main
18 |
19 | name: r-cmd-check
20 |
21 | jobs:
22 | r-cmd-check:
23 | runs-on: ${{ matrix.config.os }}
24 |
25 | name: ${{ matrix.config.os }} (${{ matrix.config.r }})
26 |
27 | env:
28 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
29 |
30 | strategy:
31 | fail-fast: false
32 | matrix:
33 | config:
34 | - {os: ubuntu-latest, r: 'devel'}
35 | - {os: ubuntu-latest, r: 'release'}
36 |
37 | steps:
38 | - uses: actions/checkout@v3
39 |
40 | - uses: r-lib/actions/setup-pandoc@v2
41 |
42 | - uses: r-lib/actions/setup-r@v2
43 | with:
44 | r-version: ${{ matrix.config.r }}
45 |
46 | - uses: supercharge/redis-github-action@1.7.0
47 | with:
48 | redis-version: 7
49 |
50 | - uses: r-lib/actions/setup-r-dependencies@v2
51 | with:
52 | extra-packages: any::rcmdcheck
53 | needs: check
54 |
55 | - uses: mxschmitt/action-tmate@v3
56 | if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
57 | with:
58 | limit-access-to-actor: true
59 |
60 | - uses: r-lib/actions/check-r-package@v2
61 | with:
62 | args: 'c("--no-manual", "--as-cran")'
63 | error-on: '"note"'
64 |
--------------------------------------------------------------------------------
/.github/workflows/no-suggest-cmd-check.yml:
--------------------------------------------------------------------------------
1 | # r cmd check workflow without suggests of the mlr3 ecosystem v0.3.1
2 | # https://github.com/mlr-org/actions
3 | # modified to use supercharge/redis-github-action@1.7.0
4 | on:
5 | workflow_dispatch:
6 | inputs:
7 | debug_enabled:
8 | type: boolean
9 | description: 'Run the build with tmate debugging enabled'
10 | required: false
11 | default: false
12 | push:
13 | branches:
14 | - main
15 | pull_request:
16 | branches:
17 | - main
18 |
19 | name: no-suggest-cmd-check
20 |
21 | jobs:
22 | no-suggest-cmd-check:
23 | runs-on: ${{ matrix.config.os }}
24 |
25 | name: ${{ matrix.config.os }} (${{ matrix.config.r }})
26 |
27 | env:
28 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
29 |
30 | strategy:
31 | fail-fast: false
32 | matrix:
33 | config:
34 | - {os: ubuntu-latest, r: 'release'}
35 |
36 | steps:
37 | - uses: actions/checkout@v5
38 |
39 | - uses: r-lib/actions/setup-pandoc@v2
40 |
41 | - uses: r-lib/actions/setup-r@v2
42 | with:
43 | r-version: ${{ matrix.config.r }}
44 |
45 | - uses: supercharge/redis-github-action@1.7.0
46 | with:
47 | redis-version: 7
48 |
49 | - uses: r-lib/actions/setup-r-dependencies@v2
50 | with:
51 | extra-packages: |
52 | any::rcmdcheck
53 | any::testthat
54 | any::knitr
55 | any::rmarkdown
56 | needs: check
57 | dependencies: '"hard"'
58 | cache: false
59 |
60 | - uses: mxschmitt/action-tmate@v3
61 | if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
62 | with:
63 | limit-access-to-actor: true
64 |
65 | - uses: r-lib/actions/check-r-package@v2
66 | with:
67 | args: 'c("--no-manual", "--as-cran")'
68 |
--------------------------------------------------------------------------------
/man/mlr_fselectors.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/mlr_fselectors.R
3 | \docType{data}
4 | \name{mlr_fselectors}
5 | \alias{mlr_fselectors}
6 | \title{Dictionary of FSelectors}
7 | \format{
8 | \link[R6:R6Class]{R6::R6Class} object inheriting from \link[mlr3misc:Dictionary]{mlr3misc::Dictionary}.
9 | }
10 | \description{
11 | A \link[mlr3misc:Dictionary]{mlr3misc::Dictionary} storing objects of class \link{FSelector}.
12 | Each fselector has an associated help page, see \code{mlr_fselectors_[id]}.
13 |
14 | For a more convenient way to retrieve and construct fselectors, see \code{\link[=fs]{fs()}}/\code{\link[=fss]{fss()}}.
15 | }
16 | \section{Methods}{
17 |
18 | See \link[mlr3misc:Dictionary]{mlr3misc::Dictionary}.
19 | }
20 |
21 | \section{S3 methods}{
22 |
23 | \itemize{
24 | \item \code{as.data.table(dict, ..., objects = FALSE)}\cr
25 | \link[mlr3misc:Dictionary]{mlr3misc::Dictionary} -> \code{\link[data.table:data.table]{data.table::data.table()}}\cr
26 | Returns a \code{\link[data.table:data.table]{data.table::data.table()}} with fields "key", "label", "properties" and "packages" as columns.
27 | If \code{objects} is set to \code{TRUE}, the constructed objects are returned in the list column named \code{object}.
28 | }
29 | }
30 |
31 | \examples{
32 | as.data.table(mlr_fselectors)
33 | mlr_fselectors$get("random_search")
34 | fs("random_search")
35 | }
36 | \seealso{
37 | Sugar functions: \code{\link[=fs]{fs()}}, \code{\link[=fss]{fss()}}
38 |
39 | Other FSelector:
40 | \code{\link{FSelector}},
41 | \code{\link{mlr_fselectors_design_points}},
42 | \code{\link{mlr_fselectors_exhaustive_search}},
43 | \code{\link{mlr_fselectors_genetic_search}},
44 | \code{\link{mlr_fselectors_random_search}},
45 | \code{\link{mlr_fselectors_rfe}},
46 | \code{\link{mlr_fselectors_rfecv}},
47 | \code{\link{mlr_fselectors_sequential}},
48 | \code{\link{mlr_fselectors_shadow_variable_search}}
49 | }
50 | \concept{Dictionary}
51 | \concept{FSelector}
52 | \keyword{datasets}
53 |
--------------------------------------------------------------------------------
/R/auto_fselector.R:
--------------------------------------------------------------------------------
1 | #' @title Function for Automatic Feature Selection
2 | #'
3 | #' @inherit AutoFSelector description
4 | #' @inheritSection AutoFSelector Resources
5 | #' @inherit AutoFSelector details
6 | #' @inheritSection AutoFSelector Nested Resampling
7 | #'
8 | #' @return [AutoFSelector].
9 | #'
10 | #' @template param_fselector
11 | #' @template param_learner
12 | #' @template param_resampling
13 | #' @template param_measure
14 | #' @template param_term_evals
15 | #' @template param_term_time
16 | #' @template param_terminator
17 | #' @template param_store_fselect_instance
18 | #' @template param_store_benchmark_result
19 | #' @template param_store_models
20 | #' @template param_check_values
21 | #' @template param_callbacks
22 | #' @template param_ties_method
23 | #' @template param_rush
24 | #' @template param_id
25 | #'
26 | #' @export
27 | #' @examples
28 | #' afs = auto_fselector(
29 | #' fselector = fs("random_search"),
30 | #' learner = lrn("classif.rpart"),
31 | #' resampling = rsmp("holdout"),
32 | #' measure = msr("classif.ce"),
33 | #' term_evals = 4)
34 | #'
35 | #' afs$train(tsk("pima"))
36 | auto_fselector = function(
37 | fselector,
38 | learner,
39 | resampling,
40 | measure = NULL,
41 | term_evals = NULL,
42 | term_time = NULL,
43 | terminator = NULL,
44 | store_fselect_instance = TRUE,
45 | store_benchmark_result = TRUE,
46 | store_models = FALSE,
47 | check_values = FALSE,
48 | callbacks = NULL,
49 | ties_method = "least_features",
50 | rush = NULL,
51 | id = NULL
52 | ) {
53 | terminator = terminator %??% terminator_selection(term_evals, term_time)
54 |
55 | AutoFSelector$new(
56 | fselector = fselector,
57 | learner = learner,
58 | resampling = resampling,
59 | measure = measure,
60 | terminator = terminator,
61 | store_fselect_instance = store_fselect_instance,
62 | store_benchmark_result = store_benchmark_result,
63 | store_models = store_models,
64 | check_values = check_values,
65 | callbacks = callbacks,
66 | ties_method = ties_method,
67 | rush = rush,
68 | id = id)
69 | }
70 |
--------------------------------------------------------------------------------
/R/assertions.R:
--------------------------------------------------------------------------------
1 | #' @title Assertion for mlr3fselect objects
2 | #'
3 | #' @description
4 | #' Most assertion functions ensure the right class attribute, and optionally additional properties.
5 | #'
6 | #' @name mlr3fselect_assertions
7 | #' @keywords internal
8 | NULL
9 |
10 | assert_fselector = function(fselector) {
11 | assert_r6(fselector, "FSelector")
12 | }
13 |
14 | #' @export
15 | #' @param fselectors (list of [FSelector]).
16 | #' @rdname mlr3fselect_assertions
17 | assert_fselectors = function(fselectors) {
18 | invisible(lapply(fselectors, assert_fselector))
19 | }
20 |
21 | #' @export
22 | #' @param fselector (`FSelectorAsync`).
23 | #' @rdname mlr3fselect_assertions
24 | assert_fselector_async = function(fselector) {
25 | assert_r6(fselector, "FSelectorAsync")
26 | }
27 |
28 | #' @export
29 | #' @param fselector ([FSelectorBatch]).
30 | #' @rdname mlr3fselect_assertions
31 | assert_fselector_batch = function(fselector) {
32 | assert_r6(fselector, "FSelectorBatch")
33 | }
34 |
35 | #' @export
36 | #' @param inst ([FSelectInstanceBatchSingleCrit] | [FSelectInstanceBatchMultiCrit] | `FSelectInstanceAsyncSingleCrit` | `FSelectInstanceAsyncMultiCrit`).
37 | #' @rdname mlr3fselect_assertions
38 | assert_fselect_instance = function(inst) {
39 | assert_multi_class(inst, c(
40 | "FSelectInstanceBatchSingleCrit",
41 | "FSelectInstanceBatchMultiCrit",
42 | "FSelectInstanceAsyncSingleCrit",
43 | "FSelectInstanceAsyncMultiCrit"))
44 | }
45 |
46 | #' @export
47 | #' @param inst (`FSelectInstanceAsyncSingleCrit` | `FSelectInstanceAsyncMultiCrit`).
48 | #' @rdname mlr3fselect_assertions
49 | assert_fselect_instance_async = function(inst) {
50 | assert_multi_class(inst, c(
51 | "FSelectInstanceAsyncSingleCrit",
52 | "FSelectInstanceAsyncMultiCrit"))
53 | }
54 |
55 | #' @export
56 | #' @param inst ([FSelectInstanceBatchSingleCrit] | [FSelectInstanceBatchMultiCrit]).
57 | #' @rdname mlr3fselect_assertions
58 | assert_fselect_instance_batch = function(inst) {
59 | assert_multi_class(inst, c(
60 | "FSelectInstanceBatchSingleCrit",
61 | "FSelectInstanceBatchMultiCrit"))
62 | }
63 |
64 |
--------------------------------------------------------------------------------
/inst/testthat/helper_fselector.R:
--------------------------------------------------------------------------------
1 | test_fselector = function(.key, ..., term_evals = NULL, store_models = FALSE) {
2 | fselector = fs(.key, ...)
3 | expect_fselector(fselector)
4 | expect_man_exists(fselector$man)
5 |
6 | inst = fselect(
7 | fselector = fselector,
8 | task = TEST_MAKE_TSK(),
9 | learner = lrn("regr.rpart"),
10 | resampling = rsmp("holdout"),
11 | measures = msr("dummy"),
12 | term_evals = term_evals,
13 | store_models = store_models
14 | )
15 |
16 | # result checks
17 | archive = inst$archive
18 | expect_data_table(inst$result, nrows = 1)
19 | expect_names(names(inst$result), must.include = c("x1", "x2", "x3", "x4", "features", "n_features", "dummy"))
20 | expect_subset(inst$result$features[[1]], c("x1", "x2", "x3", "x4"))
21 | expect_data_table(inst$result_x_search_space, nrows = 1, ncols = 4, types = "logical")
22 | expect_names(names(inst$result_x_search_space), identical.to = c("x1", "x2", "x3", "x4"))
23 | expect_names(names(inst$result_y), identical.to = "dummy")
24 |
25 | list(fselector = fselector, inst = inst)
26 | }
27 |
28 | test_fselector_2D = function(.key, ..., term_evals = NULL, store_models = FALSE) {
29 | fselector = fs(.key, ...)
30 | expect_fselector(fselector)
31 | expect_man_exists(fselector$man)
32 |
33 | inst = fselect(
34 | fselector = fselector,
35 | task = TEST_MAKE_TSK(),
36 | learner = lrn("regr.rpart"),
37 | resampling = rsmp("holdout"),
38 | measures = msrs(c("regr.rmse", "regr.mse")),
39 | term_evals = term_evals,
40 | store_models = store_models
41 | )
42 |
43 | # result checks
44 | expect_names(names(inst$result), identical.to = c("x1", "x2", "x3", "x4", "features", "n_features", "regr.rmse", "regr.mse"))
45 | expect_subset(inst$result$features[[1]], c("x1", "x2", "x3", "x4"))
46 | expect_data_table(inst$result_x_search_space, types = "logical")
47 | expect_names(names(inst$result_x_search_space), identical.to = c("x1", "x2", "x3", "x4"))
48 | expect_names(names(inst$result_y), identical.to = c("regr.rmse", "regr.mse"))
49 |
50 | list(fselector = fselector, inst = inst)
51 | }
52 |
--------------------------------------------------------------------------------
/R/FSelectorAsyncRandomSearch.R:
--------------------------------------------------------------------------------
1 | #' @title Feature Selection with Asynchronous Random Search
2 | #'
3 | #' @include mlr_fselectors.R
4 | #' @name mlr_fselectors_async_random_search
5 | #'
6 | #' @description
7 | #' Feature selection using Asynchronous Random Search Algorithm.
8 | #'
9 | #' @templateVar id async_random_search
10 | #' @template section_dictionary_fselectors
11 | #'
12 | #' @section Control Parameters:
13 | #' \describe{
14 | #' \item{`max_features`}{`integer(1)`\cr
15 | #' Maximum number of features.
16 | #' By default, number of features in [mlr3::Task].}
17 | #' }
18 | #'
19 | #' @source
20 | #' `r format_bib("bergstra_2012")`
21 | #'
22 | #' @family FSelectorAsync
23 | #' @export
24 | FSelectorAsyncRandomSearch = R6Class("FSelectorAsyncRandomSearch",
25 | inherit = FSelectorAsync,
26 | public = list(
27 |
28 | #' @description
29 | #' Creates a new instance of this [R6][R6::R6Class] class.
30 | initialize = function() {
31 | ps = ps(
32 | max_features = p_int(lower = 1L)
33 | )
34 |
35 | super$initialize(
36 | id = "async_random_search",
37 | param_set = ps,
38 | properties = c("single-crit", "multi-crit"),
39 | label = "Asynchronous Random Search",
40 | man = "mlr3fselect::mlr_fselectors_async_random_search"
41 | )
42 | }
43 | ),
44 |
45 | private = list(
46 | .optimize = function(inst) {
47 | pars = self$param_set$values
48 | feature_names = inst$archive$cols_x
49 | max_features = pars$max_features %??% length(feature_names)
50 |
51 | # usually the queue is empty but callbacks might have added points
52 | get_private(inst)$.eval_queue()
53 |
54 | while (!inst$is_terminated) {
55 | # sample new points
56 | n = sample.int(max_features, 1L)
57 | x = sample.int(length(feature_names), n)
58 | xs = as.list(set_names(replace(logical(length(feature_names)), x, TRUE), feature_names))
59 | # evaluate
60 | get_private(inst)$.eval_point(xs)
61 | }
62 | }
63 | )
64 | )
65 |
66 | mlr_fselectors$add("async_random_search", FSelectorAsyncRandomSearch)
67 |
--------------------------------------------------------------------------------
/.github/workflows/dev-cmd-check.yml:
--------------------------------------------------------------------------------
1 | # dev cmd check workflow of the mlr3 ecosystem v0.4.0
2 | # https://github.com/mlr-org/actions
3 | # modified to use supercharge/redis-github-action@1.7.0
4 | on:
5 | workflow_dispatch:
6 | inputs:
7 | debug_enabled:
8 | type: boolean
9 | description: 'Run the build with tmate debugging enabled'
10 | required: false
11 | default: false
12 | push:
13 | branches:
14 | - main
15 | pull_request:
16 | branches:
17 | - main
18 |
19 | name: dev-check
20 |
21 | jobs:
22 | check-package:
23 | runs-on: ${{ matrix.config.os }}
24 |
25 | name: ${{ matrix.config.dev-package }}
26 |
27 | env:
28 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
29 |
30 | strategy:
31 | fail-fast: false
32 | matrix:
33 | config:
34 | - {os: ubuntu-latest, r: 'release', dev-package: 'mlr-org/bbotk'}
35 | - {os: ubuntu-latest, r: 'release', dev-package: 'mlr-org/mlr3'}
36 | - {os: ubuntu-latest, r: 'release', dev-package: 'mlr-org/mlr3misc'}
37 | - {os: ubuntu-latest, r: 'release', dev-package: 'mlr-org/paradox'}
38 |
39 | steps:
40 | - uses: actions/checkout@v3
41 |
42 | - uses: r-lib/actions/setup-pandoc@v2
43 |
44 | - uses: r-lib/actions/setup-r@v2
45 | with:
46 | r-version: ${{ matrix.config.r }}
47 |
48 | - uses: supercharge/redis-github-action@1.7.0
49 | with:
50 | redis-version: 7
51 |
52 | - uses: r-lib/actions/setup-r-dependencies@v2
53 | with:
54 | extra-packages: any::rcmdcheck
55 | needs: check
56 |
57 |
58 | - name: Install dev versions
59 | run: pak::pkg_install('${{ matrix.config.dev-package }}')
60 | shell: Rscript {0}
61 |
62 | - uses: mxschmitt/action-tmate@v3
63 | if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
64 | with:
65 | limit-access-to-actor: true
66 |
67 | - uses: r-lib/actions/check-r-package@v2
68 | with:
69 | args: 'c("--no-manual", "--as-cran")'
70 | error-on: '"note"'
71 |
--------------------------------------------------------------------------------
/R/FSelectorBatchFromOptimizerBatch.R:
--------------------------------------------------------------------------------
1 | #' @title FSelectorBatchFromOptimizerBatch
2 | #'
3 | #' @description
4 | #' Internally used to transform [bbotk::Optimizer] to [FSelector].
5 | #'
6 | #' @template param_man
7 | #'
8 | #' @keywords internal
9 | #' @export
10 | FSelectorBatchFromOptimizerBatch= R6Class("FSelectorBatchFromOptimizerBatch",
11 | inherit = FSelectorBatch,
12 | public = list(
13 |
14 | #' @description
15 | #' Creates a new instance of this [R6][R6::R6Class] class.
16 | #'
17 | #' @param optimizer [bbotk::Optimizer]\cr
18 | #' Optimizer that is called.
19 | initialize = function(optimizer, man = NA_character_) {
20 | private$.optimizer = assert_optimizer(optimizer)
21 | packages = union("mlr3fselect", optimizer$packages)
22 | assert_string(man, na.ok = TRUE)
23 |
24 | super$initialize(
25 | id = if ("id" %in% names(optimizer)) optimizer$id else "optimizer",
26 | param_set = optimizer$param_set,
27 | properties = optimizer$properties,
28 | packages = packages,
29 | label = optimizer$label,
30 | man = man
31 | )
32 | },
33 |
34 | #' @description
35 | #' Performs the feature selection on a [FSelectInstanceBatchSingleCrit] /
36 | #' [FSelectInstanceBatchMultiCrit] until termination.
37 | #'
38 | #' @param inst ([FSelectInstanceBatchSingleCrit] | [FSelectInstanceBatchMultiCrit]).
39 | #'
40 | #' @return [data.table::data.table].
41 | optimize = function(inst) {
42 | # We check for both classes since there is no FSelectInstance super
43 | # class anymore and OptimInstance would not ensure that we are in the
44 | # scope of mlr3fselect
45 | assert_fselect_instance_batch(inst)
46 | result = private$.optimizer$optimize(inst)
47 | inst$objective$.__enclos_env__$private$.xss = NULL
48 | inst$objective$.__enclos_env__$private$.design = NULL
49 | inst$objective$.__enclos_env__$private$.benchmark_result = NULL
50 | inst$objective$.__enclos_env__$private$.aggregated_performance = NULL
51 | return(result)
52 | }
53 | ),
54 |
55 | private = list(
56 | .optimizer = NULL
57 | )
58 | )
59 |
--------------------------------------------------------------------------------
/R/FSelectorBatchGeneticSearch.R:
--------------------------------------------------------------------------------
1 | #' @title Feature Selection with Genetic Search
2 | #'
3 | #' @include mlr_fselectors.R
4 | #' @name mlr_fselectors_genetic_search
5 | #'
6 | #' @description
7 | #' Feature selection using the Genetic Algorithm from the package \CRANpkg{genalg}.
8 | #'
9 | #' @templateVar id genetic_search
10 | #' @template section_dictionary_fselectors
11 | #'
12 | #' @section Control Parameters:
13 | #' For the meaning of the control parameters, see [genalg::rbga.bin()].
14 | #' [genalg::rbga.bin()] internally terminates after `iters` iteration.
15 | #' We set `ìters = 100000` to allow the termination via our terminators.
16 | #' If more iterations are needed, set `ìters` to a higher value in the parameter set.
17 | #'
18 | #' @family FSelector
19 | #' @export
20 | #' @template example
21 | FSelectorBatchGeneticSearch = R6Class("FSelectorBatchGeneticSearch",
22 | inherit = FSelectorBatch,
23 | public = list(
24 |
25 | #' @description
26 | #' Creates a new instance of this [R6][R6::R6Class] class.
27 | initialize = function() {
28 | ps = ps(
29 | suggestion = p_uty(),
30 | popSize = p_int(lower = 5L, default = 200L),
31 | mutationChance = p_dbl(lower = 0, upper = 1),
32 | elitism = p_int(lower = 1L),
33 | zeroToOneRatio = p_int(lower = 1, default = 10L),
34 | iters = p_int(lower = 1, default = 100000L)
35 | )
36 | ps$values$iters = 100000L
37 |
38 | super$initialize(
39 | id = "genetic_search",
40 | param_set = ps,
41 | properties = "single-crit",
42 | packages = "genalg",
43 | label = "Genetic Search",
44 | man = "mlr3fselect::mlr_fselectors_genetic_search"
45 | )
46 | }
47 | ),
48 | private = list(
49 | .optimize = function(inst) {
50 | pars = self$param_set$values
51 | if (is.null(pars$mutationChance)) pars$mutationChance = NA
52 | if (is.null(pars$elitism)) pars$elitism = NA
53 | n = inst$objective$domain$length
54 |
55 | mlr3misc::invoke(genalg::rbga.bin, size = n, evalFunc = inst$objective_function, .args = pars)
56 | }
57 | )
58 | )
59 |
60 | mlr_fselectors$add("genetic_search", FSelectorBatchGeneticSearch)
61 |
--------------------------------------------------------------------------------
/R/FSelectorAsyncFromOptimizerAsync.R:
--------------------------------------------------------------------------------
1 | #' @title FSelectorAsyncFromOptimizerAsync
2 | #'
3 | #' @description
4 | #' Internally used to transform [bbotk::Optimizer] to [FSelector].
5 | #'
6 | #' @template param_man
7 | #'
8 | #' @keywords internal
9 | #' @export
10 | FSelectorAsyncFromOptimizerAsync = R6Class("FSelectorAsyncFromOptimizerAsync",
11 | inherit = FSelectorAsync,
12 | public = list(
13 |
14 | #' @description
15 | #' Creates a new instance of this [R6][R6::R6Class] class.
16 | #'
17 | #' @param optimizer [bbotk::Optimizer]\cr
18 | #' Optimizer that is called.
19 | initialize = function(optimizer, man = NA_character_) {
20 | private$.optimizer = assert_optimizer_async(optimizer)
21 | packages = union("mlr3fselect", optimizer$packages)
22 | assert_string(man, na.ok = TRUE)
23 |
24 | super$initialize(
25 | id = if ("id" %in% names(optimizer)) optimizer$id else "fselector",
26 | param_set = optimizer$param_set,
27 | properties = optimizer$properties,
28 | packages = packages,
29 | label = optimizer$label,
30 | man = man
31 | )
32 | },
33 |
34 | #' @description
35 | #' Performs the feature selection on a [FSelectInstanceAsyncSingleCrit] /
36 | #' [FSelectInstanceAsyncMultiCrit] until termination. The single evaluations and
37 | #' the final results will be written into the [ArchiveAsyncFSelect] that
38 | #' resides in the [FSelectInstanceAsyncSingleCrit]/[FSelectInstanceAsyncMultiCrit].
39 | #' The final result is returned.
40 | #'
41 | #' @param inst ([FSelectInstanceAsyncSingleCrit] | [FSelectInstanceAsyncMultiCrit]).
42 | #'
43 | #' @return [data.table::data.table].
44 | optimize = function(inst) {
45 | assert_fselect_instance_async(inst)
46 | private$.optimizer$optimize(inst)
47 | }
48 | ),
49 |
50 | active = list(
51 |
52 | #' @field param_set ([paradox::ParamSet])\cr
53 | #' Set of control parameters.
54 | param_set = function(rhs) {
55 | if (!missing(rhs) && !identical(rhs, private$.optimizer$param_set)) {
56 | stop("$param_set is read-only.")
57 | }
58 | private$.optimizer$param_set
59 | }
60 | ),
61 |
62 | private = list(
63 | .optimizer = NULL
64 | )
65 | )
66 |
67 |
68 |
--------------------------------------------------------------------------------
/R/FSelectorBatchExhaustiveSearch.R:
--------------------------------------------------------------------------------
1 | #' @title Feature Selection with Exhaustive Search
2 | #'
3 | #' @include mlr_fselectors.R
4 | #' @name mlr_fselectors_exhaustive_search
5 | #'
6 | #' @description
7 | #' Feature Selection using the Exhaustive Search Algorithm.
8 | #' Exhaustive Search generates all possible feature sets.
9 | #'
10 | #' @details
11 | #' The feature selection terminates itself when all feature sets are evaluated.
12 | #' It is not necessary to set a termination criterion.
13 | #'
14 | #' @templateVar id exhaustive_search
15 | #' @template section_dictionary_fselectors
16 | #'
17 | #' @section Control Parameters:
18 | #' \describe{
19 | #' \item{`max_features`}{`integer(1)`\cr
20 | #' Maximum number of features.
21 | #' By default, number of features in [mlr3::Task].}
22 | #' }
23 | #'
24 | #' @family FSelector
25 | #' @export
26 | #' @template example
27 | FSelectorBatchExhaustiveSearch = R6Class("FSelectorBatchExhaustiveSearch",
28 | inherit = FSelectorBatch,
29 | public = list(
30 |
31 | #' @description
32 | #' Creates a new instance of this [R6][R6::R6Class] class.
33 | initialize = function() {
34 | ps = ps(
35 | max_features = p_int(lower = 1L),
36 | batch_size = p_int(lower = 1L, tags = "required")
37 | )
38 | ps$values = list(batch_size = 10L)
39 |
40 | super$initialize(
41 | id = "exhaustive_search",
42 | param_set = ps,
43 | properties = c("single-crit", "multi-crit"),
44 | label = "Exhaustive Search",
45 | man = "mlr3fselect::mlr_fselectors_exhaustive_search")
46 | }
47 | ),
48 | private = list(
49 | .optimize = function(inst) {
50 | pars = self$param_set$values
51 | feature_names = inst$archive$cols_x
52 | n_features = length(feature_names)
53 |
54 | fun = function(i, state) {
55 | state[i] = TRUE
56 | as.list(state)
57 | }
58 |
59 | states = set_col_names(rbindlist(unlist(map(seq(pars$max_features %??% n_features), function(n) {
60 | combn(n_features, n, fun, simplify = FALSE, state = logical(n_features))
61 | }), recursive = FALSE)), feature_names)
62 |
63 | chunks = split(seq_row(states), ceiling(seq_along(seq_row(states)) / pars$batch_size))
64 | walk(chunks, function(row_ids) inst$eval_batch(states[row_ids]))
65 | }
66 | )
67 | )
68 |
69 | mlr_fselectors$add("exhaustive_search", FSelectorBatchExhaustiveSearch)
70 |
--------------------------------------------------------------------------------
/R/FSelectorBatchDesignPoints.R:
--------------------------------------------------------------------------------
1 | #' @title Feature Selection with Design Points
2 | #'
3 | #' @include mlr_fselectors.R
4 | #' @name mlr_fselectors_design_points
5 | #'
6 | #' @description
7 | #' Feature selection using user-defined feature sets.
8 | #'
9 | #' @details
10 | #' The feature sets are evaluated in order as given.
11 | #'
12 | #' The feature selection terminates itself when all feature sets are evaluated.
13 | #' It is not necessary to set a termination criterion.
14 | #'
15 | #' @templateVar id design_points
16 | #' @template section_dictionary_fselectors
17 | #'
18 | #' @inheritSection bbotk::OptimizerBatchDesignPoints Parameters
19 | #'
20 | #' @family FSelector
21 | #' @export
22 | #' @examples
23 | #' # Feature Selection
24 | #' \donttest{
25 | #'
26 | #' # retrieve task and load learner
27 | #' task = tsk("pima")
28 | #' learner = lrn("classif.rpart")
29 | #'
30 | #' # create design
31 | #' design = mlr3misc::rowwise_table(
32 | #' ~age, ~glucose, ~insulin, ~mass, ~pedigree, ~pregnant, ~pressure, ~triceps,
33 | #' TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE,
34 | #' TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE,
35 | #' TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE,
36 | #' TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE
37 | #' )
38 | #'
39 | #' # run feature selection on the Pima Indians diabetes data set
40 | #' instance = fselect(
41 | #' fselector = fs("design_points", design = design),
42 | #' task = task,
43 | #' learner = learner,
44 | #' resampling = rsmp("holdout"),
45 | #' measure = msr("classif.ce")
46 | #' )
47 | #'
48 | #' # best performing feature set
49 | #' instance$result
50 | #'
51 | #' # all evaluated feature sets
52 | #' as.data.table(instance$archive)
53 | #'
54 | #' # subset the task and fit the final model
55 | #' task$select(instance$result_feature_set)
56 | #' learner$train(task)
57 | #' }
58 | FSelectorBatchDesignPoints = R6Class("FSelectorBatchDesignPoints",
59 | inherit = FSelectorBatchFromOptimizerBatch,
60 | public = list(
61 |
62 | #' @description
63 | #' Creates a new instance of this [R6][R6::R6Class] class.
64 | initialize = function() {
65 | super$initialize(
66 | optimizer = OptimizerBatchDesignPoints$new(),
67 | man = "mlr3fselect::mlr_fselectors_design_points"
68 | )
69 | }
70 | )
71 | )
72 |
73 | mlr_fselectors$add("design_points", FSelectorBatchDesignPoints)
74 |
--------------------------------------------------------------------------------
/man/extract_inner_fselect_results.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/extract_inner_fselect_results.R
3 | \name{extract_inner_fselect_results}
4 | \alias{extract_inner_fselect_results}
5 | \title{Extract Inner Feature Selection Results}
6 | \usage{
7 | extract_inner_fselect_results(x, fselect_instance, ...)
8 | }
9 | \arguments{
10 | \item{x}{(\link[mlr3:ResampleResult]{mlr3::ResampleResult} | \link[mlr3:BenchmarkResult]{mlr3::BenchmarkResult}).}
11 |
12 | \item{fselect_instance}{(\code{logical(1)})\cr
13 | If \code{TRUE}, instances are added to the table.}
14 |
15 | \item{...}{(any)\cr
16 | Additional arguments.}
17 | }
18 | \value{
19 | \code{\link[data.table:data.table]{data.table::data.table()}}.
20 | }
21 | \description{
22 | Extract inner feature selection results of nested resampling.
23 | Implemented for \link[mlr3:ResampleResult]{mlr3::ResampleResult} and \link[mlr3:BenchmarkResult]{mlr3::BenchmarkResult}.
24 | }
25 | \details{
26 | The function iterates over the \link{AutoFSelector} objects and binds the feature selection results to a \code{\link[data.table:data.table]{data.table::data.table()}}.
27 | \link{AutoFSelector} must be initialized with \code{store_fselect_instance = TRUE} and \code{resample()} or \code{benchmark()} must be called with \code{store_models = TRUE}.
28 | Optionally, the instance can be added for each iteration.
29 | }
30 | \section{Data structure}{
31 |
32 |
33 | The returned data table has the following columns:
34 | \itemize{
35 | \item \code{experiment} (integer(1))\cr
36 | Index, giving the according row number in the original benchmark grid.
37 | \item \code{iteration} (integer(1))\cr
38 | Iteration of the outer resampling.
39 | \item One column for each feature of the task.
40 | \item One column for each performance measure.
41 | \item \code{features} (character())\cr
42 | Vector of selected feature set.
43 | \item \code{task_id} (\code{character(1)}).
44 | \item \code{learner_id} (\code{character(1)}).
45 | \item \code{resampling_id} (\code{character(1)}).
46 | }
47 | }
48 |
49 | \examples{
50 | # Nested Resampling on Palmer Penguins Data Set
51 |
52 | # create auto fselector
53 | at = auto_fselector(
54 | fselector = fs("random_search"),
55 | learner = lrn("classif.rpart"),
56 | resampling = rsmp ("holdout"),
57 | measure = msr("classif.ce"),
58 | term_evals = 4)
59 |
60 | resampling_outer = rsmp("cv", folds = 2)
61 | rr = resample(tsk("iris"), at, resampling_outer, store_models = TRUE)
62 |
63 | # extract inner results
64 | extract_inner_fselect_results(rr)
65 | }
66 |
--------------------------------------------------------------------------------
/tests/testthat/test_FSelectInstanceMultiCrit.R:
--------------------------------------------------------------------------------
1 | test_that("empty FSelectInstanceBatchMultiCrit works", {
2 | inst = TEST_MAKE_INST_2D()
3 |
4 | expect_data_table(inst$archive$data, nrows = 0L)
5 | expect_identical(inst$archive$n_evals, 0L)
6 | expect_identical(inst$archive$n_batch, 0L)
7 | expect_null(inst$result)
8 | })
9 |
10 | test_that("eval_batch works", {
11 | inst = TEST_MAKE_INST_2D()
12 |
13 | xdt = data.table(x1 = list(TRUE, FALSE), x2 = list(FALSE, TRUE),
14 | x3 = list(TRUE, TRUE), x4 = list(TRUE, TRUE))
15 |
16 | z = inst$eval_batch(xdt)
17 | expect_named(z, c("regr.mse", "regr.rmse"))
18 | expect_identical(inst$archive$n_evals, 2L)
19 | expect_data_table(z, nrows = 2L)
20 |
21 | z = inst$eval_batch(xdt)
22 | expect_named(z, c("regr.mse", "regr.rmse"))
23 | expect_identical(inst$archive$n_evals, 4L)
24 | expect_data_table(z, nrows = 2L)
25 | })
26 |
27 | test_that("objective_function works", {
28 | inst = TEST_MAKE_INST_2D()
29 | y = inst$objective_function(c(1, 1, 0, 0))
30 | expect_named(y, c("regr.mse", "regr.rmse"))
31 | })
32 |
33 | test_that("store_benchmark_result flag works", {
34 | inst = TEST_MAKE_INST_2D(store_benchmark_result = FALSE)
35 | xdt = data.table(x1 = list(TRUE, FALSE), x2 = list(FALSE, TRUE),
36 | x3 = list(TRUE, TRUE), x4 = list(TRUE, TRUE))
37 | inst$eval_batch(xdt)
38 |
39 | expect_true("uhashes" %nin% colnames(inst$archive$data))
40 |
41 | inst = TEST_MAKE_INST_2D(store_benchmark_result = TRUE)
42 | xdt = data.table(x1 = list(TRUE, FALSE), x2 = list(FALSE, TRUE),
43 | x3 = list(TRUE, TRUE), x4 = list(TRUE, TRUE))
44 | inst$eval_batch(xdt)
45 | expect_r6(inst$archive$benchmark_result, "BenchmarkResult")
46 | })
47 |
48 | test_that("result$features works", {
49 | inst = TEST_MAKE_INST_2D(store_benchmark_result = FALSE)
50 | xdt = data.table(x1 = list(TRUE, FALSE), x2 = list(FALSE, TRUE),
51 | x3 = list(TRUE, TRUE), x4 = list(TRUE, TRUE))
52 | ydt = data.table(regr.mse = list(0.1, 0.2),
53 | regr.rmse = list(0.2, 0.1))
54 | inst$assign_result(xdt, ydt)
55 | expect_list(inst$result_feature_set)
56 | expect_character(inst$result_feature_set[[1]])
57 |
58 | inst = TEST_MAKE_INST_2D(store_benchmark_result = FALSE)
59 | xdt = data.table(x1 = list(TRUE), x2 = list(FALSE),
60 | x3 = list(TRUE), x4 = list(TRUE))
61 | ydt = data.table(regr.mse = list(0.1),
62 | regr.rmse = list(0.2))
63 | inst$assign_result(xdt, ydt)
64 | expect_list(inst$result_feature_set)
65 | expect_character(inst$result_feature_set[[1]])
66 | })
67 |
--------------------------------------------------------------------------------
/R/fselect_nested.R:
--------------------------------------------------------------------------------
1 | #' @title Function for Nested Resampling
2 | #'
3 | #' @description
4 | #' Function to conduct nested resampling.
5 | #'
6 | #' @param inner_resampling ([mlr3::Resampling])\cr
7 | #' Resampling used for the inner loop.
8 | #' @param outer_resampling [mlr3::Resampling])\cr
9 | #' Resampling used for the outer loop.
10 | #'
11 | #' @return [mlr3::ResampleResult]
12 | #'
13 | #' @template param_fselector
14 | #' @template param_task
15 | #' @template param_learner
16 | #' @template param_measure
17 | #' @template param_term_evals
18 | #' @template param_term_time
19 | #' @template param_terminator
20 | #' @template param_store_fselect_instance
21 | #' @template param_store_benchmark_result
22 | #' @template param_store_models
23 | #' @template param_check_values
24 | #' @template param_callbacks
25 | #' @template param_ties_method
26 | #'
27 | #' @export
28 | #' @examples
29 | #' # Nested resampling on Palmer Penguins data set
30 | #' rr = fselect_nested(
31 | #' fselector = fs("random_search"),
32 | #' task = tsk("penguins"),
33 | #' learner = lrn("classif.rpart"),
34 | #' inner_resampling = rsmp ("holdout"),
35 | #' outer_resampling = rsmp("cv", folds = 2),
36 | #' measure = msr("classif.ce"),
37 | #' term_evals = 4)
38 | #'
39 | #' # Performance scores estimated on the outer resampling
40 | #' rr$score()
41 | #'
42 | #' # Unbiased performance of the final model trained on the full data set
43 | #' rr$aggregate()
44 | fselect_nested = function(
45 | fselector,
46 | task,
47 | learner,
48 | inner_resampling,
49 | outer_resampling,
50 | measure = NULL,
51 | term_evals = NULL,
52 | term_time = NULL,
53 | terminator = NULL,
54 | store_fselect_instance = TRUE,
55 | store_benchmark_result = TRUE,
56 | store_models = FALSE,
57 | check_values = FALSE,
58 | callbacks = NULL,
59 | ties_method = "least_features"
60 | ) {
61 | assert_task(task)
62 | assert_resampling(inner_resampling)
63 | assert_resampling(outer_resampling)
64 | terminator = terminator %??% terminator_selection(term_evals, term_time)
65 |
66 | afs = auto_fselector(
67 | learner = learner,
68 | resampling = inner_resampling,
69 | measure = measure,
70 | terminator = terminator,
71 | fselector = fselector,
72 | store_fselect_instance = store_fselect_instance,
73 | store_benchmark_result = store_benchmark_result,
74 | store_models = store_models,
75 | check_values = check_values,
76 | callbacks = callbacks,
77 | ties_method = ties_method)
78 |
79 | resample(task, afs, outer_resampling, store_models = TRUE)
80 | }
81 |
--------------------------------------------------------------------------------
/inst/testthat/helper_misc.R:
--------------------------------------------------------------------------------
1 | TEST_MAKE_TSK = function(n = 4L) {
2 | x = set_names(map_dtc(seq(n), function(x) rnorm(100L)), paste0("x", seq(n)))
3 | y = rnorm(100)
4 | TaskRegr$new(id = "mlr3fselect", backend = cbind(x, y), target = "y")
5 | }
6 |
7 | TEST_MAKE_INST_1D = function(n = 4L, folds = 2L, store_models = TRUE, store_benchmark_result = TRUE,
8 | measure = msr("dummy"), terminator = trm("evals", n_evals = 10)) {
9 | FSelectInstanceBatchSingleCrit$new(
10 | task = TEST_MAKE_TSK(n),
11 | learner = lrn("regr.rpart"),
12 | resampling = rsmp("cv", folds = folds),
13 | measure = measure,
14 | terminator = terminator,
15 | store_models = store_models,
16 | store_benchmark_result = store_benchmark_result)
17 | }
18 |
19 | TEST_MAKE_INST_2D = function(n = 4L, folds = 2L, store_models = FALSE, store_benchmark_result = TRUE) {
20 | FSelectInstanceBatchMultiCrit$new(
21 | task = TEST_MAKE_TSK(n),
22 | learner = lrn("regr.rpart"),
23 | resampling = rsmp("cv", folds = folds),
24 | measures = msrs(c("regr.mse", "regr.rmse")),
25 | terminator = trm("evals", n_evals = 10),
26 | store_models,
27 | store_benchmark_result = store_benchmark_result)
28 | }
29 |
30 | MeasureDummy = R6Class("MeasureDummy", inherit = MeasureRegr,
31 | public = list(
32 | initialize = function(score_design = NULL, minimize = FALSE) {
33 | if (is.null(score_design)) {
34 | score_design = data.table(
35 | score = c(1, 2, 4, 3),
36 | features = list("x1", c("x1", "x2"), c("x1", "x2", "x3"), c("x1", "x2", "x3", "x4"))
37 | )
38 | }
39 | private$.score_design = score_design
40 | super$initialize(id = "dummy", range = c(0, 4), minimize = minimize, properties = c("requires_task", "requires_learner"))
41 | }
42 | ),
43 | private = list(
44 | .score = function(prediction, learner, task, ...) {
45 | score = private$.score_design[sapply(get("features"), identical, task$feature_names), score]
46 | if (length(score) == 0) 0 else score
47 | },
48 |
49 | .score_design = NULL
50 | )
51 | )
52 | mlr3::mlr_measures$add("dummy", MeasureDummy)
53 |
54 | flush_redis = function() {
55 | config = redux::redis_config()
56 | r = redux::hiredis(config)
57 | r$FLUSHDB()
58 | }
59 |
60 | expect_rush_reset = function(rush, type = "kill") {
61 | rush$reset(type = type)
62 | # Sys.sleep(1)
63 | # keys = rush$connector$command(c("KEYS", "*"))
64 | # if (!test_list(keys, len = 0)) {
65 | # stopf("Found keys in redis after reset: %s", keys)
66 | # }
67 | mirai::daemons(0)
68 | }
69 |
--------------------------------------------------------------------------------
/R/ContextAsyncFSelect.R:
--------------------------------------------------------------------------------
1 | #' @title Asynchronous Feature Selection Context
2 | #'
3 | #' @description
4 | #' A [CallbackAsyncFSelect] accesses and modifies data during the optimization via the `ContextAsyncFSelect`.
5 | #' See the section on active bindings for a list of modifiable objects.
6 | #' See [callback_async_fselect()] for a list of stages that access `ContextAsyncFSelect`.
7 | #'
8 | #' @details
9 | #' Changes to `$instance` and `$optimizer` in the stages executed on the workers are not reflected in the main process.
10 | #'
11 | #' @template param_inst_async
12 | #' @template param_fselector
13 | #'
14 | #' @export
15 | ContextAsyncFSelect = R6Class("ContextAsyncFSelect",
16 | inherit = ContextAsync,
17 | public = list(
18 |
19 | #' @field auto_fselector ([AutoFSelector])\cr
20 | #' The [AutoFSelector] instance.
21 | auto_fselector = NULL
22 | ),
23 |
24 | active = list(
25 |
26 | #' @field xs_objective (`list()`)\cr
27 | #' The feature subset currently evaluated.
28 | xs_objective = function(rhs) {
29 | if (missing(rhs)) {
30 | return(get_private(self$instance$objective)$.xs)
31 | } else {
32 | self$instance$objective$.__enclos_env__$private$.xs = rhs
33 | }
34 | },
35 |
36 | #' @field resample_result ([mlr3::BenchmarkResult])\cr
37 | #' The resample result of the feature subset currently evaluated.
38 | resample_result = function(rhs) {
39 | if (missing(rhs)) {
40 | return(get_private(self$instance$objective)$.resample_result)
41 | } else {
42 | self$instance$objective$.__enclos_env__$private$.resample_result = rhs
43 | }
44 | },
45 |
46 | #' @field aggregated_performance (`list()`)\cr
47 | #' Aggregated performance scores and training time of the evaluated feature subset.
48 | #' This list is passed to the archive.
49 | #' A callback can add additional elements which are also written to the archive.
50 | aggregated_performance = function(rhs) {
51 | if (missing(rhs)) {
52 | return(get_private(self$instance$objective)$.aggregated_performance)
53 | } else {
54 | self$instance$objective$.__enclos_env__$private$.aggregated_performance = rhs
55 | }
56 | },
57 |
58 | #' @field result_feature_set (character())\cr
59 | #' The feature set passed to `instance$assign_result()`.
60 | result_feature_set = function(rhs) {
61 | if (missing(rhs)) {
62 | return(get_private(self$instance)$.result_feature_set)
63 | } else {
64 | self$instance$.__enclos_env__$private$.result_feature_set = rhs
65 | }
66 | }
67 | )
68 | )
69 |
--------------------------------------------------------------------------------
/R/ContextBatchFSelect.R:
--------------------------------------------------------------------------------
1 | #' @title Evaluation Context
2 | #'
3 | #' @description
4 | #' The [ContextBatchFSelect] allows [CallbackBatchFSelect]s to access and modify data while a batch of feature sets is evaluated.
5 | #' See the section on active bindings for a list of modifiable objects.
6 | #' See [callback_batch_fselect()] for a list of stages that access [ContextBatchFSelect].
7 | #'
8 | #' @details
9 | #' This context is re-created each time a new batch of feature sets is evaluated.
10 | #' Changes to `$objective_fselect`, `$design` `$benchmark_result` are discarded after the function is finished.
11 | #' Modification on the data table in `$aggregated_performance` are written to the archive.
12 | #' Any number of columns can be added.
13 | #'
14 | #' @export
15 | ContextBatchFSelect = R6Class("ContextBatchFSelect",
16 | inherit = ContextBatch,
17 | public = list(
18 |
19 | #' @field auto_fselector ([AutoFSelector])\cr
20 | #' The [AutoFSelector] instance.
21 | auto_fselector = NULL
22 | ),
23 |
24 | active = list(
25 | #' @field xss (list())\cr
26 | #' The feature sets of the latest batch.
27 | xss = function(rhs) {
28 | if (missing(rhs)) {
29 | return(get_private(self$instance$objective)$.xss)
30 | } else {
31 | get_private(self$instance$objective)$.xss = rhs
32 | }
33 | },
34 |
35 | #' @field design ([data.table::data.table])\cr
36 | #' The benchmark design of the latest batch.
37 | design = function(rhs) {
38 | if (missing(rhs)) {
39 | return(get_private(self$instance$objective)$.design)
40 | } else {
41 | get_private(self$instance$objective)$.design = rhs
42 | }
43 | },
44 |
45 | #' @field benchmark_result ([mlr3::BenchmarkResult])\cr
46 | #' The benchmark result of the latest batch.
47 | benchmark_result = function(rhs) {
48 | if (missing(rhs)) {
49 | return(get_private(self$instance$objective)$.benchmark_result)
50 | } else {
51 | get_private(self$instance$objective)$.benchmark_result = rhs
52 | }
53 | },
54 |
55 | #' @field aggregated_performance ([data.table::data.table])\cr
56 | #' Aggregated performance scores and training time of the latest batch.
57 | #' This data table is passed to the archive.
58 | #' A callback can add additional columns which are also written to the archive.
59 | aggregated_performance = function(rhs) {
60 | if (missing(rhs)) {
61 | return(get_private(self$instance$objective)$.aggregated_performance)
62 | } else {
63 | get_private(self$instance$objective)$.aggregated_performance = rhs
64 | }
65 | }
66 | )
67 | )
68 |
--------------------------------------------------------------------------------
/R/FSelectorAsyncExhaustiveSearch.R:
--------------------------------------------------------------------------------
1 | #' @title Feature Selection with Asynchronous Exhaustive Search
2 | #'
3 | #' @include FSelectorAsync.R
4 | #' @name mlr_fselectors_async_exhaustive_search
5 | #'
6 | #' @description
7 | #' Feature Selection using the Asynchronous Exhaustive Search Algorithm.
8 | #' Exhaustive Search generates all possible feature sets.
9 | #' The feature sets are evaluated asynchronously.
10 | #'
11 | #' @details
12 | #' The feature selection terminates itself when all feature sets are evaluated.
13 | #' It is not necessary to set a termination criterion.
14 | #'
15 | #' @templateVar id async_exhaustive_search
16 | #' @template section_dictionary_fselectors
17 | #'
18 | #' @section Control Parameters:
19 | #' \describe{
20 | #' \item{`max_features`}{`integer(1)`\cr
21 | #' Maximum number of features.
22 | #' By default, number of features in [mlr3::Task].}
23 | #' }
24 | #'
25 | #' @family FSelectorAsync
26 | #' @export
27 | FSelectorAsyncExhaustiveSearch = R6Class("FSelectorAsyncExhaustiveSearch",
28 | inherit = FSelectorAsync,
29 | public = list(
30 |
31 | #' @description
32 | #' Creates a new instance of this [R6][R6::R6Class] class.
33 | initialize = function() {
34 | ps = ps(
35 | max_features = p_int(lower = 1L)
36 | )
37 |
38 | super$initialize(
39 | id = "async_exhaustive_search",
40 | param_set = ps,
41 | properties = c("single-crit", "multi-crit", "async"),
42 | packages = "rush",
43 | label = "Asynchronous Exhaustive Search",
44 | man = "mlr3fselect::mlr_fselectors_async_exhaustive_search")
45 | },
46 |
47 | #' @description
48 | #' Starts the asynchronous optimization.
49 | #'
50 | #' @param inst ([FSelectInstanceAsyncSingleCrit] | [FSelectInstanceAsyncMultiCrit]).
51 | #' @return [data.table::data.table].
52 | optimize = function(inst) {
53 | pars = self$param_set$values
54 | feature_names = inst$archive$cols_x
55 | n_features = length(feature_names)
56 |
57 | fun = function(i, state) {
58 | state[i] = TRUE
59 | as.list(state)
60 | }
61 |
62 | states = set_col_names(rbindlist(unlist(map(seq(pars$max_features %??% n_features), function(n) {
63 | combn(n_features, n, fun, simplify = FALSE, state = logical(n_features))
64 | }), recursive = FALSE)), feature_names)
65 |
66 | optimize_async_default(inst, self, states)
67 | }
68 | ),
69 |
70 | private = list(
71 | .optimize = function(inst) {
72 | # evaluate feature sets
73 | get_private(inst)$.eval_queue()
74 | }
75 | )
76 | )
77 |
78 | mlr_fselectors$add("async_exhaustive_search", FSelectorAsyncExhaustiveSearch)
79 |
--------------------------------------------------------------------------------
/tests/testthat/test_auto_fselector.R:
--------------------------------------------------------------------------------
1 | test_that("auto_fselector function works", {
2 | afs = auto_fselector(fselector = fs("random_search", batch_size = 10), learner = lrn("classif.rpart"), resampling = rsmp ("holdout"),
3 | measure = msr("classif.ce"), term_evals = 50)
4 |
5 | expect_class(afs, "AutoFSelector")
6 | expect_class(afs$instance_args$terminator, "TerminatorEvals")
7 |
8 | afs = auto_fselector(fselector = fs("random_search", batch_size = 10), learner = lrn("classif.rpart"), resampling = rsmp ("holdout"),
9 | measure = msr("classif.ce"), term_time = 50)
10 |
11 | expect_class(afs, "AutoFSelector")
12 | expect_class(afs$instance_args$terminator, "TerminatorRunTime")
13 |
14 | afs = auto_fselector(fselector = fs("random_search", batch_size = 10), learner = lrn("classif.rpart"), resampling = rsmp ("holdout"),
15 | measure = msr("classif.ce"), term_evals = 10, term_time = 50)
16 |
17 | expect_class(afs, "AutoFSelector")
18 | expect_class(afs$instance_args$terminator, "TerminatorCombo")
19 | })
20 |
21 | # Async ------------------------------------------------------------------------
22 |
23 | test_that("async auto fselector works", {
24 | skip_on_cran()
25 | skip_if_not_installed("rush")
26 | flush_redis()
27 |
28 | mirai::daemons(2)
29 | rush::rush_plan(n_workers = 2, worker_type = "remote")
30 |
31 | afs = auto_fselector(
32 | fselector = fs("async_random_search"),
33 | learner = lrn("classif.rpart"),
34 | resampling = rsmp("cv", folds = 3),
35 | measure = msr("classif.ce"),
36 | terminator = trm("evals", n_evals = 3)
37 | )
38 |
39 | expect_class(afs, "AutoFSelector")
40 | afs$train(tsk("pima"))
41 |
42 | expect_class(afs$fselect_instance, "FSelectInstanceAsyncSingleCrit")
43 | expect_rush_reset(afs$fselect_instance$rush, type = "kill")
44 | })
45 |
46 | test_that("async auto fselector works with rush controller", {
47 | skip_on_cran()
48 | skip_if_not_installed("rush")
49 | flush_redis()
50 |
51 | on.exit(mirai::daemons(0))
52 | mirai::daemons(2)
53 | rush::rush_plan(n_workers = 2, worker_type = "remote")
54 | rush = rush::rsh(network_id = "fselect_network")
55 |
56 | afs = auto_fselector(
57 | fselector = fs("async_random_search"),
58 | learner = lrn("classif.rpart"),
59 | resampling = rsmp("cv", folds = 3),
60 | measure = msr("classif.ce"),
61 | terminator = trm("evals", n_evals = 3),
62 | rush = rush
63 | )
64 |
65 | expect_class(afs, "AutoFSelector")
66 | expect_class(afs$instance_args$rush, "Rush")
67 | afs$train(tsk("pima"))
68 |
69 | expect_class(afs$fselect_instance, "FSelectInstanceAsyncSingleCrit")
70 | expect_rush_reset(afs$fselect_instance$rush, type = "kill")
71 | })
72 |
--------------------------------------------------------------------------------
/R/ObjectiveFSelect.R:
--------------------------------------------------------------------------------
1 | #' @title Class for Feature Selection Objective
2 | #'
3 | #' @description
4 | #' Stores the objective function that estimates the performance of feature subsets.
5 | #' This class is usually constructed internally by the [FSelectInstanceBatchSingleCrit] / [FSelectInstanceBatchMultiCrit].
6 | #'
7 | #' @template param_task
8 | #' @template param_learner
9 | #' @template param_resampling
10 | #' @template param_measures
11 | #' @template param_store_models
12 | #' @template param_check_values
13 | #' @template param_store_benchmark_result
14 | #' @template param_callbacks
15 | #'
16 | #' @export
17 | ObjectiveFSelect = R6Class("ObjectiveFSelect",
18 | inherit = Objective,
19 | public = list(
20 |
21 | #' @field task ([mlr3::Task]).
22 | task = NULL,
23 |
24 | #' @field learner ([mlr3::Learner]).
25 | learner = NULL,
26 |
27 | #' @field resampling ([mlr3::Resampling]).
28 | resampling = NULL,
29 |
30 | #' @field measures (list of [mlr3::Measure]).
31 | measures = NULL,
32 |
33 | #' @field store_models (`logical(1)`).
34 | store_models = NULL,
35 |
36 | #' @field store_benchmark_result (`logical(1)`).
37 | store_benchmark_result = NULL,
38 |
39 | #' @field callbacks (List of [CallbackBatchFSelect]s).
40 | callbacks = NULL,
41 |
42 | #' @description
43 | #' Creates a new instance of this [R6][R6::R6Class] class.
44 | initialize = function(
45 | task,
46 | learner,
47 | resampling,
48 | measures,
49 | check_values = TRUE,
50 | store_benchmark_result = TRUE,
51 | store_models = FALSE,
52 | callbacks = NULL
53 | ) {
54 | self$task = assert_task(as_task(task, clone = TRUE))
55 | self$learner = assert_learner(as_learner(learner, clone = TRUE), task = self$task)
56 | self$measures = assert_measures(as_measures(measures, clone = TRUE), task = self$task, learner = self$learner)
57 | self$store_models = assert_flag(store_models)
58 | self$store_benchmark_result = assert_flag(store_benchmark_result) || self$store_models
59 | self$callbacks = assert_callbacks(as_callbacks(callbacks))
60 |
61 | super$initialize(
62 | id = sprintf("%s_on_%s", self$learner$id, self$task$id),
63 | properties = "noisy",
64 | domain = task_to_domain(self$task),
65 | codomain = measures_to_codomain(self$measures),
66 | constants = ps(resampling = p_uty()),
67 | check_values = check_values)
68 |
69 | # set resamplings in constants
70 | resampling = assert_resampling(as_resampling(resampling, clone = TRUE))
71 | if (!resampling$is_instantiated) resampling$instantiate(task)
72 | self$resampling = resampling
73 | self$constants$values$resampling = list(resampling)
74 | }
75 | )
76 | )
77 |
--------------------------------------------------------------------------------
/tests/testthat/test_fsi.R:
--------------------------------------------------------------------------------
1 | test_that("fsi function creates a FSelectInstanceBatchSingleCrit", {
2 | instance = fsi(
3 | task = tsk("pima"),
4 | learner = lrn("classif.rpart"),
5 | resampling = rsmp ("holdout"),
6 | measures = msr("classif.ce"),
7 | terminator = trm("evals", n_evals = 2))
8 | expect_class(instance, "FSelectInstanceBatchSingleCrit")
9 | })
10 |
11 | test_that("fsi function creates a FSelectInstanceBatchMultiCrit", {
12 | instance = fsi(
13 | task = tsk("pima"),
14 | learner = lrn("classif.rpart"),
15 | resampling = rsmp ("holdout"),
16 | measures = msrs(c("classif.ce", "classif.acc")),
17 | terminator = trm("evals", n_evals = 2))
18 | expect_class(instance, "FSelectInstanceBatchMultiCrit")
19 | })
20 |
21 | test_that("fsi and FSelectInstanceBatchSingleCrit are equal", {
22 | fsi_args = formalArgs(fsi)
23 | fsi_args[fsi_args == "measures"] = "measure"
24 |
25 | expect_equal(fsi_args, formalArgs(FSelectInstanceBatchSingleCrit$public_methods$initialize))
26 |
27 | task = tsk("pima")
28 | learner = lrn("classif.rpart")
29 | resampling = rsmp ("holdout")
30 | measures = msr("classif.ce")
31 | terminator = trm("evals", n_evals = 2)
32 | store_benchmark_result = FALSE
33 | store_models = TRUE
34 | check_values = TRUE
35 | callbacks = clbk("mlr3fselect.backup")
36 | resampling$instantiate(task)
37 |
38 | instance_1 = FSelectInstanceBatchSingleCrit$new(task, learner, resampling, measures, terminator, store_benchmark_result, store_models, check_values, callbacks)
39 | instance_2 = fsi(task, learner, resampling, measures, terminator, store_benchmark_result, store_models, check_values, callbacks)
40 |
41 | suppressWarnings(expect_equal(instance_1, instance_2))
42 | })
43 |
44 | test_that("fsi and FSelectInstanceBatchMultiCrit are equal", {
45 | fsi_args = formalArgs(fsi)
46 | fsi_args = fsi_args[fsi_args != "ties_method"]
47 |
48 | expect_equal(fsi_args, formalArgs(FSelectInstanceBatchMultiCrit$public_methods$initialize))
49 |
50 | task = tsk("pima")
51 | learner = lrn("classif.rpart")
52 | resampling = rsmp ("holdout")
53 | measures = msrs(c("classif.ce", "classif.acc"))
54 | terminator = trm("evals", n_evals = 2)
55 | store_benchmark_result = FALSE
56 | store_models = TRUE
57 | check_values = TRUE
58 | callbacks = clbk("mlr3fselect.backup")
59 | resampling$instantiate(task)
60 |
61 | instance_1 = FSelectInstanceBatchMultiCrit$new(task, learner, resampling, measures, terminator, store_benchmark_result, store_models, check_values, callbacks)
62 | instance_2 = fsi(task, learner, resampling, measures, terminator, store_benchmark_result, store_models, check_values, callbacks)
63 |
64 | suppressWarnings(expect_equal(instance_1, instance_2))
65 | })
66 |
67 |
--------------------------------------------------------------------------------
/man/extract_inner_fselect_archives.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/extract_inner_fselect_archives.R
3 | \name{extract_inner_fselect_archives}
4 | \alias{extract_inner_fselect_archives}
5 | \title{Extract Inner Feature Selection Archives}
6 | \usage{
7 | extract_inner_fselect_archives(x, exclude_columns = "uhash")
8 | }
9 | \arguments{
10 | \item{x}{(\link[mlr3:ResampleResult]{mlr3::ResampleResult} | \link[mlr3:BenchmarkResult]{mlr3::BenchmarkResult}).}
11 |
12 | \item{exclude_columns}{(\code{character()})\cr
13 | Exclude columns from result table. Set to \code{NULL} if no column should be
14 | excluded.}
15 | }
16 | \value{
17 | \code{\link[data.table:data.table]{data.table::data.table()}}.
18 | }
19 | \description{
20 | Extract inner feature selection archives of nested resampling.
21 | Implemented for \link[mlr3:ResampleResult]{mlr3::ResampleResult} and \link[mlr3:BenchmarkResult]{mlr3::BenchmarkResult}.
22 | The function iterates over the \link{AutoFSelector} objects and binds the archives to a \code{\link[data.table:data.table]{data.table::data.table()}}.
23 | \link{AutoFSelector} must be initialized with \code{store_fselect_instance = TRUE} and \code{resample()} or \code{benchmark()} must be called with \code{store_models = TRUE}.
24 | }
25 | \section{Data structure}{
26 |
27 |
28 | The returned data table has the following columns:
29 | \itemize{
30 | \item \code{experiment} (integer(1))\cr
31 | Index, giving the according row number in the original benchmark grid.
32 | \item \code{iteration} (integer(1))\cr
33 | Iteration of the outer resampling.
34 | \item One column for each feature of the task.
35 | \item One column for each performance measure.
36 | \item \code{runtime_learners} (\code{numeric(1)})\cr
37 | Sum of training and predict times logged in learners per
38 | \link[mlr3:ResampleResult]{mlr3::ResampleResult} / evaluation. This does not include potential
39 | overhead time.
40 | \item \code{timestamp} (\code{POSIXct})\cr
41 | Time stamp when the evaluation was logged into the archive.
42 | \item \code{batch_nr} (\code{integer(1)})\cr
43 | Feature sets are evaluated in batches. Each batch has a unique batch
44 | number.
45 | \item \code{resample_result} (\link[mlr3:ResampleResult]{mlr3::ResampleResult})\cr
46 | Resample result of the inner resampling.
47 | \item \code{task_id} (\code{character(1)}).
48 | \item \code{learner_id} (\code{character(1)}).
49 | \item \code{resampling_id} (\code{character(1)}).
50 | }
51 | }
52 |
53 | \examples{
54 | # Nested Resampling on Palmer Penguins Data Set
55 |
56 | # create auto fselector
57 | at = auto_fselector(
58 | fselector = fs("random_search"),
59 | learner = lrn("classif.rpart"),
60 | resampling = rsmp ("holdout"),
61 | measure = msr("classif.ce"),
62 | term_evals = 4)
63 |
64 | resampling_outer = rsmp("cv", folds = 2)
65 | rr = resample(tsk("penguins"), at, resampling_outer, store_models = TRUE)
66 |
67 | # extract inner archives
68 | extract_inner_fselect_archives(rr)
69 | }
70 |
--------------------------------------------------------------------------------
/NAMESPACE:
--------------------------------------------------------------------------------
1 | # Generated by roxygen2: do not edit by hand
2 |
3 | S3method(as.data.table,ArchiveAsyncFSelect)
4 | S3method(as.data.table,ArchiveAsyncFSelectFrozen)
5 | S3method(as.data.table,ArchiveBatchFSelect)
6 | S3method(as.data.table,DictionaryFSelector)
7 | S3method(as.data.table,EnsembleFSResult)
8 | S3method(c,EnsembleFSResult)
9 | S3method(extract_inner_fselect_archives,BenchmarkResult)
10 | S3method(extract_inner_fselect_archives,ResampleResult)
11 | S3method(extract_inner_fselect_results,BenchmarkResult)
12 | S3method(extract_inner_fselect_results,ResampleResult)
13 | export(ArchiveAsyncFSelect)
14 | export(ArchiveAsyncFSelectFrozen)
15 | export(ArchiveBatchFSelect)
16 | export(AutoFSelector)
17 | export(CallbackAsyncFSelect)
18 | export(ContextAsyncFSelect)
19 | export(ContextBatchFSelect)
20 | export(EnsembleFSResult)
21 | export(FSelectInstanceAsyncMultiCrit)
22 | export(FSelectInstanceAsyncSingleCrit)
23 | export(FSelectInstanceBatchMultiCrit)
24 | export(FSelectInstanceBatchSingleCrit)
25 | export(FSelector)
26 | export(FSelectorAsync)
27 | export(FSelectorAsyncDesignPoints)
28 | export(FSelectorAsyncExhaustiveSearch)
29 | export(FSelectorAsyncFromOptimizerAsync)
30 | export(FSelectorAsyncRandomSearch)
31 | export(FSelectorBatch)
32 | export(FSelectorBatchDesignPoints)
33 | export(FSelectorBatchExhaustiveSearch)
34 | export(FSelectorBatchFromOptimizerBatch)
35 | export(FSelectorBatchGeneticSearch)
36 | export(FSelectorBatchRFE)
37 | export(FSelectorBatchRFECV)
38 | export(FSelectorBatchRandomSearch)
39 | export(FSelectorBatchSequential)
40 | export(FSelectorBatchShadowVariableSearch)
41 | export(ObjectiveFSelect)
42 | export(ObjectiveFSelectAsync)
43 | export(ObjectiveFSelectBatch)
44 | export(assert_async_fselect_callback)
45 | export(assert_async_fselect_callbacks)
46 | export(assert_fselect_instance)
47 | export(assert_fselect_instance_async)
48 | export(assert_fselect_instance_batch)
49 | export(assert_fselector_async)
50 | export(assert_fselector_batch)
51 | export(assert_fselectors)
52 | export(auto_fselector)
53 | export(callback_async_fselect)
54 | export(callback_batch_fselect)
55 | export(clbk)
56 | export(clbks)
57 | export(embedded_ensemble_fselect)
58 | export(ensemble_fselect)
59 | export(extract_inner_fselect_archives)
60 | export(extract_inner_fselect_results)
61 | export(faggregate)
62 | export(fs)
63 | export(fselect)
64 | export(fselect_nested)
65 | export(fsi)
66 | export(fsi_async)
67 | export(fss)
68 | export(mlr_callbacks)
69 | export(mlr_fselectors)
70 | export(mlr_terminators)
71 | export(trm)
72 | export(trms)
73 | import(bbotk)
74 | import(checkmate)
75 | import(cli)
76 | import(data.table)
77 | import(mlr3)
78 | import(mlr3misc)
79 | import(paradox)
80 | importFrom(R6,R6Class)
81 | importFrom(bbotk,mlr_terminators)
82 | importFrom(bbotk,trm)
83 | importFrom(bbotk,trms)
84 | importFrom(mlr3misc,clbk)
85 | importFrom(mlr3misc,clbks)
86 | importFrom(mlr3misc,mlr_callbacks)
87 | importFrom(stats,sd)
88 | importFrom(utils,bibentry)
89 | importFrom(utils,combn)
90 | importFrom(utils,head)
91 | importFrom(utils,packageVersion)
92 | importFrom(utils,tail)
93 |
--------------------------------------------------------------------------------
/man/ObjectiveFSelectAsync.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ObjectiveFSelectAsync.R
3 | \name{ObjectiveFSelectAsync}
4 | \alias{ObjectiveFSelectAsync}
5 | \title{Class for Feature Selection Objective}
6 | \description{
7 | Stores the objective function that estimates the performance of feature subsets.
8 | This class is usually constructed internally by the \link{FSelectInstanceAsyncSingleCrit} or \link{FSelectInstanceAsyncMultiCrit}.
9 | }
10 | \section{Super classes}{
11 | \code{\link[bbotk:Objective]{bbotk::Objective}} -> \code{\link[mlr3fselect:ObjectiveFSelect]{mlr3fselect::ObjectiveFSelect}} -> \code{ObjectiveFSelectAsync}
12 | }
13 | \section{Methods}{
14 | \subsection{Public methods}{
15 | \itemize{
16 | \item \href{#method-ObjectiveFSelectAsync-clone}{\code{ObjectiveFSelectAsync$clone()}}
17 | }
18 | }
19 | \if{html}{\out{
20 | Inherited methods
21 |
30 |
mlr3misc::Context$format()mlr3misc::Context$print()bbotk::ContextAsync$initialize()mlr3misc::Context$format()mlr3misc::Context$print()bbotk::ContextBatch$initialize()mlr3misc::Callback$call()mlr3misc::Callback$format()mlr3misc::Callback$help()mlr3misc::Callback$initialize()mlr3misc::Callback$print()mlr3misc::Callback$call()mlr3misc::Callback$format()mlr3misc::Callback$help()mlr3misc::Callback$initialize()mlr3misc::Callback$print()