shapiq 1.2.3__tar.gz → 1.3.0__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.
- {shapiq-1.2.3 → shapiq-1.3.0}/CHANGELOG.md +33 -1
- {shapiq-1.2.3/shapiq.egg-info → shapiq-1.3.0}/PKG-INFO +72 -8
- {shapiq-1.2.3 → shapiq-1.3.0}/README.md +35 -6
- shapiq-1.3.0/pyproject.toml +245 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/__init__.py +14 -3
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/approximator/__init__.py +8 -3
- shapiq-1.2.3/shapiq/approximator/_base.py → shapiq-1.3.0/shapiq/approximator/base.py +139 -61
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/approximator/marginals/owen.py +58 -24
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/approximator/marginals/stratified.py +40 -14
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/approximator/montecarlo/__init__.py +1 -1
- shapiq-1.2.3/shapiq/approximator/montecarlo/_base.py → shapiq-1.3.0/shapiq/approximator/montecarlo/base.py +105 -64
- shapiq-1.3.0/shapiq/approximator/montecarlo/shapiq.py +165 -0
- shapiq-1.3.0/shapiq/approximator/montecarlo/svarmiq.py +124 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/approximator/permutation/sii.py +50 -18
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/approximator/permutation/stii.py +67 -28
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/approximator/permutation/sv.py +46 -8
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/approximator/regression/__init__.py +1 -1
- shapiq-1.2.3/shapiq/approximator/regression/_base.py → shapiq-1.3.0/shapiq/approximator/regression/base.py +138 -83
- shapiq-1.3.0/shapiq/approximator/regression/faithful.py +134 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/approximator/regression/kadd_shap.py +34 -15
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/approximator/regression/kernelshap.py +33 -15
- shapiq-1.3.0/shapiq/approximator/regression/kernelshapiq.py +157 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/approximator/sampling.py +128 -57
- shapiq-1.3.0/shapiq/approximator/sparse/__init__.py +9 -0
- shapiq-1.3.0/shapiq/approximator/sparse/base.py +303 -0
- shapiq-1.3.0/shapiq/approximator/sparse/spex.py +67 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/benchmark/__init__.py +0 -2
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/benchmark/configuration.py +29 -37
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/benchmark/load.py +41 -33
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/benchmark/metrics.py +29 -18
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/benchmark/plot.py +41 -31
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/benchmark/precompute.py +44 -51
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/benchmark/run.py +76 -61
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/datasets/_all.py +28 -16
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/explainer/__init__.py +3 -2
- shapiq-1.3.0/shapiq/explainer/agnostic.py +131 -0
- shapiq-1.3.0/shapiq/explainer/base.py +265 -0
- shapiq-1.3.0/shapiq/explainer/configuration.py +189 -0
- shapiq-1.3.0/shapiq/explainer/custom_types.py +7 -0
- shapiq-1.3.0/shapiq/explainer/tabpfn.py +159 -0
- shapiq-1.3.0/shapiq/explainer/tabular.py +209 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/explainer/tree/base.py +25 -22
- shapiq-1.3.0/shapiq/explainer/tree/conversion/__init__.py +1 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/explainer/tree/conversion/edges.py +39 -25
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/explainer/tree/conversion/lightgbm.py +15 -14
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/explainer/tree/conversion/sklearn.py +36 -18
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/explainer/tree/conversion/xgboost.py +21 -12
- shapiq-1.3.0/shapiq/explainer/tree/explainer.py +152 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/explainer/tree/treeshapiq.py +194 -105
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/explainer/tree/utils.py +7 -2
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/explainer/tree/validation.py +21 -8
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/explainer/utils.py +103 -43
- shapiq-1.3.0/shapiq/explainer/validation.py +137 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/game_theory/__init__.py +4 -2
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/game_theory/aggregation.py +16 -11
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/game_theory/core.py +26 -12
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/game_theory/exact.py +301 -174
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/game_theory/indices.py +57 -29
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/game_theory/moebius_converter.py +184 -124
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/__init__.py +0 -3
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/base.py +155 -71
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/__init__.py +1 -1
- shapiq-1.3.0/shapiq/games/benchmark/_setup/__init__.py +7 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/_setup/_california_torch_setup.py +30 -16
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/_setup/_resnet_setup.py +24 -15
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/_setup/_vit_setup.py +36 -24
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/data_valuation/__init__.py +0 -2
- shapiq-1.3.0/shapiq/games/benchmark/data_valuation/base.py +124 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/data_valuation/benchmark.py +48 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/dataset_valuation/__init__.py +0 -2
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/dataset_valuation/base.py +65 -33
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/dataset_valuation/benchmark.py +68 -30
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/ensemble_selection/__init__.py +0 -2
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/ensemble_selection/base.py +116 -58
- shapiq-1.3.0/shapiq/games/benchmark/ensemble_selection/benchmark.py +201 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/ensemble_selection/benchmark_random_forest.py +68 -36
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/feature_selection/__init__.py +0 -2
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/feature_selection/base.py +55 -31
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/feature_selection/benchmark.py +52 -32
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/global_xai/__init__.py +0 -2
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/global_xai/base.py +45 -23
- shapiq-1.3.0/shapiq/games/benchmark/global_xai/benchmark_tabular.py +194 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/local_xai/__init__.py +0 -2
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/local_xai/base.py +41 -22
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/local_xai/benchmark_image.py +70 -32
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/local_xai/benchmark_language.py +34 -28
- shapiq-1.3.0/shapiq/games/benchmark/local_xai/benchmark_tabular.py +213 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/setup.py +66 -41
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/synthetic/__init__.py +1 -3
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/synthetic/dummy.py +20 -13
- shapiq-1.2.3/shapiq/games/benchmark/synthetic/random.py → shapiq-1.3.0/shapiq/games/benchmark/synthetic/random_game.py +17 -4
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/synthetic/soum.py +93 -44
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/treeshapiq_xai/__init__.py +0 -2
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/treeshapiq_xai/base.py +67 -33
- shapiq-1.3.0/shapiq/games/benchmark/treeshapiq_xai/benchmark.py +270 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/uncertainty/__init__.py +0 -2
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/uncertainty/base.py +60 -11
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/uncertainty/benchmark.py +33 -7
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/unsupervised_cluster/__init__.py +0 -2
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/unsupervised_cluster/base.py +49 -18
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/unsupervised_cluster/benchmark.py +55 -24
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/unsupervised_data/__init__.py +0 -2
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/benchmark/unsupervised_data/base.py +31 -15
- shapiq-1.3.0/shapiq/games/benchmark/unsupervised_data/benchmark.py +76 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/imputer/base.py +56 -28
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/imputer/baseline_imputer.py +48 -21
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/imputer/conditional_imputer.py +73 -37
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/imputer/marginal_imputer.py +55 -25
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/imputer/tabpfn_imputer.py +61 -29
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/interaction_values.py +208 -130
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/plot/__init__.py +1 -1
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/plot/_config.py +4 -1
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/plot/bar.py +13 -2
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/plot/force.py +88 -50
- shapiq-1.3.0/shapiq/plot/network.py +70 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/plot/sentence.py +15 -8
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/plot/si_graph.py +486 -242
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/plot/stacked_bar.py +21 -16
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/plot/upset.py +25 -9
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/plot/utils.py +62 -8
- shapiq-1.2.3/shapiq/plot/watefall.py → shapiq-1.3.0/shapiq/plot/waterfall.py +54 -21
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/utils/__init__.py +3 -1
- shapiq-1.3.0/shapiq/utils/custom_types.py +30 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/utils/datasets.py +6 -1
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/utils/modules.py +23 -16
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/utils/sets.py +67 -23
- {shapiq-1.2.3 → shapiq-1.3.0/shapiq.egg-info}/PKG-INFO +72 -8
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq.egg-info/SOURCES.txt +15 -11
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq.egg-info/requires.txt +3 -0
- shapiq-1.2.3/pyproject.toml +0 -121
- shapiq-1.2.3/shapiq/approximator/montecarlo/shapiq.py +0 -130
- shapiq-1.2.3/shapiq/approximator/montecarlo/svarmiq.py +0 -89
- shapiq-1.2.3/shapiq/approximator/regression/faithful.py +0 -97
- shapiq-1.2.3/shapiq/approximator/regression/kernelshapiq.py +0 -132
- shapiq-1.2.3/shapiq/explainer/_base.py +0 -153
- shapiq-1.2.3/shapiq/explainer/tabpfn.py +0 -129
- shapiq-1.2.3/shapiq/explainer/tabular.py +0 -291
- shapiq-1.2.3/shapiq/explainer/tree/conversion/__init__.py +0 -0
- shapiq-1.2.3/shapiq/explainer/tree/explainer.py +0 -125
- shapiq-1.2.3/shapiq/games/benchmark/_setup/__init__.py +0 -4
- shapiq-1.2.3/shapiq/games/benchmark/data_valuation/base.py +0 -92
- shapiq-1.2.3/shapiq/games/benchmark/ensemble_selection/benchmark.py +0 -166
- shapiq-1.2.3/shapiq/games/benchmark/global_xai/benchmark_tabular.py +0 -157
- shapiq-1.2.3/shapiq/games/benchmark/local_xai/benchmark_tabular.py +0 -171
- shapiq-1.2.3/shapiq/games/benchmark/treeshapiq_xai/benchmark.py +0 -216
- shapiq-1.2.3/shapiq/games/benchmark/unsupervised_data/benchmark.py +0 -37
- shapiq-1.2.3/shapiq/plot/network.py +0 -382
- shapiq-1.2.3/shapiq/utils/types.py +0 -6
- shapiq-1.2.3/tests/test_base_interaction_values.py +0 -774
- shapiq-1.2.3/tests/test_configuration.py +0 -17
- shapiq-1.2.3/tests/test_integration_import_all.py +0 -60
- {shapiq-1.2.3 → shapiq-1.3.0}/LICENSE +0 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/setup.cfg +0 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/approximator/marginals/__init__.py +0 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/approximator/permutation/__init__.py +0 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/datasets/__init__.py +0 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/explainer/tree/__init__.py +0 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq/games/imputer/__init__.py +0 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq.egg-info/dependency_links.txt +0 -0
- {shapiq-1.2.3 → shapiq-1.3.0}/shapiq.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,38 @@
|
|
|
1
1
|
## Changelog
|
|
2
2
|
|
|
3
|
-
###
|
|
3
|
+
### v1.3.0 (2025-06-17)
|
|
4
|
+
|
|
5
|
+
#### Highlights
|
|
6
|
+
- `shapiq.SPEX` (Sparse Exact) approximator for efficient computation of sparse interaction values for really large models and games. Paper: [SPEX: Scaling Feature Interaction Explanations for LLMs](https://arxiv.org/abs/2502.13870)
|
|
7
|
+
- `shapiq.AgnosticExplainer` a generic explainer that works for any value function or `shapiq.Game` object, allowing for more flexibility in explainers.
|
|
8
|
+
- prettier graph-based plots via `shapiq.si_graph_plot()` and `shapiq.network_plot()`, which now use the same backend for more flexibility and easier maintenance.
|
|
9
|
+
|
|
10
|
+
#### New Features
|
|
11
|
+
- adds the SPEX (Sparse Exact) module in `approximator.sparse` for efficient computation of sparse interaction values [#379](https://github.com/mmschlk/shapiq/pull/379)
|
|
12
|
+
- adds `shapiq.AgnosticExplainer` which is a generic explainer that can be used for any value function or `shapiq.Game` object. This allows for more flexibility in the explainers. [#100](https://github.com/mmschlk/shapiq/issues/100), [#395](https://github.com/mmschlk/shapiq/pull/395)
|
|
13
|
+
- changes `budget` to be a mandatory parameter given to the `TabularExplainer.explain()` method [#355](https://github.com/mmschlk/shapiq/pull/356)
|
|
14
|
+
- changes logic of `InteractionValues.get_n_order()` function to be callable with **either** the `order: int` parameter and optional assignment of `min_order: int` and `max_order: int` parameters **or** with the min/max order parameters [#372](https://github.com/mmschlk/shapiq/pull/372)
|
|
15
|
+
- renamed `min_percentage` parameter in the force plot to `contribution_threshold` to better reflect its purpose [#391](https://github.com/mmschlk/shapiq/pull/391)
|
|
16
|
+
- adds ``verbose`` parameter to the ``Explainer``'s ``explain_X()`` method to control weather a progress bar is shown or not which is defaulted to ``False``. [#391](https://github.com/mmschlk/shapiq/pull/391)
|
|
17
|
+
- made `InteractionValues.get_n_order()` and `InteractionValues.get_n_order_values()` function more efficient by iterating over the stored interactions and not over the powerset of all potential interactions, which made the function not usable for higher player counts (models with many features, and results obtained from `TreeExplainer`). Note, this change does not really help `get_n_order_values()` as it still needs to create a numpy array of shape `n_players` times `order` [#372](https://github.com/mmschlk/shapiq/pull/372)
|
|
18
|
+
- streamlined the ``network_plot()`` plot function to use the ``si_graph_plot()`` as its backend function. This allows for more flexibility in the plot function and makes it easier to use the same code for different purposes. In addition, the ``si_graph_plot`` was modified to make plotting more easy and allow for more flexibility with new parameters. [#349](https://github.com/mmschlk/shapiq/pull/349)
|
|
19
|
+
- adds `Game.compute()` method to the `shapiq.Game` class to compute game values without changing the state of the game object. The compute method also introduces a `shapiq.utils.sets.generate_interaction_lookup_from_coalitions()` utility method which creates an interaction lookup dict from an array of coalitions. [#397](https://github.com/mmschlk/shapiq/pull/397)
|
|
20
|
+
- streamlines the creation of network plots and graph plots which now uses the same backend. The network plot via `shapiq.network_plot()` or `InteractionValues.plot_network()` is now a special case of the `shapiq.si_graph_plot()` and `InteractionValues.plot_si_graph()`. This allows to create more beautiful plots and easier maintenance in the future. [#349](https://github.com/mmschlk/shapiq/pull/349)
|
|
21
|
+
|
|
22
|
+
#### Testing, Code-Quality and Documentation
|
|
23
|
+
- activates ``"ALL"`` rules in ``ruff-format`` configuration to enforce stricter code quality checks and addressed around 500 (not automatically solvable) issues in the code base. [#391](https://github.com/mmschlk/shapiq/pull/391)
|
|
24
|
+
- improved the testing environment by adding a new fixture module containing mock `InteractionValues` objects to be used in the tests. This allows for more efficient and cleaner tests, as well as easier debugging of the tests [#372](https://github.com/mmschlk/shapiq/pull/372)
|
|
25
|
+
- removed check and error message if the ``index`` parameter is not in the list of available indices in the ``TabularExplainer`` since the type hints were replaced by Literals [#391](https://github.com/mmschlk/shapiq/pull/391)
|
|
26
|
+
- removed multiple instances where ``shapiq`` tests if some approximators/explainers can be instantiated with certain indices or not in favor of using Literals in the ``__init__`` method of the approximator classes. This allows for better type hinting and IDE support, as well as cleaner code. [#391](https://github.com/mmschlk/shapiq/pull/391)
|
|
27
|
+
- Added documentation for all public modules, classes, and functions in the code base to improve the documentation quality and make it easier to understand how to use the package. [#391](https://github.com/mmschlk/shapiq/pull/391)
|
|
28
|
+
- suppress a ``RuntimeWarning`` in ``Regression`` approximators ``solve_regression()``method when the solver is not able to find good interim solutions for the regression problem.
|
|
29
|
+
- refactors the tests into ``tests_unit/`` and ``tests_integration/`` to better separate unit tests from integration tests. [#395](https://github.com/mmschlk/shapiq/pull/395)
|
|
30
|
+
- adds new integration tests in ``tests/tests_integration/test_explainer_california_housing`` which compares the different explainers against ground-truth interaction values computed by ``shapiq.ExactComputer`` and interaction values stored on [disk](https://github.com/mmschlk/shapiq/tree/main/tests/data/interaction_values/california_housing) as a form of regression test. This test should help finding bugs in the future when the approximators, explainers, or exact computation are changed. [#395](https://github.com/mmschlk/shapiq/pull/395)
|
|
31
|
+
|
|
32
|
+
#### Bug Fixes
|
|
33
|
+
- fixed a bug in the `shapiq.waterfall_plot` function that caused the plot to not display correctly resulting in cutoff y_ticks. Additionally, the file was renamed from `watefall.py` to `waterfall.py` to match the function name [#377](https://github.com/mmschlk/shapiq/pull/377)
|
|
34
|
+
- fixes a bug with `TabPFNExplainer`, where the model was not able to be used for predictions after it was explained. This was due to the model being fitted on a subset of features, which caused inconsistencies in the model's predictions after explanation. The fix includes that after each call to the `TabPFNImputer.value_function`, the tabpfn model is fitted on the whole dataset (without omitting features). This means that the original model can be used for predictions after it has been explained. [#396](https://github.com/mmschlk/shapiq/issues/396).
|
|
35
|
+
- fixed a bug in computing `BII` or `BV` indices with `shapiq.approximator.MonteCarlo` approximators (affecting `SHAP-IQ`, `SVARM` and `SVARM-IQ`). All orders of BII should now be computed correctly. [#395](https://github.com/mmschlk/shapiq/pull/395)
|
|
4
36
|
|
|
5
37
|
### v1.2.3 (2025-03-24)
|
|
6
38
|
- substantially improves the runtime of all `Regression` approximators by a) a faster pre-computation of the regression matrices and b) a faster computation of the weighted least squares regression [#340](https://github.com/mmschlk/shapiq/issues/340)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: shapiq
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Shapley Interactions for Machine Learning
|
|
5
5
|
Author: Hubert Baniecki, Fabian Fumagalli
|
|
6
6
|
Author-email: Maximilian Muschalik <Maximilian.Muschalik@lmu.de>
|
|
@@ -33,9 +33,12 @@ Requires-Dist: pandas
|
|
|
33
33
|
Requires-Dist: scikit-learn
|
|
34
34
|
Requires-Dist: tqdm
|
|
35
35
|
Requires-Dist: requests
|
|
36
|
+
Requires-Dist: sparse-transform
|
|
37
|
+
Requires-Dist: galois
|
|
36
38
|
Requires-Dist: matplotlib
|
|
37
39
|
Requires-Dist: networkx
|
|
38
40
|
Requires-Dist: colour
|
|
41
|
+
Requires-Dist: pillow
|
|
39
42
|
Provides-Extra: ml
|
|
40
43
|
Requires-Dist: tabpfn; extra == "ml"
|
|
41
44
|
Requires-Dist: torchvision; extra == "ml"
|
|
@@ -62,15 +65,21 @@ Dynamic: license-file
|
|
|
62
65
|
[](https://pepy.tech/project/shapiq)
|
|
63
66
|
|
|
64
67
|
[](https://github.com/psf/black)
|
|
65
|
-

|
|
66
|
-

|
|
68
|
+
[](https://github.com/mmschlk/shapiq/issues)
|
|
69
|
+
[](https://github.com/mmschlk/shapiq/commits/main)
|
|
67
70
|
|
|
68
71
|
> An interaction may speak more than a thousand main effects.
|
|
69
72
|
|
|
70
73
|
Shapley Interaction Quantification (`shapiq`) is a Python package for (1) approximating any-order Shapley interactions, (2) benchmarking game-theoretical algorithms for machine learning, (3) explaining feature interactions of model predictions. `shapiq` extends the well-known [shap](https://github.com/shap/shap) package for both researchers working on game theory in machine learning, as well as the end-users explaining models. SHAP-IQ extends individual Shapley values by quantifying the **synergy** effect between entities (aka **players** in the jargon of game theory) like explanatory features, data points, or weak learners in ensemble models. Synergies between players give a more comprehensive view of machine learning models.
|
|
71
74
|
|
|
72
75
|
## 🛠️ Install
|
|
73
|
-
`shapiq` is intended to work with **Python 3.10 and above**.
|
|
76
|
+
`shapiq` is intended to work with **Python 3.10 and above**.
|
|
77
|
+
Installation can be done via `uv` :
|
|
78
|
+
```sh
|
|
79
|
+
uv add shapiq
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
or via `pip`:
|
|
74
83
|
|
|
75
84
|
```sh
|
|
76
85
|
pip install shapiq
|
|
@@ -84,6 +93,7 @@ If you are interested in the underlying game theoretic algorithms, then check ou
|
|
|
84
93
|
### Compute any-order feature interactions
|
|
85
94
|
|
|
86
95
|
Explain your models with Shapley interactions:
|
|
96
|
+
Just load your data and model, and then use a `shapiq.Explainer` to compute Shapley interactions.
|
|
87
97
|
|
|
88
98
|
```python
|
|
89
99
|
import shapiq
|
|
@@ -182,7 +192,7 @@ The pseudo-code above can produce the following plot (here also an image is adde
|
|
|
182
192
|
|
|
183
193
|
### Explain TabPFN
|
|
184
194
|
|
|
185
|
-
With ``shapiq`` you can also [``TabPFN``](https://github.com/PriorLabs/TabPFN) by making use of the _remove-and-recontextualize_ explanation paradigm implemented in ``shapiq.TabPFNExplainer``.
|
|
195
|
+
With ``shapiq`` you can also explain [``TabPFN``](https://github.com/PriorLabs/TabPFN) by making use of the _remove-and-recontextualize_ explanation paradigm implemented in ``shapiq.TabPFNExplainer``.
|
|
186
196
|
|
|
187
197
|
```python
|
|
188
198
|
import tabpfn, shapiq
|
|
@@ -195,7 +205,7 @@ explainer = shapiq.TabPFNExplainer( # setup the explainer
|
|
|
195
205
|
labels=labels,
|
|
196
206
|
index="FSII"
|
|
197
207
|
)
|
|
198
|
-
fsii_values = explainer.explain(
|
|
208
|
+
fsii_values = explainer.explain(data[0]) # explain with Faithful Shapley values
|
|
199
209
|
fsii_values.plot_force() # plot the force plot
|
|
200
210
|
```
|
|
201
211
|
|
|
@@ -203,6 +213,28 @@ fsii_values.plot_force() # plot the force plot
|
|
|
203
213
|
<img width="800px" src="https://raw.githubusercontent.com/mmschlk/shapiq/main/docs/source/_static/images/fsii_tabpfn_force_plot_example.png" alt="Force Plot of FSII values as derived from the example tabpfn notebook">
|
|
204
214
|
</p>
|
|
205
215
|
|
|
216
|
+
### Use SPEX (SParse EXplainer) <img src="https://raw.githubusercontent.com/mmschlk/shapiq/main/docs/source/_static/images/spex_logo.png" alt="spex_logo" align="right" height="75px"/>
|
|
217
|
+
For large-scale use-cases you can also check out the [👓``SPEX``](https://shapiq.readthedocs.io/en/latest/api/shapiq.approximator.sparse.html#shapiq.approximator.sparse.SPEX) approximator.
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
# load your data and model with large number of features
|
|
221
|
+
data, model, n_features = ...
|
|
222
|
+
|
|
223
|
+
# use the SPEX approximator directly
|
|
224
|
+
approximator = shapiq.SPEX(n=n_features, index="FBII", max_order=2)
|
|
225
|
+
fbii_scores = approximator.approximate(budget=2000, game=model.predict)
|
|
226
|
+
|
|
227
|
+
# or use SPEX with an explainer
|
|
228
|
+
explainer = shapiq.Explainer(
|
|
229
|
+
model=model,
|
|
230
|
+
data=data,
|
|
231
|
+
index="FBII",
|
|
232
|
+
max_order=2,
|
|
233
|
+
approximator="spex" # specify SPEX as approximator
|
|
234
|
+
)
|
|
235
|
+
explanation = explainer.explain(data[0])
|
|
236
|
+
```
|
|
237
|
+
|
|
206
238
|
|
|
207
239
|
## 📖 Documentation with tutorials
|
|
208
240
|
The documentation of ``shapiq`` can be found at https://shapiq.readthedocs.io.
|
|
@@ -214,7 +246,7 @@ There is a lot of great resources available to get you started with Shapley valu
|
|
|
214
246
|
If you use ``shapiq`` and enjoy it, please consider citing our [NeurIPS paper](https://arxiv.org/abs/2410.01649) or consider starring this repository.
|
|
215
247
|
|
|
216
248
|
```bibtex
|
|
217
|
-
@inproceedings{
|
|
249
|
+
@inproceedings{Muschalik.2024b,
|
|
218
250
|
title = {shapiq: Shapley Interactions for Machine Learning},
|
|
219
251
|
author = {Maximilian Muschalik and Hubert Baniecki and Fabian Fumagalli and
|
|
220
252
|
Patrick Kolpaczki and Barbara Hammer and Eyke H\"{u}llermeier},
|
|
@@ -243,7 +275,39 @@ Built with ❤️ by the shapiq team.
|
|
|
243
275
|
|
|
244
276
|
## Changelog
|
|
245
277
|
|
|
246
|
-
###
|
|
278
|
+
### v1.3.0 (2025-06-17)
|
|
279
|
+
|
|
280
|
+
#### Highlights
|
|
281
|
+
- `shapiq.SPEX` (Sparse Exact) approximator for efficient computation of sparse interaction values for really large models and games. Paper: [SPEX: Scaling Feature Interaction Explanations for LLMs](https://arxiv.org/abs/2502.13870)
|
|
282
|
+
- `shapiq.AgnosticExplainer` a generic explainer that works for any value function or `shapiq.Game` object, allowing for more flexibility in explainers.
|
|
283
|
+
- prettier graph-based plots via `shapiq.si_graph_plot()` and `shapiq.network_plot()`, which now use the same backend for more flexibility and easier maintenance.
|
|
284
|
+
|
|
285
|
+
#### New Features
|
|
286
|
+
- adds the SPEX (Sparse Exact) module in `approximator.sparse` for efficient computation of sparse interaction values [#379](https://github.com/mmschlk/shapiq/pull/379)
|
|
287
|
+
- adds `shapiq.AgnosticExplainer` which is a generic explainer that can be used for any value function or `shapiq.Game` object. This allows for more flexibility in the explainers. [#100](https://github.com/mmschlk/shapiq/issues/100), [#395](https://github.com/mmschlk/shapiq/pull/395)
|
|
288
|
+
- changes `budget` to be a mandatory parameter given to the `TabularExplainer.explain()` method [#355](https://github.com/mmschlk/shapiq/pull/356)
|
|
289
|
+
- changes logic of `InteractionValues.get_n_order()` function to be callable with **either** the `order: int` parameter and optional assignment of `min_order: int` and `max_order: int` parameters **or** with the min/max order parameters [#372](https://github.com/mmschlk/shapiq/pull/372)
|
|
290
|
+
- renamed `min_percentage` parameter in the force plot to `contribution_threshold` to better reflect its purpose [#391](https://github.com/mmschlk/shapiq/pull/391)
|
|
291
|
+
- adds ``verbose`` parameter to the ``Explainer``'s ``explain_X()`` method to control weather a progress bar is shown or not which is defaulted to ``False``. [#391](https://github.com/mmschlk/shapiq/pull/391)
|
|
292
|
+
- made `InteractionValues.get_n_order()` and `InteractionValues.get_n_order_values()` function more efficient by iterating over the stored interactions and not over the powerset of all potential interactions, which made the function not usable for higher player counts (models with many features, and results obtained from `TreeExplainer`). Note, this change does not really help `get_n_order_values()` as it still needs to create a numpy array of shape `n_players` times `order` [#372](https://github.com/mmschlk/shapiq/pull/372)
|
|
293
|
+
- streamlined the ``network_plot()`` plot function to use the ``si_graph_plot()`` as its backend function. This allows for more flexibility in the plot function and makes it easier to use the same code for different purposes. In addition, the ``si_graph_plot`` was modified to make plotting more easy and allow for more flexibility with new parameters. [#349](https://github.com/mmschlk/shapiq/pull/349)
|
|
294
|
+
- adds `Game.compute()` method to the `shapiq.Game` class to compute game values without changing the state of the game object. The compute method also introduces a `shapiq.utils.sets.generate_interaction_lookup_from_coalitions()` utility method which creates an interaction lookup dict from an array of coalitions. [#397](https://github.com/mmschlk/shapiq/pull/397)
|
|
295
|
+
- streamlines the creation of network plots and graph plots which now uses the same backend. The network plot via `shapiq.network_plot()` or `InteractionValues.plot_network()` is now a special case of the `shapiq.si_graph_plot()` and `InteractionValues.plot_si_graph()`. This allows to create more beautiful plots and easier maintenance in the future. [#349](https://github.com/mmschlk/shapiq/pull/349)
|
|
296
|
+
|
|
297
|
+
#### Testing, Code-Quality and Documentation
|
|
298
|
+
- activates ``"ALL"`` rules in ``ruff-format`` configuration to enforce stricter code quality checks and addressed around 500 (not automatically solvable) issues in the code base. [#391](https://github.com/mmschlk/shapiq/pull/391)
|
|
299
|
+
- improved the testing environment by adding a new fixture module containing mock `InteractionValues` objects to be used in the tests. This allows for more efficient and cleaner tests, as well as easier debugging of the tests [#372](https://github.com/mmschlk/shapiq/pull/372)
|
|
300
|
+
- removed check and error message if the ``index`` parameter is not in the list of available indices in the ``TabularExplainer`` since the type hints were replaced by Literals [#391](https://github.com/mmschlk/shapiq/pull/391)
|
|
301
|
+
- removed multiple instances where ``shapiq`` tests if some approximators/explainers can be instantiated with certain indices or not in favor of using Literals in the ``__init__`` method of the approximator classes. This allows for better type hinting and IDE support, as well as cleaner code. [#391](https://github.com/mmschlk/shapiq/pull/391)
|
|
302
|
+
- Added documentation for all public modules, classes, and functions in the code base to improve the documentation quality and make it easier to understand how to use the package. [#391](https://github.com/mmschlk/shapiq/pull/391)
|
|
303
|
+
- suppress a ``RuntimeWarning`` in ``Regression`` approximators ``solve_regression()``method when the solver is not able to find good interim solutions for the regression problem.
|
|
304
|
+
- refactors the tests into ``tests_unit/`` and ``tests_integration/`` to better separate unit tests from integration tests. [#395](https://github.com/mmschlk/shapiq/pull/395)
|
|
305
|
+
- adds new integration tests in ``tests/tests_integration/test_explainer_california_housing`` which compares the different explainers against ground-truth interaction values computed by ``shapiq.ExactComputer`` and interaction values stored on [disk](https://github.com/mmschlk/shapiq/tree/main/tests/data/interaction_values/california_housing) as a form of regression test. This test should help finding bugs in the future when the approximators, explainers, or exact computation are changed. [#395](https://github.com/mmschlk/shapiq/pull/395)
|
|
306
|
+
|
|
307
|
+
#### Bug Fixes
|
|
308
|
+
- fixed a bug in the `shapiq.waterfall_plot` function that caused the plot to not display correctly resulting in cutoff y_ticks. Additionally, the file was renamed from `watefall.py` to `waterfall.py` to match the function name [#377](https://github.com/mmschlk/shapiq/pull/377)
|
|
309
|
+
- fixes a bug with `TabPFNExplainer`, where the model was not able to be used for predictions after it was explained. This was due to the model being fitted on a subset of features, which caused inconsistencies in the model's predictions after explanation. The fix includes that after each call to the `TabPFNImputer.value_function`, the tabpfn model is fitted on the whole dataset (without omitting features). This means that the original model can be used for predictions after it has been explained. [#396](https://github.com/mmschlk/shapiq/issues/396).
|
|
310
|
+
- fixed a bug in computing `BII` or `BV` indices with `shapiq.approximator.MonteCarlo` approximators (affecting `SHAP-IQ`, `SVARM` and `SVARM-IQ`). All orders of BII should now be computed correctly. [#395](https://github.com/mmschlk/shapiq/pull/395)
|
|
247
311
|
|
|
248
312
|
### v1.2.3 (2025-03-24)
|
|
249
313
|
- substantially improves the runtime of all `Regression` approximators by a) a faster pre-computation of the regression matrices and b) a faster computation of the weighted least squares regression [#340](https://github.com/mmschlk/shapiq/issues/340)
|
|
@@ -11,15 +11,21 @@
|
|
|
11
11
|
[](https://pepy.tech/project/shapiq)
|
|
12
12
|
|
|
13
13
|
[](https://github.com/psf/black)
|
|
14
|
-

|
|
15
|
-

|
|
14
|
+
[](https://github.com/mmschlk/shapiq/issues)
|
|
15
|
+
[](https://github.com/mmschlk/shapiq/commits/main)
|
|
16
16
|
|
|
17
17
|
> An interaction may speak more than a thousand main effects.
|
|
18
18
|
|
|
19
19
|
Shapley Interaction Quantification (`shapiq`) is a Python package for (1) approximating any-order Shapley interactions, (2) benchmarking game-theoretical algorithms for machine learning, (3) explaining feature interactions of model predictions. `shapiq` extends the well-known [shap](https://github.com/shap/shap) package for both researchers working on game theory in machine learning, as well as the end-users explaining models. SHAP-IQ extends individual Shapley values by quantifying the **synergy** effect between entities (aka **players** in the jargon of game theory) like explanatory features, data points, or weak learners in ensemble models. Synergies between players give a more comprehensive view of machine learning models.
|
|
20
20
|
|
|
21
21
|
## 🛠️ Install
|
|
22
|
-
`shapiq` is intended to work with **Python 3.10 and above**.
|
|
22
|
+
`shapiq` is intended to work with **Python 3.10 and above**.
|
|
23
|
+
Installation can be done via `uv` :
|
|
24
|
+
```sh
|
|
25
|
+
uv add shapiq
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
or via `pip`:
|
|
23
29
|
|
|
24
30
|
```sh
|
|
25
31
|
pip install shapiq
|
|
@@ -33,6 +39,7 @@ If you are interested in the underlying game theoretic algorithms, then check ou
|
|
|
33
39
|
### Compute any-order feature interactions
|
|
34
40
|
|
|
35
41
|
Explain your models with Shapley interactions:
|
|
42
|
+
Just load your data and model, and then use a `shapiq.Explainer` to compute Shapley interactions.
|
|
36
43
|
|
|
37
44
|
```python
|
|
38
45
|
import shapiq
|
|
@@ -131,7 +138,7 @@ The pseudo-code above can produce the following plot (here also an image is adde
|
|
|
131
138
|
|
|
132
139
|
### Explain TabPFN
|
|
133
140
|
|
|
134
|
-
With ``shapiq`` you can also [``TabPFN``](https://github.com/PriorLabs/TabPFN) by making use of the _remove-and-recontextualize_ explanation paradigm implemented in ``shapiq.TabPFNExplainer``.
|
|
141
|
+
With ``shapiq`` you can also explain [``TabPFN``](https://github.com/PriorLabs/TabPFN) by making use of the _remove-and-recontextualize_ explanation paradigm implemented in ``shapiq.TabPFNExplainer``.
|
|
135
142
|
|
|
136
143
|
```python
|
|
137
144
|
import tabpfn, shapiq
|
|
@@ -144,7 +151,7 @@ explainer = shapiq.TabPFNExplainer( # setup the explainer
|
|
|
144
151
|
labels=labels,
|
|
145
152
|
index="FSII"
|
|
146
153
|
)
|
|
147
|
-
fsii_values = explainer.explain(
|
|
154
|
+
fsii_values = explainer.explain(data[0]) # explain with Faithful Shapley values
|
|
148
155
|
fsii_values.plot_force() # plot the force plot
|
|
149
156
|
```
|
|
150
157
|
|
|
@@ -152,6 +159,28 @@ fsii_values.plot_force() # plot the force plot
|
|
|
152
159
|
<img width="800px" src="https://raw.githubusercontent.com/mmschlk/shapiq/main/docs/source/_static/images/fsii_tabpfn_force_plot_example.png" alt="Force Plot of FSII values as derived from the example tabpfn notebook">
|
|
153
160
|
</p>
|
|
154
161
|
|
|
162
|
+
### Use SPEX (SParse EXplainer) <img src="https://raw.githubusercontent.com/mmschlk/shapiq/main/docs/source/_static/images/spex_logo.png" alt="spex_logo" align="right" height="75px"/>
|
|
163
|
+
For large-scale use-cases you can also check out the [👓``SPEX``](https://shapiq.readthedocs.io/en/latest/api/shapiq.approximator.sparse.html#shapiq.approximator.sparse.SPEX) approximator.
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
# load your data and model with large number of features
|
|
167
|
+
data, model, n_features = ...
|
|
168
|
+
|
|
169
|
+
# use the SPEX approximator directly
|
|
170
|
+
approximator = shapiq.SPEX(n=n_features, index="FBII", max_order=2)
|
|
171
|
+
fbii_scores = approximator.approximate(budget=2000, game=model.predict)
|
|
172
|
+
|
|
173
|
+
# or use SPEX with an explainer
|
|
174
|
+
explainer = shapiq.Explainer(
|
|
175
|
+
model=model,
|
|
176
|
+
data=data,
|
|
177
|
+
index="FBII",
|
|
178
|
+
max_order=2,
|
|
179
|
+
approximator="spex" # specify SPEX as approximator
|
|
180
|
+
)
|
|
181
|
+
explanation = explainer.explain(data[0])
|
|
182
|
+
```
|
|
183
|
+
|
|
155
184
|
|
|
156
185
|
## 📖 Documentation with tutorials
|
|
157
186
|
The documentation of ``shapiq`` can be found at https://shapiq.readthedocs.io.
|
|
@@ -163,7 +192,7 @@ There is a lot of great resources available to get you started with Shapley valu
|
|
|
163
192
|
If you use ``shapiq`` and enjoy it, please consider citing our [NeurIPS paper](https://arxiv.org/abs/2410.01649) or consider starring this repository.
|
|
164
193
|
|
|
165
194
|
```bibtex
|
|
166
|
-
@inproceedings{
|
|
195
|
+
@inproceedings{Muschalik.2024b,
|
|
167
196
|
title = {shapiq: Shapley Interactions for Machine Learning},
|
|
168
197
|
author = {Maximilian Muschalik and Hubert Baniecki and Fabian Fumagalli and
|
|
169
198
|
Patrick Kolpaczki and Barbara Hammer and Eyke H\"{u}llermeier},
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "shapiq"
|
|
7
|
+
dynamic = ["version", "readme"]
|
|
8
|
+
description = "Shapley Interactions for Machine Learning"
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
dependencies = [
|
|
11
|
+
# core
|
|
12
|
+
"numpy",
|
|
13
|
+
"scipy",
|
|
14
|
+
"pandas",
|
|
15
|
+
"scikit-learn",
|
|
16
|
+
"tqdm",
|
|
17
|
+
"requests",
|
|
18
|
+
"sparse-transform",
|
|
19
|
+
"galois",
|
|
20
|
+
# plotting
|
|
21
|
+
"matplotlib",
|
|
22
|
+
"networkx",
|
|
23
|
+
"colour",
|
|
24
|
+
"pillow",
|
|
25
|
+
]
|
|
26
|
+
authors = [
|
|
27
|
+
{name = "Maximilian Muschalik", email = "Maximilian.Muschalik@lmu.de"},
|
|
28
|
+
{name = "Hubert Baniecki"},
|
|
29
|
+
{name = "Fabian Fumagalli"},
|
|
30
|
+
]
|
|
31
|
+
maintainers = [
|
|
32
|
+
{name = "Maximilian Muschalik", email = "Maximilian.Muschalik@lmu.de"},
|
|
33
|
+
]
|
|
34
|
+
license = "MIT"
|
|
35
|
+
classifiers = [
|
|
36
|
+
"Development Status :: 4 - Beta",
|
|
37
|
+
"Intended Audience :: Developers",
|
|
38
|
+
"Intended Audience :: Science/Research",
|
|
39
|
+
"Topic :: Scientific/Engineering",
|
|
40
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
41
|
+
'Operating System :: Microsoft :: Windows',
|
|
42
|
+
'Operating System :: Unix',
|
|
43
|
+
'Operating System :: MacOS',
|
|
44
|
+
'Programming Language :: Python :: 3',
|
|
45
|
+
'Programming Language :: Python :: 3.10',
|
|
46
|
+
'Programming Language :: Python :: 3.11',
|
|
47
|
+
'Programming Language :: Python :: 3.12',
|
|
48
|
+
'Programming Language :: Python :: 3.13',
|
|
49
|
+
]
|
|
50
|
+
keywords = [
|
|
51
|
+
"python",
|
|
52
|
+
"machine learning",
|
|
53
|
+
"interpretable machine learning",
|
|
54
|
+
"shap",
|
|
55
|
+
"xai",
|
|
56
|
+
"explainable ai",
|
|
57
|
+
"interaction",
|
|
58
|
+
"shapley interactions",
|
|
59
|
+
"shapley values",
|
|
60
|
+
"feature interaction",
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
[tool.setuptools.packages.find]
|
|
64
|
+
where = ["."]
|
|
65
|
+
include = ["shapiq*"]
|
|
66
|
+
|
|
67
|
+
[tool.setuptools.dynamic]
|
|
68
|
+
version = {attr = "shapiq.__version__"}
|
|
69
|
+
readme = {file = ["README.md", "CHANGELOG.md"], content-type = "text/markdown"}
|
|
70
|
+
|
|
71
|
+
[project.urls]
|
|
72
|
+
documentation = "https://shapiq.readthedocs.io"
|
|
73
|
+
source = "https://github.com/mmschlk/shapiq"
|
|
74
|
+
tracker = "https://github.com/mmschlk/shapiq/issues"
|
|
75
|
+
changelog = "https://github.com/mmschlk/shapiq/blob/main/CHANGELOG.md"
|
|
76
|
+
|
|
77
|
+
[project.optional-dependencies]
|
|
78
|
+
ml = [
|
|
79
|
+
"tabpfn",
|
|
80
|
+
"torchvision",
|
|
81
|
+
"torch",
|
|
82
|
+
"xgboost",
|
|
83
|
+
"lightgbm",
|
|
84
|
+
"transformers",
|
|
85
|
+
"scikit-image",
|
|
86
|
+
"joblib",
|
|
87
|
+
"tensorflow; python_version < '3.13'",
|
|
88
|
+
"tf-keras; python_version < '3.13'",
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
[tool.pytest.ini_options]
|
|
92
|
+
testpaths = ["tests"]
|
|
93
|
+
minversion = "8.0"
|
|
94
|
+
|
|
95
|
+
[tool.ruff]
|
|
96
|
+
line-length = 100
|
|
97
|
+
target-version = "py310"
|
|
98
|
+
src = ["tests", "shapiq", "docs"]
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
[tool.ruff.lint]
|
|
102
|
+
# we allow star arguments to be of type Any e.g. def func(*args: Any, **kwargs: Any) -> None: is ok
|
|
103
|
+
flake8-annotations.allow-star-arg-any = true
|
|
104
|
+
select = ["ALL"]
|
|
105
|
+
ignore = [
|
|
106
|
+
"E501", # Line too long
|
|
107
|
+
"N803", # Variable X in function should be lowercase
|
|
108
|
+
"N806", # Variable X in function should be lowercase
|
|
109
|
+
"S301", # exclude pickle restriction, atm. games are unpickled this will need to be fixed # TODO: must be fixed in the future
|
|
110
|
+
"COM812", # this is redundant with the formatter which anyways does this (must be excluded) in the future # TODO: add remove pickle calls and remove this exclusion
|
|
111
|
+
"FIX002", # we use TODOs atm to track potential code improvements # TODO: add this in the future
|
|
112
|
+
"PLR0913", # Too many arguments are passed to function
|
|
113
|
+
"PLR0915", # Too many statements in function
|
|
114
|
+
"PLR0912", # Too many branches in function
|
|
115
|
+
"PLR2004", # Magic values in comparison ... this gets flaged with all checks for two-way interactions
|
|
116
|
+
"C901", # Too complex functions
|
|
117
|
+
"PLR0911", # too many return statements in function
|
|
118
|
+
"N802", # Function name should be lowercase
|
|
119
|
+
]
|
|
120
|
+
exclude = [
|
|
121
|
+
".bzr",
|
|
122
|
+
".direnv",
|
|
123
|
+
".eggs",
|
|
124
|
+
".git",
|
|
125
|
+
".git-rewrite",
|
|
126
|
+
".hg",
|
|
127
|
+
".ipynb_checkpoints",
|
|
128
|
+
".mypy_cache",
|
|
129
|
+
".nox",
|
|
130
|
+
".pants.d",
|
|
131
|
+
".pyenv",
|
|
132
|
+
".pytest_cache",
|
|
133
|
+
".pytype",
|
|
134
|
+
".ruff_cache",
|
|
135
|
+
".svn",
|
|
136
|
+
".tox",
|
|
137
|
+
".venv",
|
|
138
|
+
".vscode",
|
|
139
|
+
"__pypackages__",
|
|
140
|
+
"_build",
|
|
141
|
+
"buck-out",
|
|
142
|
+
"build",
|
|
143
|
+
"dist",
|
|
144
|
+
"node_modules",
|
|
145
|
+
"site-packages",
|
|
146
|
+
"venv",
|
|
147
|
+
"docs/build",
|
|
148
|
+
]
|
|
149
|
+
|
|
150
|
+
# Exclude a variety of commonly ignored directories.
|
|
151
|
+
# Note to developers: If you add a new ignore at least put a comment next to it why it is ignored
|
|
152
|
+
[tool.ruff.lint.per-file-ignores]
|
|
153
|
+
"tests/*.py" = [
|
|
154
|
+
# "ALL",
|
|
155
|
+
"S101", # we need asserts in tests
|
|
156
|
+
"D", # test docstrings don't matter too much
|
|
157
|
+
"E501", # line too long
|
|
158
|
+
"ANN", # type annotations
|
|
159
|
+
"ARG", # some functions are not used
|
|
160
|
+
"INP", # inports can be different
|
|
161
|
+
"N", # type hints are excludes in tests
|
|
162
|
+
"PTH", # we can use os for now
|
|
163
|
+
"S", # in tests we can use some security issues for now
|
|
164
|
+
"PT", # we can use print statements in tests
|
|
165
|
+
"NPY",
|
|
166
|
+
"SLF", # private members are okay in tests
|
|
167
|
+
"TRY",
|
|
168
|
+
]
|
|
169
|
+
"*.ipynb" = [
|
|
170
|
+
"E402", # Module level import not at top of file (its .ipynb)
|
|
171
|
+
"T20", # notebooks can have print statements
|
|
172
|
+
"I002", # notebooks do not have to import required modules
|
|
173
|
+
"D", # docstrings are not required in notebooks
|
|
174
|
+
"SLF001", # private members are okay in notebooks
|
|
175
|
+
"ANN001", # type annotations are not required in notebooks
|
|
176
|
+
]
|
|
177
|
+
"docs/source/*.py" = [
|
|
178
|
+
"A001", # some conf.py variables shadow builtins which is okay here
|
|
179
|
+
"ANN001", # some magic functions I don't want to annotate
|
|
180
|
+
"INP", # docs can be an implicit package (does not need to be imported)
|
|
181
|
+
"I002", # benchmark code does not have to import required modules
|
|
182
|
+
]
|
|
183
|
+
"benchmark/*.py" = [
|
|
184
|
+
"INP", # imports can be different here
|
|
185
|
+
"I002", # benchmark code does not have to import required modules
|
|
186
|
+
"PTH" # in benchmark code we use a lot of os, which is okay
|
|
187
|
+
]
|
|
188
|
+
"docs/copy_notebooks.py" = [
|
|
189
|
+
"PTH", # the script uses os, which is not cirtical for shapiq so it's fine
|
|
190
|
+
"I002", # benchmark code does not have to import required modules
|
|
191
|
+
]
|
|
192
|
+
"__init__.py" = [
|
|
193
|
+
"I002", # __init__.py does not have to import required modules
|
|
194
|
+
"RUF022", # we can have unsorted imports in __init__.py
|
|
195
|
+
"FA",
|
|
196
|
+
]
|
|
197
|
+
"scripts/*.py" = [
|
|
198
|
+
"INP", # imports can be different here
|
|
199
|
+
"I002", # script code does not have to import required modules
|
|
200
|
+
"PTH" # in script code we use a lot of os, which is okay
|
|
201
|
+
]
|
|
202
|
+
|
|
203
|
+
[tool.ruff.lint.pydocstyle]
|
|
204
|
+
convention = "google"
|
|
205
|
+
|
|
206
|
+
[tool.ruff.lint.isort]
|
|
207
|
+
known-first-party = ["shapiq"]
|
|
208
|
+
extra-standard-library = ["typing_extensions"]
|
|
209
|
+
combine-as-imports = true
|
|
210
|
+
force-wrap-aliases = true
|
|
211
|
+
no-lines-before = ["future"]
|
|
212
|
+
required-imports = ["from __future__ import annotations"]
|
|
213
|
+
|
|
214
|
+
[dependency-groups]
|
|
215
|
+
test = [
|
|
216
|
+
"pytest>=8.3.5",
|
|
217
|
+
"pytest-cov>=6.0.0",
|
|
218
|
+
"pytest-xdist>=3.6.1",
|
|
219
|
+
"pytest-randomly",
|
|
220
|
+
]
|
|
221
|
+
lint = [
|
|
222
|
+
"ruff>=0.11.2",
|
|
223
|
+
"pre-commit>=4.2.0",
|
|
224
|
+
]
|
|
225
|
+
docs = [
|
|
226
|
+
"sphinx>=8.0.0",
|
|
227
|
+
"furo",
|
|
228
|
+
"myst-parser",
|
|
229
|
+
"sphinx-copybutton",
|
|
230
|
+
"sphinx-autodoc-typehints",
|
|
231
|
+
"sphinx_toolbox",
|
|
232
|
+
"sphinxcontrib-bibtex", # references based on bibtex
|
|
233
|
+
"nbconvert",
|
|
234
|
+
"nbsphinx",
|
|
235
|
+
"commonmark", # Markdown parser and renderer
|
|
236
|
+
]
|
|
237
|
+
dev = [
|
|
238
|
+
"build>=1.2.2.post1",
|
|
239
|
+
"twine>=6.1.0",
|
|
240
|
+
"notebook>=7.3.3",
|
|
241
|
+
"ipywidgets",
|
|
242
|
+
{include-group = "test"},
|
|
243
|
+
{include-group = "lint"},
|
|
244
|
+
{include-group = "docs"},
|
|
245
|
+
]
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
"""shapiq
|
|
1
|
+
"""shapiq: Shapley Interactions for Machine Learning.
|
|
2
|
+
|
|
3
|
+
shapiq is a library creating explanations for machine learning models based on
|
|
2
4
|
the well established Shapley value and its generalization to interaction.
|
|
3
5
|
"""
|
|
4
6
|
|
|
5
|
-
__version__ = "1.
|
|
7
|
+
__version__ = "1.3.0"
|
|
6
8
|
|
|
7
9
|
# approximator classes
|
|
8
10
|
from .approximator import (
|
|
9
11
|
SHAPIQ,
|
|
12
|
+
SPEX,
|
|
10
13
|
SVARM,
|
|
11
14
|
SVARMIQ,
|
|
12
15
|
InconsistentKernelSHAPIQ,
|
|
@@ -40,7 +43,13 @@ from .benchmark import (
|
|
|
40
43
|
from .datasets import load_adult_census, load_bike_sharing, load_california_housing
|
|
41
44
|
|
|
42
45
|
# explainer classes
|
|
43
|
-
from .explainer import
|
|
46
|
+
from .explainer import (
|
|
47
|
+
AgnosticExplainer,
|
|
48
|
+
Explainer,
|
|
49
|
+
TabPFNExplainer,
|
|
50
|
+
TabularExplainer,
|
|
51
|
+
TreeExplainer,
|
|
52
|
+
)
|
|
44
53
|
|
|
45
54
|
# exact computer classes
|
|
46
55
|
from .game_theory.exact import ExactComputer
|
|
@@ -95,11 +104,13 @@ __all__ = [
|
|
|
95
104
|
"SVARMIQ",
|
|
96
105
|
"kADDSHAP",
|
|
97
106
|
"UnbiasedKernelSHAP",
|
|
107
|
+
"SPEX",
|
|
98
108
|
# explainers
|
|
99
109
|
"Explainer",
|
|
100
110
|
"TabularExplainer",
|
|
101
111
|
"TreeExplainer",
|
|
102
112
|
"TabPFNExplainer",
|
|
113
|
+
"AgnosticExplainer",
|
|
103
114
|
# imputers
|
|
104
115
|
"MarginalImputer",
|
|
105
116
|
"BaselineImputer",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Approximators to estimate the Shapley interaction values."""
|
|
2
2
|
|
|
3
|
-
from .
|
|
3
|
+
from .base import Approximator
|
|
4
4
|
from .marginals import OwenSamplingSV, StratifiedSamplingSV
|
|
5
5
|
from .montecarlo import SHAPIQ, SVARM, SVARMIQ, UnbiasedKernelSHAP
|
|
6
6
|
from .permutation.sii import PermutationSamplingSII
|
|
@@ -14,6 +14,7 @@ from .regression import (
|
|
|
14
14
|
RegressionFSII,
|
|
15
15
|
kADDSHAP,
|
|
16
16
|
)
|
|
17
|
+
from .sparse import SPEX
|
|
17
18
|
|
|
18
19
|
# contains all SV approximators
|
|
19
20
|
SV_APPROXIMATORS: list[Approximator.__class__] = [
|
|
@@ -24,6 +25,7 @@ SV_APPROXIMATORS: list[Approximator.__class__] = [
|
|
|
24
25
|
PermutationSamplingSV,
|
|
25
26
|
KernelSHAP,
|
|
26
27
|
kADDSHAP,
|
|
28
|
+
SPEX,
|
|
27
29
|
]
|
|
28
30
|
|
|
29
31
|
# contains all SI approximators
|
|
@@ -44,6 +46,7 @@ SII_APPROXIMATORS: list[Approximator.__class__] = [
|
|
|
44
46
|
InconsistentKernelSHAPIQ,
|
|
45
47
|
SVARMIQ,
|
|
46
48
|
SHAPIQ,
|
|
49
|
+
SPEX,
|
|
47
50
|
]
|
|
48
51
|
|
|
49
52
|
# contains all approximators that can be used for STII
|
|
@@ -53,6 +56,7 @@ STII_APPROXIMATORS: list[Approximator.__class__] = [
|
|
|
53
56
|
InconsistentKernelSHAPIQ,
|
|
54
57
|
SVARMIQ,
|
|
55
58
|
SHAPIQ,
|
|
59
|
+
SPEX,
|
|
56
60
|
]
|
|
57
61
|
|
|
58
62
|
# contains all approximators that can be used for FSII
|
|
@@ -62,11 +66,13 @@ FSII_APPROXIMATORS: list[Approximator.__class__] = [
|
|
|
62
66
|
InconsistentKernelSHAPIQ,
|
|
63
67
|
SVARMIQ,
|
|
64
68
|
SHAPIQ,
|
|
69
|
+
SPEX,
|
|
65
70
|
]
|
|
66
71
|
|
|
67
72
|
# contains all approximators that can be used for FBII
|
|
68
73
|
FBII_APPROXIMATORS: list[Approximator.__class__] = [
|
|
69
74
|
RegressionFBII,
|
|
75
|
+
SPEX,
|
|
70
76
|
]
|
|
71
77
|
|
|
72
78
|
__all__ = [
|
|
@@ -84,6 +90,7 @@ __all__ = [
|
|
|
84
90
|
"SVARM",
|
|
85
91
|
"SVARMIQ",
|
|
86
92
|
"kADDSHAP",
|
|
93
|
+
"SPEX",
|
|
87
94
|
"UnbiasedKernelSHAP",
|
|
88
95
|
"SV_APPROXIMATORS",
|
|
89
96
|
"SI_APPROXIMATORS",
|
|
@@ -92,5 +99,3 @@ __all__ = [
|
|
|
92
99
|
"FSII_APPROXIMATORS",
|
|
93
100
|
"FBII_APPROXIMATORS",
|
|
94
101
|
]
|
|
95
|
-
|
|
96
|
-
# Path: shapiq/approximator/__init__.py
|