Skip to content

Commit 0b164e4

Browse files
authored
fix(rfe): write importance to the whole batch when recursive is FALSE (#168)
1 parent 186024b commit 0b164e4

3 files changed

Lines changed: 32 additions & 1 deletion

File tree

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# mlr3fselect (development version)
22

33
* fix: `ArchiveAsyncFSelect` pushed results with the removed `rush::Rush$push_results()` method.
4+
* fix: `fs("rfecv", recursive = FALSE)` failed with an internal `data.table` error because the importance scores of all resampling iterations were written to a single archive row (#168).
45
* fix: `fs("rfecv")` ignored the direction of the measure and selected the feature set size with the worst mean performance for minimizing measures such as `msr("classif.ce")` or `msr("regr.mse")`.
56
Feature selection results obtained with `fs("rfecv")` and a minimizing measure are invalid and should be recomputed (#167).
67

R/FSelectorBatchRFE.R

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,12 @@ rfe_workhorse = function(inst, subsets, recursive, aggregation = raw_importance,
277277
archive$data[list(archive$n_batch), "importance" := importances, on = "batch_nr"]
278278
} else {
279279
# log importance to archive
280-
set(archive$data, archive$n_evals, "importance", map(importances, function(x) x[seq(j)]))
280+
# the batch holds one row per fold, so the truncated importance of each fold is assigned to the whole batch
281+
archive$data[
282+
list(archive$n_batch),
283+
"importance" := map(importances, function(x) x[seq(j)]),
284+
on = "batch_nr"
285+
]
281286
}
282287
}
283288
if (folds > 1) {

tests/testthat/test_FSelectorRFECV.R

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,31 @@ test_that("default parameters work", {
6868
})
6969
})
7070

71+
test_that("recursive parameter works", {
72+
instance = fsi(
73+
task = TEST_MAKE_TSK(),
74+
learner = lrn("regr.rpart"),
75+
resampling = rsmp("cv", folds = 3),
76+
measures = msr("dummy"),
77+
terminator = trm("none"),
78+
store_models = TRUE
79+
)
80+
81+
optimizer = fs("rfecv", recursive = FALSE, n_features = 1, feature_number = 1)
82+
optimizer$optimize(instance)
83+
data = instance$archive$data
84+
85+
# the importance of the first batch is reused and truncated in the following batches
86+
walk(seq(3), function(i) {
87+
importances = data[list(i), importance, on = "iteration"]
88+
walk(seq(2, length(importances)), function(j) {
89+
expect_equal(importances[[j]], importances[[1]][seq(length(importances) + 1 - j)])
90+
})
91+
})
92+
93+
pwalk(data, function(x1, x2, x3, x4, importance, ...) expect_equal(x1 + x2 + x3 + x4, length(importance)))
94+
})
95+
7196
test_that("learner without importance method throw an error", {
7297
learner = lrn("classif.rpart")
7398
learner$properties = setdiff(learner$properties, "importance")

0 commit comments

Comments
 (0)