Exact additive SHAP assuming feature independence. The implementation works for models fitted via

additive_shap(object, X, verbose = TRUE, ...)

Arguments

object

Fitted additive model.

X

Dataframe with rows to be explained. Passed to predict(object, newdata = X, type = "terms").

verbose

Set to FALSE to suppress messages.

...

Currently unused.

Value

An object of class "kernelshap" with the following components:

  • S: \((n \times p)\) matrix with SHAP values.

  • X: Same as input argument X.

  • baseline: The baseline.

  • exact: TRUE.

  • txt: Summary text.

  • predictions: Vector with predictions of X on the scale of "terms".

  • algorithm: "additive_shap".

Details

The SHAP values are extracted via predict(object, newdata = X, type = "terms"), a logic adopted from fastshap:::explain.lm(..., exact = TRUE). Models with interactions (specified via : or *), or with terms of multiple features like log(x1/x2) are not supported.

Note that the SHAP values obtained by additive_shap() are expected to match those of permshap() and kernelshap() as long as their background data equals the full training data (which is typically not feasible).

Examples

# MODEL ONE: Linear regression
fit <- lm(Sepal.Length ~ ., data = iris)
s <- additive_shap(fit, head(iris))
#> Exact additive SHAP via predict(..., type = 'terms')
s
#> SHAP values of first observations:
#>      Sepal.Width Petal.Length Petal.Width   Species
#> [1,]  0.21951350    -1.955357   0.3149451 0.5823533
#> [2,] -0.02843097    -1.955357   0.3149451 0.5823533

# MODEL TWO: More complicated (but not very clever) formula
fit <- lm(
  Sepal.Length ~ poly(Sepal.Width, 2) + log(Petal.Length) + log(Sepal.Width),
  data = iris
)
s_add <- additive_shap(fit, head(iris))
#> Exact additive SHAP via predict(..., type = 'terms')
s_add
#> SHAP values of first observations:
#>      Sepal.Width Petal.Length
#> [1,]   0.3380346    -1.205754
#> [2,]  -0.0577949    -1.205754

# Equals kernelshap()/permshap() when background data is full training data
s_kernel <- kernelshap(
 fit, head(iris[c("Sepal.Width", "Petal.Length")]), bg_X = iris
)
#> Exact Kernel SHAP values
#> 
  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |============                                                          |  17%
  |                                                                            
  |=======================                                               |  33%
  |                                                                            
  |===================================                                   |  50%
  |                                                                            
  |===============================================                       |  67%
  |                                                                            
  |==========================================================            |  83%
  |                                                                            
  |======================================================================| 100%
all.equal(s_add$S, s_kernel$S)
#> [1] TRUE