shap-cuda 0.54.1.dev0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,80 @@
1
+ cmake_minimum_required(VERSION 3.24...3.27)
2
+ project(shap_cuda_extensions LANGUAGES CXX)
3
+
4
+ if (NOT SKBUILD)
5
+ message(FATAL_ERROR "\
6
+ This CMakeLists.txt is meant to be used with scikit-build.
7
+ Please use 'python -m pip install .', not 'cmake'.")
8
+ endif()
9
+
10
+ if (CMAKE_VERSION VERSION_LESS 3.18)
11
+ set(DEV_MODULE Development)
12
+ else()
13
+ set(DEV_MODULE Development.Module)
14
+ endif()
15
+
16
+ find_package(Python 3.12
17
+ COMPONENTS Interpreter ${DEV_MODULE} REQUIRED
18
+ OPTIONAL_COMPONENTS Development.SABIModule)
19
+
20
+ if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
21
+ set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
22
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
23
+ endif()
24
+
25
+ # Optional: CUDA may not be present (e.g. a docs build). In that case skip
26
+ # _cext_gpu and install the pure-Python package only - GPUTreeExplainer's own
27
+ # try/except around importing it degrades to a clear runtime error instead of
28
+ # making the whole install fail.
29
+ enable_language(CUDA OPTIONAL)
30
+
31
+ if(CMAKE_CUDA_COMPILER)
32
+ find_package(CUDAToolkit)
33
+ endif()
34
+
35
+ if(CMAKE_CUDA_COMPILER AND CUDAToolkit_FOUND)
36
+ message(STATUS "CUDA toolkit found, building the _cext_gpu extension.")
37
+
38
+ if(NOT "${SKBUILD_SABI_VERSION}" STREQUAL "")
39
+ set(USE_SABI USE_SABI ${SKBUILD_SABI_VERSION})
40
+ endif()
41
+
42
+ python_add_library(
43
+ _cext_gpu MODULE
44
+
45
+ ${USE_SABI} WITH_SOABI
46
+
47
+ # The .cu file is compiled by nvcc, the .cc file by the host compiler
48
+ shap_cuda/cext/_cext_gpu.cu
49
+ shap_cuda/cext/_cext_gpu.cc
50
+ )
51
+
52
+ execute_process(
53
+ COMMAND "${PYTHON_EXECUTABLE}"
54
+ -c "import numpy; print(numpy.get_include())"
55
+ OUTPUT_VARIABLE NUMPY_INCLUDE_DIR
56
+ OUTPUT_STRIP_TRAILING_WHITESPACE
57
+ )
58
+
59
+ target_include_directories(_cext_gpu PUBLIC ${NUMPY_INCLUDE_DIR})
60
+ target_link_libraries(_cext_gpu PRIVATE CUDA::cudart)
61
+
62
+ set_target_properties(_cext_gpu PROPERTIES
63
+ CUDA_ARCHITECTURES "60;70;75;80"
64
+ CUDA_STANDARD 14
65
+ CUDA_EXTENSIONS ON
66
+ )
67
+
68
+ target_compile_options(_cext_gpu PRIVATE
69
+ $<$<COMPILE_LANGUAGE:CUDA>:
70
+ --expt-extended-lambda
71
+ --expt-relaxed-constexpr
72
+ >
73
+ )
74
+
75
+ install(TARGETS _cext_gpu LIBRARY DESTINATION shap_cuda)
76
+ else()
77
+ message(STATUS "CUDA toolkit not found, skipping the _cext_gpu extension. "
78
+ "shap-cuda will install as Python-only; GPUTreeExplainer will "
79
+ "raise a clear error when actually used.")
80
+ endif()
@@ -0,0 +1,130 @@
1
+ Metadata-Version: 2.1
2
+ Name: shap-cuda
3
+ Version: 0.54.1.dev0
4
+ Summary: CUDA-accelerated GPUTreeExplainer backend for shap.
5
+ Author-Email: Scott Lundberg <slund1@cs.washington.edu>
6
+ License: MIT License
7
+ Classifier: Operating System :: POSIX
8
+ Classifier: Operating System :: Unix
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Programming Language :: Python :: 3.14
12
+ Classifier: Intended Audience :: Information Technology
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Topic :: Scientific/Engineering
15
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
16
+ Classifier: Development Status :: 4 - Beta
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Project-URL: Repository, http://github.com/shap/shap
19
+ Requires-Python: >=3.12
20
+ Requires-Dist: shap
21
+ Requires-Dist: numpy<2.5,>=2
22
+ Requires-Dist: packaging>20.9
23
+ Description-Content-Type: text/markdown
24
+
25
+ # shap-cuda
26
+
27
+ CUDA-accelerated `GPUTreeExplainer` backend for [shap](https://github.com/shap/shap).
28
+
29
+ Installing this package registers `GPUTreeExplainer` with `shap` via the
30
+ `shap.tree_backends` entry-point group; use it through `shap.GPUTreeExplainer`,
31
+ not by importing `shap_cuda` directly.
32
+
33
+ ## Build locally from source
34
+
35
+ Build both `shap` and `shap-cuda` from the same checkout: the backend uses SHAP
36
+ internals and checks that their release versions match. The commands below are
37
+ for Linux and run from the repository root, not this backend directory.
38
+
39
+ ### Prerequisites
40
+
41
+ - Python 3.12 or newer; Python 3.13 is used in the examples below.
42
+ - A C++ compiler and Python development headers (on Ubuntu/Debian, install
43
+ `build-essential` and the development package for your Python version).
44
+ - The NVIDIA CUDA toolkit, including `nvcc`. CI builds with CUDA 12.8; the
45
+ backend currently targets GPU architectures `60`, `70`, `75`, and `80`, so
46
+ use a toolkit that supports those targets.
47
+ - An NVIDIA GPU and a compatible NVIDIA driver to run explanations. Building
48
+ the extension does not require a physical GPU.
49
+
50
+ Check that the toolkit and driver are available:
51
+
52
+ ```bash
53
+ nvcc --version
54
+ nvidia-smi
55
+ ```
56
+
57
+ If the toolkit is installed outside your `PATH`, point the build at it. Adjust
58
+ this example to your installation:
59
+
60
+ ```bash
61
+ export PATH=/usr/local/cuda-12.8/bin:$PATH
62
+ export CUDACXX=/usr/local/cuda-12.8/bin/nvcc
63
+ ```
64
+
65
+ The build backend installs CMake (3.24 or newer) and its other Python build
66
+ dependencies in an isolated environment as needed. The separate CUDA backend
67
+ does not require the old `SHAP_ENABLE_CUDA` environment variable.
68
+
69
+ ### Install with uv
70
+
71
+ ```bash
72
+ uv venv --python 3.13
73
+ source .venv/bin/activate
74
+ uv sync --extra cuda
75
+ ```
76
+
77
+ The repository's uv workspace resolves the `cuda` extra to the local
78
+ `backends/shap-cuda` package and builds both packages as editable installs.
79
+
80
+ ### Install with pip
81
+
82
+ Alternatively, create and activate a virtual environment, then explicitly
83
+ install both local packages:
84
+
85
+ ```bash
86
+ python3.13 -m venv .venv
87
+ source .venv/bin/activate
88
+ python -m pip install --upgrade pip
89
+ python -m pip install -v -e . -e ./backends/shap-cuda
90
+ ```
91
+
92
+ Using `pip install -e '.[cuda]'` alone can resolve `shap-cuda` from a package
93
+ index instead of this checkout; pip does not use uv's workspace configuration.
94
+
95
+ ### Verify and use the backend
96
+
97
+ Confirm that the compiled extension loads and that SHAP discovers the backend:
98
+
99
+ ```bash
100
+ python -c "import shap; import shap_cuda._cext_gpu; print(shap.GPUTreeExplainer)"
101
+ ```
102
+
103
+ Importing the extension directly here is a build check. For explanations, use
104
+ the public SHAP API:
105
+
106
+ ```python
107
+ import numpy as np
108
+ import shap
109
+ from sklearn.tree import DecisionTreeRegressor
110
+
111
+ X = np.array([[0., 0.], [0., 1.], [1., 0.], [1., 1.]])
112
+ model = DecisionTreeRegressor(max_depth=2).fit(X, X[:, 0] + X[:, 1])
113
+ explainer = shap.GPUTreeExplainer(model)
114
+ values = explainer.shap_values(X)
115
+ print(values)
116
+ ```
117
+
118
+ This example also checks that GPU execution works. Importing the package alone
119
+ does not prove that the CUDA extension was built. In verbose build output,
120
+ look for `CUDA toolkit found, building the _cext_gpu extension.` If the
121
+ extension is missing or the build cannot find `nvcc`, check `CUDACXX` and the
122
+ toolkit installation, then rebuild:
123
+
124
+ ```bash
125
+ # uv
126
+ uv sync --extra cuda --reinstall-package shap-cuda
127
+
128
+ # Or pip; --no-deps keeps the existing local SHAP installation.
129
+ python -m pip install -v --no-cache-dir --force-reinstall --no-deps -e ./backends/shap-cuda
130
+ ```
@@ -0,0 +1,106 @@
1
+ # shap-cuda
2
+
3
+ CUDA-accelerated `GPUTreeExplainer` backend for [shap](https://github.com/shap/shap).
4
+
5
+ Installing this package registers `GPUTreeExplainer` with `shap` via the
6
+ `shap.tree_backends` entry-point group; use it through `shap.GPUTreeExplainer`,
7
+ not by importing `shap_cuda` directly.
8
+
9
+ ## Build locally from source
10
+
11
+ Build both `shap` and `shap-cuda` from the same checkout: the backend uses SHAP
12
+ internals and checks that their release versions match. The commands below are
13
+ for Linux and run from the repository root, not this backend directory.
14
+
15
+ ### Prerequisites
16
+
17
+ - Python 3.12 or newer; Python 3.13 is used in the examples below.
18
+ - A C++ compiler and Python development headers (on Ubuntu/Debian, install
19
+ `build-essential` and the development package for your Python version).
20
+ - The NVIDIA CUDA toolkit, including `nvcc`. CI builds with CUDA 12.8; the
21
+ backend currently targets GPU architectures `60`, `70`, `75`, and `80`, so
22
+ use a toolkit that supports those targets.
23
+ - An NVIDIA GPU and a compatible NVIDIA driver to run explanations. Building
24
+ the extension does not require a physical GPU.
25
+
26
+ Check that the toolkit and driver are available:
27
+
28
+ ```bash
29
+ nvcc --version
30
+ nvidia-smi
31
+ ```
32
+
33
+ If the toolkit is installed outside your `PATH`, point the build at it. Adjust
34
+ this example to your installation:
35
+
36
+ ```bash
37
+ export PATH=/usr/local/cuda-12.8/bin:$PATH
38
+ export CUDACXX=/usr/local/cuda-12.8/bin/nvcc
39
+ ```
40
+
41
+ The build backend installs CMake (3.24 or newer) and its other Python build
42
+ dependencies in an isolated environment as needed. The separate CUDA backend
43
+ does not require the old `SHAP_ENABLE_CUDA` environment variable.
44
+
45
+ ### Install with uv
46
+
47
+ ```bash
48
+ uv venv --python 3.13
49
+ source .venv/bin/activate
50
+ uv sync --extra cuda
51
+ ```
52
+
53
+ The repository's uv workspace resolves the `cuda` extra to the local
54
+ `backends/shap-cuda` package and builds both packages as editable installs.
55
+
56
+ ### Install with pip
57
+
58
+ Alternatively, create and activate a virtual environment, then explicitly
59
+ install both local packages:
60
+
61
+ ```bash
62
+ python3.13 -m venv .venv
63
+ source .venv/bin/activate
64
+ python -m pip install --upgrade pip
65
+ python -m pip install -v -e . -e ./backends/shap-cuda
66
+ ```
67
+
68
+ Using `pip install -e '.[cuda]'` alone can resolve `shap-cuda` from a package
69
+ index instead of this checkout; pip does not use uv's workspace configuration.
70
+
71
+ ### Verify and use the backend
72
+
73
+ Confirm that the compiled extension loads and that SHAP discovers the backend:
74
+
75
+ ```bash
76
+ python -c "import shap; import shap_cuda._cext_gpu; print(shap.GPUTreeExplainer)"
77
+ ```
78
+
79
+ Importing the extension directly here is a build check. For explanations, use
80
+ the public SHAP API:
81
+
82
+ ```python
83
+ import numpy as np
84
+ import shap
85
+ from sklearn.tree import DecisionTreeRegressor
86
+
87
+ X = np.array([[0., 0.], [0., 1.], [1., 0.], [1., 1.]])
88
+ model = DecisionTreeRegressor(max_depth=2).fit(X, X[:, 0] + X[:, 1])
89
+ explainer = shap.GPUTreeExplainer(model)
90
+ values = explainer.shap_values(X)
91
+ print(values)
92
+ ```
93
+
94
+ This example also checks that GPU execution works. Importing the package alone
95
+ does not prove that the CUDA extension was built. In verbose build output,
96
+ look for `CUDA toolkit found, building the _cext_gpu extension.` If the
97
+ extension is missing or the build cannot find `nvcc`, check `CUDACXX` and the
98
+ toolkit installation, then rebuild:
99
+
100
+ ```bash
101
+ # uv
102
+ uv sync --extra cuda --reinstall-package shap-cuda
103
+
104
+ # Or pip; --no-deps keeps the existing local SHAP installation.
105
+ python -m pip install -v --no-cache-dir --force-reinstall --no-deps -e ./backends/shap-cuda
106
+ ```
@@ -0,0 +1,38 @@
1
+ """PEP 517 build backend wrapping scikit-build-core.
2
+
3
+ shap_cuda/cext/tree_shap.h is a symlink into the sibling shap/cext/ dir (the
4
+ CPU and GPU extensions compile against the same header). scikit-build-core's
5
+ sdist packaging preserves symlinks as-is, which produces a tarball that's
6
+ broken once extracted outside this monorepo. build_sdist here swaps the
7
+ symlink for its resolved file content before delegating, then restores it.
8
+ """
9
+
10
+ import shutil
11
+ from pathlib import Path
12
+ from typing import Any
13
+
14
+ from scikit_build_core import build as _skbuild
15
+
16
+ _SYMLINKED_HEADERS: list[Path] = [Path(__file__).parent / "shap_cuda" / "cext" / "tree_shap.h"]
17
+
18
+
19
+ def __getattr__(name: str) -> Any:
20
+ # Every PEP 517 hook other than build_sdist delegates to scikit-build-core unmodified.
21
+ return getattr(_skbuild, name)
22
+
23
+
24
+ def build_sdist(sdist_directory: str, config_settings: dict[str, Any] | None = None) -> str:
25
+ materialized: list[tuple[Path, Path]] = []
26
+ try:
27
+ for header in _SYMLINKED_HEADERS:
28
+ if header.is_symlink():
29
+ resolved = header.resolve()
30
+ relative_target = Path("../../../../shap/cext") / header.name
31
+ header.unlink()
32
+ shutil.copyfile(resolved, header)
33
+ materialized.append((header, relative_target))
34
+ return _skbuild.build_sdist(sdist_directory, config_settings)
35
+ finally:
36
+ for header, relative_target in materialized:
37
+ header.unlink()
38
+ header.symlink_to(relative_target)
@@ -0,0 +1,86 @@
1
+ [build-system]
2
+ requires = [
3
+ "scikit-build-core>=0.10.0",
4
+ "setuptools-scm>=8.0",
5
+ "numpy>=2.0",
6
+ "packaging>20.9",
7
+ ]
8
+ build-backend = "_build_backend"
9
+ backend-path = ["."]
10
+
11
+ [project]
12
+ name = "shap-cuda"
13
+ description = "CUDA-accelerated GPUTreeExplainer backend for shap."
14
+ readme = "README.md"
15
+ license = {text = "MIT License"}
16
+ authors = [
17
+ {name = "Scott Lundberg", email = "slund1@cs.washington.edu"},
18
+ ]
19
+ requires-python = ">=3.12"
20
+ dependencies = [
21
+ "shap",
22
+ "numpy>=2,<2.5",
23
+ "packaging>20.9",
24
+ ]
25
+ classifiers = [
26
+ "Operating System :: POSIX",
27
+ "Operating System :: Unix",
28
+ "Programming Language :: Python :: 3.12",
29
+ "Programming Language :: Python :: 3.13",
30
+ "Programming Language :: Python :: 3.14",
31
+ "Intended Audience :: Information Technology",
32
+ "Intended Audience :: Science/Research",
33
+ "Topic :: Scientific/Engineering",
34
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
35
+ "Development Status :: 4 - Beta",
36
+ "License :: OSI Approved :: MIT License",
37
+ ]
38
+ dynamic = ["version"]
39
+
40
+ [project.entry-points."shap.tree_backends"]
41
+ cuda = "shap_cuda:GPUTreeExplainer"
42
+
43
+ [project.urls]
44
+ Repository = 'http://github.com/shap/shap'
45
+
46
+ [dependency-groups]
47
+ test = ["pytest", "pytest-mpl", "pytest-cov", "xgboost", "lightgbm", "matplotlib", "ipython"]
48
+
49
+ [tool.uv.sources]
50
+ shap = {workspace = true}
51
+
52
+ [tool.uv]
53
+ cache-keys = [
54
+ { file = "shap_cuda/cext/*.cc" },
55
+ { file = "shap_cuda/cext/*.cu" },
56
+ { file = "shap_cuda/cext/*.h" },
57
+ { file = "CMakeLists.txt" },
58
+ ]
59
+
60
+ [tool.setuptools_scm]
61
+ root = "../.."
62
+ version_file = "shap_cuda/_version.py"
63
+ local_scheme = "no-local-version"
64
+
65
+ [tool.scikit-build]
66
+ wheel.packages = ["shap_cuda"]
67
+
68
+ metadata.version.provider = "scikit_build_core.metadata.setuptools_scm"
69
+ sdist.include = ["shap_cuda/_version.py"]
70
+
71
+ minimum-version = "build-system.requires"
72
+ build-dir = "build/{wheel_tag}"
73
+
74
+ # Exclude C/C++/CUDA source files from the wheel (compiled .so is sufficient)
75
+ wheel.exclude = ["**/*.cc", "**/*.cpp", "**/*.h", "**/*.cu"]
76
+
77
+ wheel.py-api = "cp312"
78
+
79
+ [tool.ruff]
80
+ extend = "../../pyproject.toml"
81
+
82
+ [tool.pytest.ini_options]
83
+ addopts = "--mpl -m 'not xslow'"
84
+ mpl-default-style = "default"
85
+ testpaths = ["tests"]
86
+ markers = ["xslow: mark test as extremely slow (not run unless explicitly requested)"]
@@ -0,0 +1,8 @@
1
+ from ._gpu_tree import GPUTreeExplainer
2
+
3
+ try:
4
+ from ._version import version as __version__
5
+ except ImportError:
6
+ __version__ = "0.0.0-not-built"
7
+
8
+ __all__ = ["GPUTreeExplainer"]
@@ -0,0 +1,201 @@
1
+ """GPU accelerated tree explanations"""
2
+
3
+ import numpy as np
4
+ import shap
5
+ from packaging.version import parse as _parse_version
6
+ from shap.explainers._tree import (
7
+ TreeExplainer,
8
+ _xgboost_cat_unsupported,
9
+ feature_perturbation_codes,
10
+ output_transform_codes,
11
+ )
12
+ from shap.utils import assert_import, record_import_error
13
+
14
+ try:
15
+ from ._version import version as _shap_cuda_version
16
+ except ImportError:
17
+ _shap_cuda_version = "0.0.0-not-built"
18
+
19
+ try:
20
+ from . import _cext_gpu # type: ignore
21
+ except ImportError as e:
22
+ record_import_error("cext_gpu", "cuda extension was not built during install!", e)
23
+
24
+
25
+ def _check_versions_match() -> None:
26
+ shap_release = _parse_version(shap.__version__).release
27
+ shap_cuda_release = _parse_version(_shap_cuda_version).release
28
+ if shap_release != shap_cuda_release:
29
+ raise RuntimeError(
30
+ f"shap=={shap.__version__} and shap-cuda=={_shap_cuda_version} are from different "
31
+ "releases and are not guaranteed to be compatible. Reinstall matching versions, "
32
+ f"e.g. `pip install shap=={shap.__version__} shap-cuda=={shap.__version__}`."
33
+ )
34
+
35
+
36
+ class GPUTreeExplainer(TreeExplainer):
37
+ """Experimental GPU accelerated version of TreeExplainer. Currently requires source build with
38
+ cuda available and 'CUDA_PATH' environment variable defined.
39
+
40
+ Examples
41
+ --------
42
+ See `GPUTree explainer examples <https://shap.readthedocs.io/en/latest/example_notebooks/api_examples/explainers/GPUTree.html>`_
43
+
44
+ """
45
+
46
+ def __init__(self, *args, **kwargs):
47
+ _check_versions_match()
48
+ super().__init__(*args, **kwargs)
49
+
50
+ def shap_values(self, X, y=None, tree_limit=None, approximate=False, check_additivity=True, from_call=False):
51
+ """Estimate the SHAP values for a set of samples.
52
+
53
+ Parameters
54
+ ----------
55
+ X : numpy.array, pandas.DataFrame or catboost.Pool (for catboost)
56
+ A matrix of samples (# samples x # features) on which to explain the model's output.
57
+
58
+ y : numpy.array
59
+ An array of label values for each sample. Used when explaining loss functions.
60
+
61
+ tree_limit : None (default) or int
62
+ Limit the number of trees used by the model. By default None means no use the limit
63
+ of the
64
+ original model, and -1 means no limit.
65
+
66
+ approximate : bool
67
+ Not supported.
68
+
69
+ check_additivity : bool
70
+ Run a validation check that the sum of the SHAP values equals the output of the
71
+ model. This
72
+ check takes only a small amount of time, and will catch potential unforeseen errors.
73
+ Note that this check only runs right now when explaining the margin of the model.
74
+
75
+ Returns
76
+ -------
77
+ array or list
78
+ For models with a single output this returns a matrix of SHAP values
79
+ (# samples x # features). Each row sums to the difference between the model output
80
+ for that
81
+ sample and the expected value of the model output (which is stored in the expected_value
82
+ attribute of the explainer when it is constant). For models with vector outputs this
83
+ returns
84
+ a list of such matrices, one for each output.
85
+
86
+ """
87
+ assert not approximate, "approximate not supported"
88
+
89
+ X, y, X_missing, flat_output, tree_limit, check_additivity = self._validate_inputs(
90
+ X, y, tree_limit, check_additivity
91
+ )
92
+
93
+ model = self.model
94
+ _xgboost_cat_unsupported(model)
95
+ transform = model.get_transform()
96
+
97
+ # run the core algorithm using the C extension
98
+ assert_import("cext_gpu")
99
+ phi = np.zeros((X.shape[0], X.shape[1] + 1, self.model.num_outputs))
100
+ _cext_gpu.dense_tree_shap(
101
+ self.model.children_left,
102
+ self.model.children_right,
103
+ self.model.children_default,
104
+ self.model.features,
105
+ self.model.thresholds,
106
+ self.model.threshold_types,
107
+ self.model.values,
108
+ self.model.node_sample_weight,
109
+ self.model.max_depth,
110
+ X,
111
+ X_missing,
112
+ y,
113
+ self.data,
114
+ self.data_missing,
115
+ tree_limit,
116
+ self.model.base_offset,
117
+ phi,
118
+ feature_perturbation_codes[self.feature_perturbation],
119
+ output_transform_codes[transform],
120
+ False,
121
+ )
122
+
123
+ out = self._get_shap_output(phi, flat_output)
124
+ if check_additivity and self.model.model_output == "raw":
125
+ self.assert_additivity(out, self.model.predict(X)) # type: ignore[arg-type]
126
+
127
+ return out
128
+
129
+ def shap_interaction_values(self, X, y=None, tree_limit=None):
130
+ """Estimate the SHAP interaction values for a set of samples.
131
+
132
+ Parameters
133
+ ----------
134
+ X : numpy.array, pandas.DataFrame or catboost.Pool (for catboost)
135
+ A matrix of samples (# samples x # features) on which to explain the model's output.
136
+
137
+ y : numpy.array
138
+ An array of label values for each sample. Used when explaining loss functions (not
139
+ yet supported).
140
+
141
+ tree_limit : None (default) or int
142
+ Limit the number of trees used by the model. By default None means no use the limit
143
+ of the
144
+ original model, and -1 means no limit.
145
+
146
+ Returns
147
+ -------
148
+ array or list
149
+ For models with a single output this returns a tensor of SHAP values
150
+ (# samples x # features x # features). The matrix (# features x # features) for each
151
+ sample sums
152
+ to the difference between the model output for that sample and the expected value of
153
+ the model output
154
+ (which is stored in the expected_value attribute of the explainer). Each row of this
155
+ matrix sums to the
156
+ SHAP value for that feature for that sample. The diagonal entries of the matrix
157
+ represent the
158
+ "main effect" of that feature on the prediction and the symmetric off-diagonal
159
+ entries represent the
160
+ interaction effects between all pairs of features for that sample. For models with
161
+ vector outputs
162
+ this returns a list of tensors, one for each output.
163
+
164
+ """
165
+ if self.model.model_output != "raw":
166
+ raise ValueError('Only model_output = "raw" is supported for SHAP interaction values right now!')
167
+ if self.feature_perturbation == "interventional":
168
+ raise ValueError(
169
+ 'feature_perturbation="interventional" is not yet supported for interaction values. '
170
+ 'Use feature_perturbation="tree_path_dependent" instead.'
171
+ )
172
+ transform = "identity"
173
+
174
+ X, y, X_missing, flat_output, tree_limit, _ = self._validate_inputs(X, y, tree_limit, False)
175
+ # run the core algorithm using the C extension
176
+ assert_import("cext_gpu")
177
+ phi = np.zeros((X.shape[0], X.shape[1] + 1, X.shape[1] + 1, self.model.num_outputs))
178
+ _cext_gpu.dense_tree_shap(
179
+ self.model.children_left,
180
+ self.model.children_right,
181
+ self.model.children_default,
182
+ self.model.features,
183
+ self.model.thresholds,
184
+ self.model.threshold_types,
185
+ self.model.values,
186
+ self.model.node_sample_weight,
187
+ self.model.max_depth,
188
+ X,
189
+ X_missing,
190
+ y,
191
+ self.data,
192
+ self.data_missing,
193
+ tree_limit,
194
+ self.model.base_offset,
195
+ phi,
196
+ feature_perturbation_codes[self.feature_perturbation],
197
+ output_transform_codes[transform],
198
+ True,
199
+ )
200
+
201
+ return self._get_shap_interactions_output(phi, flat_output)
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '0.54.1.dev0'
22
+ __version_tuple__ = version_tuple = (0, 54, 1, 'dev0')
23
+
24
+ __commit_id__ = commit_id = 'g7d48b3044'