ModelOriented / localModel

LIME-like explanations with interpretable features based on Ceteris Paribus curves. Now on CRAN.
https://modeloriented.github.io/localModel
14 stars 3 forks source link

individual_surrogate_model yields incorrect results because column names are mixed up #37

Closed FrieseWoudloper closed 3 years ago

FrieseWoudloper commented 3 years ago

The function transform_to_interpretable returns a data frame with the wrong column names. I'm using the latest localModel version from Github (0.5).

Test case:

library(archivist)
library(DALEX)
library(DALEXtra)
library(randomForest)

titanic  <- archivist::aread("pbiecek/models/27e5c")
new_observation <- archivist::aread("pbiecek/models/e3596")
titanic_rf  <- archivist::aread("pbiecek/models/4e0fc")

x <- explain(model = titanic_rf, 
                    data = titanic[, -9],
                    y = titanic$survived == "yes", 
                    label = "Random Forest",
                    verbose = FALSE)
seed <- 1

I then run this code (taken from individual_surrogate_model function):

  x$data <- x$data[, intersect(colnames(x$data), colnames(new_observation)), drop = F]
  predicted_names <- assign_target_names(x)

  # Create interpretable features
  feature_representations_full <- get_feature_representations(x, new_observation,
                                                              predicted_names, seed)
  encoded_data <- transform_to_interpretable(x, new_observation,
                                             feature_representations_full)

Contents of encoded_data:

          class       gender      age                           sibsp    parch     fare
1 gender = male     baseline baseline embarked = Belfast, Southampton baseline baseline
2 gender = male age <= 15.36 baseline embarked = Belfast, Southampton baseline baseline
3 gender = male     baseline baseline embarked = Belfast, Southampton baseline baseline

     parch     fare embarked
1 baseline baseline baseline
2 baseline baseline baseline
3 baseline baseline baseline

The column names are not correct: class should be gender, gender should be age, etcetera.

I think this causes the counterintuitive LIME explanation for Johnny D's prediction from the random forest model found in section 9.6.2 of the book Explanatory Model Analysis:

http://ema.drwhy.ai/ema_files/figure-html/limeExplLocalModelTitanic-1.png

This problem is caused by a line of code in the function transform_to_interpretable:

transform_to_interpretable <- function(x, new_observation,
                                       feature_representations) {
  encoded_data <- as.data.frame(lapply(feature_representations,
                                       function(x) x[[1]]))
  colnames(encoded_data) <- intersect(colnames(new_observation),
                                       colnames(x$data))
  encoded_data
}

This solution works for my test case, but might not work for all cases:

transform_to_interpretable <- function(x, new_observation,
                                       feature_representations) {
  encoded_data <- as.data.frame(lapply(feature_representations,
                                       function(x) x[[1]]))
  colnames(encoded_data) <- colnames(x$data)
  encoded_data
}

in which case the new_observation argument is obsolete.

FrieseWoudloper commented 3 years ago

The problem arrises when the ordering of columns in the dataframe of the explainer containing the instances, is different from that in the dataframe containing the new observation.

pbiecek commented 3 years ago

Thank you for fixing this problem!