Exact additive SHAP assuming feature independence. The implementation works for models fitted via
lm()
,
gam::gam()
,
survival::coxph()
, and
additive_shap(object, X, verbose = TRUE, ...)
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".
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).
# 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