diff --git a/DESCRIPTION b/DESCRIPTION index 6f4dbab7..f09edf7e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: mlr3fselect Title: Feature Selection for 'mlr3' -Version: 1.1.1.9000 +Version: 1.2.1.9000 Authors@R: c( person("Marc", "Becker", , "marcbecker@posteo.de", role = c("aut", "cre"), comment = c(ORCID = "0000-0002-8115-0400")), @@ -27,7 +27,7 @@ Depends: mlr3 (>= 0.21.1), R (>= 3.1.0) Imports: - bbotk (>= 1.0.0), + bbotk (>= 1.2.0), checkmate (>= 2.0.0), data.table, lgr, @@ -43,8 +43,6 @@ Suggests: mlr3pipelines, rpart, testthat (>= 3.0.0) -Remotes: - mlr-org/bbotk Config/testthat/edition: 3 Config/testthat/parallel: true Encoding: UTF-8 diff --git a/NEWS.md b/NEWS.md index 4e6cd6d4..c456706a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,13 @@ # mlr3fselect (development version) +# mlr3fselect 1.2.1 + +* compatibility: mlr3 0.22.0 + +# mlr3fselect 1.2.0 + * feat: Add internal tuning callback `mlr3fselect.internal_tuning`. +* fix: Register mlr3fselect in the `mlr_reflections$loaded_packages` field. # mlr3fselect 1.1.1 diff --git a/R/AutoFSelector.R b/R/AutoFSelector.R index de08ed9f..49c481df 100644 --- a/R/AutoFSelector.R +++ b/R/AutoFSelector.R @@ -37,6 +37,7 @@ #' @template param_check_values #' @template param_callbacks #' @template param_ties_method +#' @template param_id #' #' @export #' @examples @@ -123,7 +124,8 @@ AutoFSelector = R6Class("AutoFSelector", store_models = FALSE, check_values = FALSE, callbacks = NULL, - ties_method = "least_features" + ties_method = "least_features", + id = NULL ) { ia = list() self$fselector = assert_r6(fselector, "FSelector")$clone() @@ -141,8 +143,10 @@ AutoFSelector = R6Class("AutoFSelector", ia$ties_method = assert_choice(ties_method, c("least_features", "random")) self$instance_args = ia + id = assert_string(id, null.ok = TRUE) %??% paste0(learner$id, ".fselector") + super$initialize( - id = paste0(learner$id, ".fselector"), + id = id, task_type = learner$task_type, packages = c("mlr3fselect", learner$packages), feature_types = learner$feature_types, diff --git a/R/auto_fselector.R b/R/auto_fselector.R index 8a92d7be..698ada12 100644 --- a/R/auto_fselector.R +++ b/R/auto_fselector.R @@ -20,6 +20,7 @@ #' @template param_check_values #' @template param_callbacks #' @template param_ties_method +#' @template param_id #' #' @export #' @inherit AutoFSelector examples @@ -36,7 +37,8 @@ auto_fselector = function( store_models = FALSE, check_values = FALSE, callbacks = NULL, - ties_method = "least_features" + ties_method = "least_features", + id = NULL ) { terminator = terminator %??% terminator_selection(term_evals, term_time) @@ -51,5 +53,6 @@ auto_fselector = function( store_models = store_models, check_values = check_values, callbacks = callbacks, - ties_method = ties_method) + ties_method = ties_method, + id = id) } diff --git a/R/mlr_callbacks.R b/R/mlr_callbacks.R index 9c5cac29..135b6ccc 100644 --- a/R/mlr_callbacks.R +++ b/R/mlr_callbacks.R @@ -153,7 +153,7 @@ load_callback_one_se_rule = function() { label = "One Standard Error Rule Callback", man = "mlr3fselect::mlr3fselect.one_se_rule", - on_result = function(callback, context) { + on_optimization_end = function(callback, context) { archive = context$instance$archive data = as.data.table(archive) data[, "n_features" := map(get("features"), length)] @@ -203,7 +203,7 @@ load_callback_internal_tuning = function() { callback$state$internal_search_space$aggr_internal_tuned_values(internal_tuned_values) }) - data.table::set(context$aggregated_performance, j = "internal_tuned_values", value = list(internal_tuned_values)) + data.table::set(context$aggregated_performance, j = "internal_tuned_values", value = list(internal_tuned_values)) }, on_optimization_end = function(callback, context) { diff --git a/man/AutoFSelector.Rd b/man/AutoFSelector.Rd index dd4954de..365d9385 100644 --- a/man/AutoFSelector.Rd +++ b/man/AutoFSelector.Rd @@ -176,7 +176,8 @@ Creates a new instance of this \link[R6:R6Class]{R6} class. store_models = FALSE, check_values = FALSE, callbacks = NULL, - ties_method = "least_features" + ties_method = "least_features", + id = NULL )}\if{html}{\out{}} } @@ -224,6 +225,9 @@ The option \code{"least_features"} (default) selects the feature set with the le If there are multiple best feature sets with the same number of features, one is selected randomly. The \code{random} method returns a random feature set from the best feature sets. Ignored if multiple measures are used.} + +\item{\code{id}}{(\code{character(1)})\cr +Identifier for the new instance.} } \if{html}{\out{}} } diff --git a/man/auto_fselector.Rd b/man/auto_fselector.Rd index 55d4183c..cd947011 100644 --- a/man/auto_fselector.Rd +++ b/man/auto_fselector.Rd @@ -17,7 +17,8 @@ auto_fselector( store_models = FALSE, check_values = FALSE, callbacks = NULL, - ties_method = "least_features" + ties_method = "least_features", + id = NULL ) } \arguments{ @@ -70,6 +71,9 @@ The option \code{"least_features"} (default) selects the feature set with the le If there are multiple best feature sets with the same number of features, one is selected randomly. The \code{random} method returns a random feature set from the best feature sets. Ignored if multiple measures are used.} + +\item{id}{(\code{character(1)})\cr +Identifier for the new instance.} } \value{ \link{AutoFSelector}. diff --git a/tests/testthat/test_AutoFSelector.R b/tests/testthat/test_AutoFSelector.R index 58df4180..c48eb5ac 100644 --- a/tests/testthat/test_AutoFSelector.R +++ b/tests/testthat/test_AutoFSelector.R @@ -189,6 +189,7 @@ test_that("AutoFSelector get_base_learner method works", { test_that("AutoFSelector hash works #647 in mlr3", { afs_1 = AutoFSelector$new( + id = "afs_1", learner = lrn("classif.rpart"), resampling = rsmp("holdout"), measure = msr("classif.ce"), @@ -197,6 +198,7 @@ test_that("AutoFSelector hash works #647 in mlr3", { store_benchmark_result = FALSE) afs_2 = AutoFSelector$new( + id = "afs_2", learner = lrn("classif.rpart"), resampling = rsmp("holdout"), measure = msr("classif.ce"), diff --git a/tests/testthat/test_FSelectorShadowVariableSearch.R b/tests/testthat/test_FSelectorShadowVariableSearch.R index a76b267f..cc8db784 100644 --- a/tests/testthat/test_FSelectorShadowVariableSearch.R +++ b/tests/testthat/test_FSelectorShadowVariableSearch.R @@ -43,7 +43,7 @@ test_that("second selected feature is a shadow variable works", { expect_equal(instance$search_space, domain) expect_equal(instance$objective$domain, domain) # check that task is restored - expect_equal(instance$objective$task, task) + suppressWarnings(expect_equal(instance$objective$task, task)) }) test_that("search is terminated by terminator works", { diff --git a/tests/testthat/test_extract_inner_fselect_archives.R b/tests/testthat/test_extract_inner_fselect_archives.R index 9222f683..59255a9a 100644 --- a/tests/testthat/test_extract_inner_fselect_archives.R +++ b/tests/testthat/test_extract_inner_fselect_archives.R @@ -17,8 +17,8 @@ test_that("extract_inner_fselect_archives function works with resample and repea }) test_that("extract_inner_fselect_archives function works with benchmark and cv", { - at_1 = auto_fselector(fs("random_search", batch_size = 1), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) - at_2 = auto_fselector(fs("random_search", batch_size = 1), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) + at_1 = auto_fselector(fs("random_search", batch_size = 1), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_1") + at_2 = auto_fselector(fs("random_search", batch_size = 1), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_2") resampling_outer = rsmp("cv", folds = 2) grid = benchmark_grid(tsk("iris"), list(at_1, at_2), resampling_outer) bmr = benchmark(grid, store_models = TRUE) @@ -30,8 +30,8 @@ test_that("extract_inner_fselect_archives function works with benchmark and cv", }) test_that("extract_inner_fselect_archives function works with benchmark and repeated cv", { - at_1 = auto_fselector(fs("random_search", batch_size = 1), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) - at_2 = auto_fselector(fs("random_search", batch_size = 1), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) + at_1 = auto_fselector(fs("random_search", batch_size = 1), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_1") + at_2 = auto_fselector(fs("random_search", batch_size = 1), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_2") resampling_outer = rsmp("repeated_cv", folds = 2, repeats = 3) grid = benchmark_grid(tsk("iris"), list(at_1, at_2), resampling_outer) bmr = benchmark(grid, store_models = TRUE) @@ -43,8 +43,8 @@ test_that("extract_inner_fselect_archives function works with benchmark and repe }) test_that("extract_inner_fselect_archives function works with multiple tasks", { - at_1 = auto_fselector(fs("random_search", batch_size = 1), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) - at_2 = auto_fselector(fs("random_search", batch_size = 1), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) + at_1 = auto_fselector(fs("random_search", batch_size = 1), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_1") + at_2 = auto_fselector(fs("random_search", batch_size = 1), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_2") resampling_outer = rsmp("cv", folds = 2) grid = benchmark_grid(list(tsk("iris"), tsk("pima")), list(at_1, at_2), resampling_outer) bmr = benchmark(grid, store_models = TRUE) @@ -73,8 +73,8 @@ test_that("extract_inner_fselect_archives function works with no instance", { }) test_that("extract_inner_fselect_archives function works with benchmark and no models", { - at_1 = auto_fselector(fs("random_search", batch_size = 1), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) - at_2 = auto_fselector(fs("random_search", batch_size = 1), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) + at_1 = auto_fselector(fs("random_search", batch_size = 1), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_1") + at_2 = auto_fselector(fs("random_search", batch_size = 1), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_2") resampling_outer = rsmp("cv", folds = 2) grid = benchmark_grid(tsk("iris"), list(at_1, at_2), resampling_outer) bmr = benchmark(grid, store_models = FALSE) @@ -84,9 +84,9 @@ test_that("extract_inner_fselect_archives function works with benchmark and no m test_that("extract_inner_fselect_archives function works with mixed store instance", { at_1 = AutoFSelector$new(lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), trm("evals", n_evals = 4), - fselector = fs("random_search", batch_size = 1), store_fselect_instance = FALSE, store_benchmark_result = FALSE) + fselector = fs("random_search", batch_size = 1), store_fselect_instance = FALSE, store_benchmark_result = FALSE, id = "at_1") at_2 = AutoFSelector$new(lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), trm("evals", n_evals = 4), - fselector = fs("random_search", batch_size = 1)) + fselector = fs("random_search", batch_size = 1), id = "at_2") resampling_outer = rsmp("cv", folds = 2) grid = benchmark_grid(tsk("iris"), list(at_1, at_2), resampling_outer) bmr = benchmark(grid, store_models = TRUE) diff --git a/tests/testthat/test_extract_inner_fselect_result.R b/tests/testthat/test_extract_inner_fselect_result.R index a2d0ddcb..c989e79e 100644 --- a/tests/testthat/test_extract_inner_fselect_result.R +++ b/tests/testthat/test_extract_inner_fselect_result.R @@ -17,8 +17,8 @@ test_that("extract_inner_fselect_results function works with resample and repeat }) test_that("extract_inner_fselect_results function works with benchmark and cv", { - at_1 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) - at_2 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) + at_1 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_1") + at_2 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_2") resampling_outer = rsmp("cv", folds = 2) grid = benchmark_grid(tsk("iris"), list(at_1, at_2), resampling_outer) bmr = benchmark(grid, store_models = TRUE) @@ -30,8 +30,8 @@ test_that("extract_inner_fselect_results function works with benchmark and cv", }) test_that("extract_inner_fselect_results function works with benchmark and repeated cv", { - at_1 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) - at_2 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) + at_1 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_1") + at_2 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_2") resampling_outer = rsmp("repeated_cv", folds = 2, repeats = 3) grid = benchmark_grid(tsk("iris"), list(at_1, at_2), resampling_outer) bmr = benchmark(grid, store_models = TRUE) @@ -43,8 +43,8 @@ test_that("extract_inner_fselect_results function works with benchmark and repea }) test_that("extract_inner_fselect_results function works with multiple tasks", { - at_1 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) - at_2 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) + at_1 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_1") + at_2 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_2") resampling_outer = rsmp("cv", folds = 2) grid = benchmark_grid(list(tsk("iris"), tsk("pima")), list(at_1, at_2), resampling_outer) bmr = benchmark(grid, store_models = TRUE) @@ -73,8 +73,8 @@ test_that("extract_inner_fselect_results function works no instance", { }) test_that("extract_inner_fselect_results function works with benchmark and no models", { - at_1 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) - at_2 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) + at_1 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_1") + at_2 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_2") resampling_outer = rsmp("cv", folds = 2) grid = benchmark_grid(tsk("iris"), list(at_1, at_2), resampling_outer) bmr = benchmark(grid, store_models = FALSE) @@ -84,9 +84,9 @@ test_that("extract_inner_fselect_results function works with benchmark and no mo test_that("extract_inner_fselect_results function works with mixed store instance", { at_1 = AutoFSelector$new(lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), trm("evals", n_evals = 4), - fselector = fs("random_search"), store_fselect_instance = FALSE, store_benchmark_result = FALSE) + fselector = fs("random_search"), store_fselect_instance = FALSE, store_benchmark_result = FALSE, id = "at_1") at_2 = AutoFSelector$new(lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), trm("evals", n_evals = 4), - fselector = fs("random_search")) + fselector = fs("random_search"), id = "at_2") resampling_outer = rsmp("cv", folds = 2) grid = benchmark_grid(tsk("iris"), list(at_1, at_2), resampling_outer) bmr = benchmark(grid, store_models = TRUE) @@ -118,8 +118,8 @@ test_that("extract_inner_fselect_results function works with resample and return }) test_that("extract_inner_fselect_results function works with benchmark and return of instance", { - at_1 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) - at_2 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4) + at_1 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_1") + at_2 = auto_fselector(fs("random_search"), lrn("classif.rpart"), rsmp("holdout"), msr("classif.ce"), term_evals = 4, id = "at_2") resampling_outer = rsmp("cv", folds = 2) grid = benchmark_grid(tsk("iris"), list(at_1, at_2), resampling_outer) bmr = benchmark(grid, store_models = TRUE) diff --git a/tests/testthat/test_fsi.R b/tests/testthat/test_fsi.R index b07a5191..e327dfe8 100644 --- a/tests/testthat/test_fsi.R +++ b/tests/testthat/test_fsi.R @@ -38,7 +38,7 @@ test_that("fsi and FSelectInstanceBatchSingleCrit are equal", { instance_1 = FSelectInstanceBatchSingleCrit$new(task, learner, resampling, measures, terminator, store_benchmark_result, store_models, check_values, callbacks) instance_2 = fsi(task, learner, resampling, measures, terminator, store_benchmark_result, store_models, check_values, callbacks) - expect_equal(instance_1, instance_2) + suppressWarnings(expect_equal(instance_1, instance_2)) }) test_that("fsi and FSelectInstanceBatchMultiCrit are equal", { @@ -61,5 +61,5 @@ test_that("fsi and FSelectInstanceBatchMultiCrit are equal", { instance_1 = FSelectInstanceBatchMultiCrit$new(task, learner, resampling, measures, terminator, store_benchmark_result, store_models, check_values, callbacks) instance_2 = fsi(task, learner, resampling, measures, terminator, store_benchmark_result, store_models, check_values, callbacks) - expect_equal(instance_1, instance_2) + suppressWarnings(expect_equal(instance_1, instance_2)) })