Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# glex 0.6.0.9000 (development version)

* `glex()` now warns when `x` contains missing values (#41): splits are evaluated
without the model's learned missing-value direction, so the decomposition of rows
with `NA`s is unreliable and does not sum to the model prediction. Proper missing
value support needs more investigation; previously such input passed silently.

* `glex()` on `xgboost` models fit with early stopping now decomposes only the trees
up to `best_iteration`, matching what `predict()` evaluates by default. Previously
all fitted trees were decomposed, so the components did not sum to the prediction.
Expand Down
11 changes: 11 additions & 0 deletions R/glex.R
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,17 @@ calc_components <- function(
Feature_num <- NULL
Tree <- NULL

# Splits are evaluated as plain comparisons, which route an NA to the "No"
# branch regardless of the missing-value direction the model learned, and NA
# rows distort the background sample used for marginalization (#41).
if (anyNA(x)) {
warning(
"`x` contains missing values. glex routes them through splits without ",
"the model's learned missing-value direction, so the decomposition is ",
"unreliable and will not sum to the model prediction."
)
}

# Convert features to numerics (leaf = 0)
unique_features_in_tree <- unique(trees$Feature)
unique_features_in_tree <- unique_features_in_tree[
Expand Down
12 changes: 12 additions & 0 deletions tests/testthat/test-glex-xgboost.R
Original file line number Diff line number Diff line change
Expand Up @@ -368,3 +368,15 @@ test_that("early-stopped models are decomposed up to best_iteration, like predic
tolerance = 1e-5
)
})

test_that("missing values in x trigger a warning", {
set.seed(1)
x <- as.matrix(mtcars[, -1])
xg <- xgboost(x, mtcars$mpg, nrounds = 5, max_depth = 2, verbosity = 0)

x_na <- x
x_na[1, "cyl"] <- NA
expect_warning(glex(xg, x_na), "missing values")

expect_no_warning(glex(xg, x))
})
Loading