shapiq 1.2.1__tar.gz → 1.2.3__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.1 → shapiq-1.2.3}/CHANGELOG.md +16 -1
- {shapiq-1.2.1/shapiq.egg-info → shapiq-1.2.3}/PKG-INFO +48 -72
- {shapiq-1.2.1 → shapiq-1.2.3}/README.md +3 -1
- shapiq-1.2.3/pyproject.toml +121 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/__init__.py +3 -1
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/__init__.py +15 -1
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/_base.py +37 -103
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/marginals/owen.py +35 -11
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/marginals/stratified.py +17 -6
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/montecarlo/_base.py +37 -10
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/montecarlo/shapiq.py +4 -6
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/montecarlo/svarmiq.py +4 -6
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/permutation/sii.py +16 -6
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/permutation/stii.py +51 -14
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/permutation/sv.py +30 -8
- shapiq-1.2.3/shapiq/approximator/regression/__init__.py +17 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/regression/_base.py +165 -127
- shapiq-1.2.3/shapiq/approximator/regression/faithful.py +97 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/regression/kadd_shap.py +2 -4
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/regression/kernelshap.py +2 -4
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/regression/kernelshapiq.py +4 -6
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/sampling.py +17 -17
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/benchmark/configuration.py +2 -2
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/benchmark/load.py +4 -5
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/benchmark/metrics.py +1 -2
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/benchmark/plot.py +8 -8
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/benchmark/precompute.py +8 -8
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/benchmark/run.py +20 -24
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/datasets/_all.py +12 -11
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/explainer/_base.py +1 -4
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/explainer/tabpfn.py +15 -6
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/explainer/tabular.py +20 -8
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/explainer/tree/base.py +33 -12
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/explainer/tree/conversion/lightgbm.py +25 -35
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/explainer/tree/conversion/sklearn.py +2 -4
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/explainer/tree/conversion/xgboost.py +25 -37
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/explainer/tree/explainer.py +16 -6
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/explainer/tree/treeshapiq.py +49 -23
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/explainer/tree/validation.py +8 -6
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/explainer/utils.py +6 -3
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/game_theory/__init__.py +2 -2
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/game_theory/aggregation.py +14 -12
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/game_theory/core.py +1 -2
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/game_theory/exact.py +24 -20
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/game_theory/indices.py +4 -4
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/game_theory/moebius_converter.py +4 -4
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/base.py +21 -22
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/__init__.py +48 -32
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/data_valuation/base.py +2 -2
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/data_valuation/benchmark.py +3 -5
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/dataset_valuation/base.py +10 -10
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/dataset_valuation/benchmark.py +6 -8
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/ensemble_selection/__init__.py +7 -5
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/ensemble_selection/base.py +6 -6
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/ensemble_selection/benchmark.py +6 -8
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/ensemble_selection/benchmark_random_forest.py +3 -5
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/feature_selection/base.py +5 -4
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/feature_selection/benchmark.py +3 -5
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/global_xai/base.py +2 -2
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/global_xai/benchmark_tabular.py +3 -5
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/local_xai/base.py +4 -5
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/local_xai/benchmark_image.py +1 -2
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/local_xai/benchmark_tabular.py +7 -9
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/setup.py +5 -6
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/synthetic/__init__.py +2 -1
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/synthetic/dummy.py +1 -3
- shapiq-1.2.3/shapiq/games/benchmark/synthetic/random.py +33 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/synthetic/soum.py +5 -7
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/treeshapiq_xai/base.py +1 -2
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/treeshapiq_xai/benchmark.py +8 -10
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/uncertainty/base.py +2 -4
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/uncertainty/benchmark.py +2 -4
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/unsupervised_cluster/base.py +4 -6
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/unsupervised_cluster/benchmark.py +3 -5
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/imputer/base.py +4 -5
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/imputer/baseline_imputer.py +2 -3
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/imputer/conditional_imputer.py +7 -5
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/imputer/marginal_imputer.py +4 -15
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/imputer/tabpfn_imputer.py +4 -4
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/interaction_values.py +90 -30
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/plot/bar.py +5 -7
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/plot/force.py +2 -4
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/plot/network.py +13 -13
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/plot/sentence.py +3 -4
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/plot/si_graph.py +12 -15
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/plot/stacked_bar.py +6 -6
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/plot/upset.py +2 -3
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/plot/utils.py +1 -2
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/plot/watefall.py +3 -5
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/utils/datasets.py +1 -3
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/utils/modules.py +11 -15
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/utils/sets.py +6 -6
- {shapiq-1.2.1 → shapiq-1.2.3/shapiq.egg-info}/PKG-INFO +48 -72
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq.egg-info/SOURCES.txt +2 -5
- shapiq-1.2.3/shapiq.egg-info/requires.txt +23 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/tests/test_base_interaction_values.py +16 -5
- shapiq-1.2.1/MANIFEST.in +0 -3
- shapiq-1.2.1/pyproject.toml +0 -16
- shapiq-1.2.1/setup.py +0 -110
- shapiq-1.2.1/shapiq/approximator/regression/__init__.py +0 -8
- shapiq-1.2.1/shapiq/approximator/regression/fsi.py +0 -53
- shapiq-1.2.1/shapiq.egg-info/requires.txt +0 -53
- shapiq-1.2.1/shapiq.egg-info/zip-safe +0 -1
- shapiq-1.2.1/tests/test_abstract_classes.py +0 -64
- {shapiq-1.2.1 → shapiq-1.2.3}/LICENSE +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/setup.cfg +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/marginals/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/montecarlo/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/approximator/permutation/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/benchmark/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/datasets/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/explainer/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/explainer/tree/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/explainer/tree/conversion/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/explainer/tree/conversion/edges.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/explainer/tree/utils.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/_setup/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/_setup/_california_torch_setup.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/_setup/_resnet_setup.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/_setup/_vit_setup.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/data_valuation/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/dataset_valuation/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/feature_selection/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/global_xai/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/local_xai/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/local_xai/benchmark_language.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/treeshapiq_xai/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/uncertainty/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/unsupervised_cluster/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/unsupervised_data/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/unsupervised_data/base.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/benchmark/unsupervised_data/benchmark.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/games/imputer/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/plot/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/plot/_config.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/utils/__init__.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq/utils/types.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq.egg-info/dependency_links.txt +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/shapiq.egg-info/top_level.txt +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/tests/test_configuration.py +0 -0
- {shapiq-1.2.1 → shapiq-1.2.3}/tests/test_integration_import_all.py +0 -0
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
## Changelog
|
|
2
2
|
|
|
3
3
|
### Development
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
### v1.2.3 (2025-03-24)
|
|
6
|
+
- 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)
|
|
7
|
+
- removes `sample_replacements` parameter from `MarginalImputer` and removes the DeprecationWarning for it
|
|
8
|
+
- adds a trivial computation to `TreeSHAP-IQ` for trees that use only one feature in the tree (this works for decision stumps or trees splitting on only one feature multiple times). In such trees, the computation is trivial as the whole effect of $\nu(N) - \nu(\emptyset)$ is all on the main effect of the single feature and there is no interaction effect. This expands on the fix in v1.2.1 [#286](https://github.com/mmschlk/shapiq/issues/286).
|
|
9
|
+
- fixes a bug with xgboost where feature names where trees that did not contain all features would lead `TreeExplainer` to fail
|
|
10
|
+
- fixes a bug with `stacked_bar_plot` where the higher order interactions were inflated by the lower order interactions, thus wrongly showing the higher order interactions as higher than they are
|
|
11
|
+
- fixes a bug where `InteractionValues.get_subset()` returns a faulty `coalition_lookup` dictionary pointing to indices outside the subset of players [#336](https://github.com/mmschlk/shapiq/issues/336)
|
|
12
|
+
- updates default value of `TreeExplainer`'s `min_order` parameter from 1 to 0 to include the baseline value in the interaction values as per default
|
|
13
|
+
- adds the `RegressionFBII` approximator to estimate Faithful Banzhaf interactions via least squares regression [#333](https://github.com/mmschlk/shapiq/pull/333). Additionally, FBII support was introduced in TabularExplainer and MonteCarlo-Approximator.
|
|
14
|
+
- adds a `RandomGame` class as part of `shapiq.games.benchmark` which always returns a random vector of integers between 0 and 100.
|
|
15
|
+
|
|
16
|
+
### v1.2.2 (2025-03-11)
|
|
17
|
+
- changes python support to 3.10-3.13 [#318](https://github.com/mmschlk/shapiq/pull/318)
|
|
18
|
+
- fixes a bug that prohibited importing shapiq in environments without write access [#326](https://github.com/mmschlk/shapiq/issues/326)
|
|
19
|
+
- adds `ExtraTreeRegressors` to supported models [#309](https://github.com/mmschlk/shapiq/pull/309)
|
|
5
20
|
|
|
6
21
|
### v1.2.1 (2025-02-17)
|
|
7
22
|
- fixes bugs regarding plotting [#315](https://github.com/mmschlk/shapiq/issues/315) and [#316](https://github.com/mmschlk/shapiq/issues/316)
|
|
@@ -1,27 +1,30 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: shapiq
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.3
|
|
4
4
|
Summary: Shapley Interactions for Machine Learning
|
|
5
|
-
|
|
6
|
-
Author: Maximilian Muschalik
|
|
7
|
-
|
|
8
|
-
License: MIT
|
|
9
|
-
Project-URL:
|
|
10
|
-
Project-URL:
|
|
11
|
-
Project-URL:
|
|
5
|
+
Author: Hubert Baniecki, Fabian Fumagalli
|
|
6
|
+
Author-email: Maximilian Muschalik <Maximilian.Muschalik@lmu.de>
|
|
7
|
+
Maintainer-email: Maximilian Muschalik <Maximilian.Muschalik@lmu.de>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Project-URL: documentation, https://shapiq.readthedocs.io
|
|
10
|
+
Project-URL: source, https://github.com/mmschlk/shapiq
|
|
11
|
+
Project-URL: tracker, https://github.com/mmschlk/shapiq/issues
|
|
12
|
+
Project-URL: changelog, https://github.com/mmschlk/shapiq/blob/main/CHANGELOG.md
|
|
12
13
|
Keywords: python,machine learning,interpretable machine learning,shap,xai,explainable ai,interaction,shapley interactions,shapley values,feature interaction
|
|
13
14
|
Classifier: Development Status :: 4 - Beta
|
|
14
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
15
15
|
Classifier: Intended Audience :: Developers
|
|
16
16
|
Classifier: Intended Audience :: Science/Research
|
|
17
17
|
Classifier: Topic :: Scientific/Engineering
|
|
18
18
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
|
-
Classifier:
|
|
20
|
-
Classifier:
|
|
19
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
20
|
+
Classifier: Operating System :: Unix
|
|
21
|
+
Classifier: Operating System :: MacOS
|
|
22
|
+
Classifier: Programming Language :: Python :: 3
|
|
21
23
|
Classifier: Programming Language :: Python :: 3.10
|
|
22
24
|
Classifier: Programming Language :: Python :: 3.11
|
|
23
25
|
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
-
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
27
|
+
Requires-Python: >=3.10
|
|
25
28
|
Description-Content-Type: text/markdown
|
|
26
29
|
License-File: LICENSE
|
|
27
30
|
Requires-Dist: numpy
|
|
@@ -31,63 +34,20 @@ Requires-Dist: scikit-learn
|
|
|
31
34
|
Requires-Dist: tqdm
|
|
32
35
|
Requires-Dist: requests
|
|
33
36
|
Requires-Dist: matplotlib
|
|
34
|
-
Requires-Dist: colour
|
|
35
37
|
Requires-Dist: networkx
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
Requires-Dist:
|
|
39
|
-
Requires-Dist:
|
|
40
|
-
Requires-Dist:
|
|
41
|
-
Requires-Dist:
|
|
42
|
-
Requires-Dist:
|
|
43
|
-
Requires-Dist:
|
|
44
|
-
Requires-Dist:
|
|
45
|
-
Requires-Dist:
|
|
46
|
-
Requires-Dist:
|
|
47
|
-
Requires-Dist:
|
|
48
|
-
|
|
49
|
-
Requires-Dist: sphinx_toolbox; extra == "docs"
|
|
50
|
-
Requires-Dist: nbsphinx; extra == "docs"
|
|
51
|
-
Requires-Dist: pandoc; extra == "docs"
|
|
52
|
-
Requires-Dist: furo; extra == "docs"
|
|
53
|
-
Requires-Dist: sphinx-copybutton; extra == "docs"
|
|
54
|
-
Requires-Dist: myst-parser; extra == "docs"
|
|
55
|
-
Provides-Extra: dev
|
|
56
|
-
Requires-Dist: numpy; extra == "dev"
|
|
57
|
-
Requires-Dist: scipy; extra == "dev"
|
|
58
|
-
Requires-Dist: pandas; extra == "dev"
|
|
59
|
-
Requires-Dist: scikit-learn; extra == "dev"
|
|
60
|
-
Requires-Dist: tqdm; extra == "dev"
|
|
61
|
-
Requires-Dist: requests; extra == "dev"
|
|
62
|
-
Requires-Dist: matplotlib; extra == "dev"
|
|
63
|
-
Requires-Dist: colour; extra == "dev"
|
|
64
|
-
Requires-Dist: networkx; extra == "dev"
|
|
65
|
-
Requires-Dist: sphinx; extra == "dev"
|
|
66
|
-
Requires-Dist: sphinx-autodoc-typehints; extra == "dev"
|
|
67
|
-
Requires-Dist: sphinx_rtd_theme; extra == "dev"
|
|
68
|
-
Requires-Dist: sphinx_toolbox; extra == "dev"
|
|
69
|
-
Requires-Dist: nbsphinx; extra == "dev"
|
|
70
|
-
Requires-Dist: pandoc; extra == "dev"
|
|
71
|
-
Requires-Dist: furo; extra == "dev"
|
|
72
|
-
Requires-Dist: sphinx-copybutton; extra == "dev"
|
|
73
|
-
Requires-Dist: myst-parser; extra == "dev"
|
|
74
|
-
Requires-Dist: build; extra == "dev"
|
|
75
|
-
Requires-Dist: black; extra == "dev"
|
|
76
|
-
Requires-Dist: pytest; extra == "dev"
|
|
77
|
-
Requires-Dist: coverage; extra == "dev"
|
|
78
|
-
Dynamic: author
|
|
79
|
-
Dynamic: author-email
|
|
80
|
-
Dynamic: classifier
|
|
81
|
-
Dynamic: description
|
|
82
|
-
Dynamic: description-content-type
|
|
83
|
-
Dynamic: home-page
|
|
84
|
-
Dynamic: keywords
|
|
85
|
-
Dynamic: license
|
|
86
|
-
Dynamic: project-url
|
|
87
|
-
Dynamic: provides-extra
|
|
88
|
-
Dynamic: requires-dist
|
|
89
|
-
Dynamic: requires-python
|
|
90
|
-
Dynamic: summary
|
|
38
|
+
Requires-Dist: colour
|
|
39
|
+
Provides-Extra: ml
|
|
40
|
+
Requires-Dist: tabpfn; extra == "ml"
|
|
41
|
+
Requires-Dist: torchvision; extra == "ml"
|
|
42
|
+
Requires-Dist: torch; extra == "ml"
|
|
43
|
+
Requires-Dist: xgboost; extra == "ml"
|
|
44
|
+
Requires-Dist: lightgbm; extra == "ml"
|
|
45
|
+
Requires-Dist: transformers; extra == "ml"
|
|
46
|
+
Requires-Dist: scikit-image; extra == "ml"
|
|
47
|
+
Requires-Dist: joblib; extra == "ml"
|
|
48
|
+
Requires-Dist: tensorflow; python_version < "3.13" and extra == "ml"
|
|
49
|
+
Requires-Dist: tf-keras; python_version < "3.13" and extra == "ml"
|
|
50
|
+
Dynamic: license-file
|
|
91
51
|
|
|
92
52
|
# shapiq: Shapley Interactions for Machine Learning <img src="https://raw.githubusercontent.com/mmschlk/shapiq/main/docs/source/_static/logo/logo_shapiq_light.svg" alt="shapiq_logo" align="right" height="250px"/>
|
|
93
53
|
|
|
@@ -102,13 +62,15 @@ Dynamic: summary
|
|
|
102
62
|
[](https://pepy.tech/project/shapiq)
|
|
103
63
|
|
|
104
64
|
[](https://github.com/psf/black)
|
|
65
|
+

|
|
66
|
+

|
|
105
67
|
|
|
106
68
|
> An interaction may speak more than a thousand main effects.
|
|
107
69
|
|
|
108
70
|
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.
|
|
109
71
|
|
|
110
72
|
## 🛠️ Install
|
|
111
|
-
`shapiq` is intended to work with **Python 3.
|
|
73
|
+
`shapiq` is intended to work with **Python 3.10 and above**. Installation can be done via `pip`:
|
|
112
74
|
|
|
113
75
|
```sh
|
|
114
76
|
pip install shapiq
|
|
@@ -279,11 +241,25 @@ Some authors acknowledge the financial support by the German Research Foundation
|
|
|
279
241
|
---
|
|
280
242
|
Built with ❤️ by the shapiq team.
|
|
281
243
|
|
|
282
|
-
|
|
283
244
|
## Changelog
|
|
284
245
|
|
|
285
246
|
### Development
|
|
286
|
-
|
|
247
|
+
|
|
248
|
+
### v1.2.3 (2025-03-24)
|
|
249
|
+
- 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)
|
|
250
|
+
- removes `sample_replacements` parameter from `MarginalImputer` and removes the DeprecationWarning for it
|
|
251
|
+
- adds a trivial computation to `TreeSHAP-IQ` for trees that use only one feature in the tree (this works for decision stumps or trees splitting on only one feature multiple times). In such trees, the computation is trivial as the whole effect of $\nu(N) - \nu(\emptyset)$ is all on the main effect of the single feature and there is no interaction effect. This expands on the fix in v1.2.1 [#286](https://github.com/mmschlk/shapiq/issues/286).
|
|
252
|
+
- fixes a bug with xgboost where feature names where trees that did not contain all features would lead `TreeExplainer` to fail
|
|
253
|
+
- fixes a bug with `stacked_bar_plot` where the higher order interactions were inflated by the lower order interactions, thus wrongly showing the higher order interactions as higher than they are
|
|
254
|
+
- fixes a bug where `InteractionValues.get_subset()` returns a faulty `coalition_lookup` dictionary pointing to indices outside the subset of players [#336](https://github.com/mmschlk/shapiq/issues/336)
|
|
255
|
+
- updates default value of `TreeExplainer`'s `min_order` parameter from 1 to 0 to include the baseline value in the interaction values as per default
|
|
256
|
+
- adds the `RegressionFBII` approximator to estimate Faithful Banzhaf interactions via least squares regression [#333](https://github.com/mmschlk/shapiq/pull/333). Additionally, FBII support was introduced in TabularExplainer and MonteCarlo-Approximator.
|
|
257
|
+
- adds a `RandomGame` class as part of `shapiq.games.benchmark` which always returns a random vector of integers between 0 and 100.
|
|
258
|
+
|
|
259
|
+
### v1.2.2 (2025-03-11)
|
|
260
|
+
- changes python support to 3.10-3.13 [#318](https://github.com/mmschlk/shapiq/pull/318)
|
|
261
|
+
- fixes a bug that prohibited importing shapiq in environments without write access [#326](https://github.com/mmschlk/shapiq/issues/326)
|
|
262
|
+
- adds `ExtraTreeRegressors` to supported models [#309](https://github.com/mmschlk/shapiq/pull/309)
|
|
287
263
|
|
|
288
264
|
### v1.2.1 (2025-02-17)
|
|
289
265
|
- fixes bugs regarding plotting [#315](https://github.com/mmschlk/shapiq/issues/315) and [#316](https://github.com/mmschlk/shapiq/issues/316)
|
|
@@ -11,13 +11,15 @@
|
|
|
11
11
|
[](https://pepy.tech/project/shapiq)
|
|
12
12
|
|
|
13
13
|
[](https://github.com/psf/black)
|
|
14
|
+

|
|
15
|
+

|
|
14
16
|
|
|
15
17
|
> An interaction may speak more than a thousand main effects.
|
|
16
18
|
|
|
17
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.
|
|
18
20
|
|
|
19
21
|
## 🛠️ Install
|
|
20
|
-
`shapiq` is intended to work with **Python 3.
|
|
22
|
+
`shapiq` is intended to work with **Python 3.10 and above**. Installation can be done via `pip`:
|
|
21
23
|
|
|
22
24
|
```sh
|
|
23
25
|
pip install shapiq
|
|
@@ -0,0 +1,121 @@
|
|
|
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
|
+
# plotting
|
|
19
|
+
"matplotlib",
|
|
20
|
+
"networkx",
|
|
21
|
+
"colour"
|
|
22
|
+
]
|
|
23
|
+
authors = [
|
|
24
|
+
{name = "Maximilian Muschalik", email = "Maximilian.Muschalik@lmu.de"},
|
|
25
|
+
{name = "Hubert Baniecki"},
|
|
26
|
+
{name = "Fabian Fumagalli"},
|
|
27
|
+
]
|
|
28
|
+
maintainers = [
|
|
29
|
+
{name = "Maximilian Muschalik", email = "Maximilian.Muschalik@lmu.de"},
|
|
30
|
+
]
|
|
31
|
+
license = "MIT"
|
|
32
|
+
classifiers = [
|
|
33
|
+
"Development Status :: 4 - Beta",
|
|
34
|
+
"Intended Audience :: Developers",
|
|
35
|
+
"Intended Audience :: Science/Research",
|
|
36
|
+
"Topic :: Scientific/Engineering",
|
|
37
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
38
|
+
'Operating System :: Microsoft :: Windows',
|
|
39
|
+
'Operating System :: Unix',
|
|
40
|
+
'Operating System :: MacOS',
|
|
41
|
+
'Programming Language :: Python :: 3',
|
|
42
|
+
'Programming Language :: Python :: 3.10',
|
|
43
|
+
'Programming Language :: Python :: 3.11',
|
|
44
|
+
'Programming Language :: Python :: 3.12',
|
|
45
|
+
'Programming Language :: Python :: 3.13',
|
|
46
|
+
]
|
|
47
|
+
keywords = [
|
|
48
|
+
"python",
|
|
49
|
+
"machine learning",
|
|
50
|
+
"interpretable machine learning",
|
|
51
|
+
"shap",
|
|
52
|
+
"xai",
|
|
53
|
+
"explainable ai",
|
|
54
|
+
"interaction",
|
|
55
|
+
"shapley interactions",
|
|
56
|
+
"shapley values",
|
|
57
|
+
"feature interaction",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
[tool.setuptools.packages.find]
|
|
61
|
+
where = ["."]
|
|
62
|
+
include = ["shapiq*"]
|
|
63
|
+
|
|
64
|
+
[tool.setuptools.dynamic]
|
|
65
|
+
version = {attr = "shapiq.__version__"}
|
|
66
|
+
readme = {file = ["README.md", "CHANGELOG.md"], content-type = "text/markdown"}
|
|
67
|
+
|
|
68
|
+
[project.urls]
|
|
69
|
+
documentation = "https://shapiq.readthedocs.io"
|
|
70
|
+
source = "https://github.com/mmschlk/shapiq"
|
|
71
|
+
tracker = "https://github.com/mmschlk/shapiq/issues"
|
|
72
|
+
changelog = "https://github.com/mmschlk/shapiq/blob/main/CHANGELOG.md"
|
|
73
|
+
|
|
74
|
+
[project.optional-dependencies]
|
|
75
|
+
ml = [
|
|
76
|
+
"tabpfn",
|
|
77
|
+
"torchvision",
|
|
78
|
+
"torch",
|
|
79
|
+
"xgboost",
|
|
80
|
+
"lightgbm",
|
|
81
|
+
"transformers",
|
|
82
|
+
"scikit-image",
|
|
83
|
+
"joblib",
|
|
84
|
+
"tensorflow; python_version < '3.13'",
|
|
85
|
+
"tf-keras; python_version < '3.13'",
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
[tool.pytest.ini_options]
|
|
89
|
+
testpaths = ["tests"]
|
|
90
|
+
minversion = "8.0"
|
|
91
|
+
|
|
92
|
+
[tool.ruff]
|
|
93
|
+
lint.select = ["E", "F", "I", "UP"] # https://beta.ruff.rs/docs/rules/
|
|
94
|
+
lint.ignore = ["E501"]
|
|
95
|
+
line-length = 100
|
|
96
|
+
target-version = "py310"
|
|
97
|
+
|
|
98
|
+
[tool.ruff.lint.isort]
|
|
99
|
+
known-first-party = ["shapiq"]
|
|
100
|
+
extra-standard-library = ["typing_extensions"]
|
|
101
|
+
combine-as-imports = true
|
|
102
|
+
force-wrap-aliases = true
|
|
103
|
+
|
|
104
|
+
[dependency-groups]
|
|
105
|
+
test = [
|
|
106
|
+
"pytest>=8.3.5",
|
|
107
|
+
"pytest-cov>=6.0.0",
|
|
108
|
+
"pytest-xdist>=3.6.1",
|
|
109
|
+
]
|
|
110
|
+
lint = [
|
|
111
|
+
"ruff>=0.11.2",
|
|
112
|
+
"pre-commit>=4.2.0",
|
|
113
|
+
]
|
|
114
|
+
dev = [
|
|
115
|
+
"build>=1.2.2.post1",
|
|
116
|
+
"twine>=6.1.0",
|
|
117
|
+
"notebook>=7.3.3",
|
|
118
|
+
"ipywidgets",
|
|
119
|
+
{include-group = "test"},
|
|
120
|
+
{include-group = "lint"},
|
|
121
|
+
]
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
the well established Shapley value and its generalization to interaction.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
__version__ = "1.2.
|
|
5
|
+
__version__ = "1.2.3"
|
|
6
6
|
|
|
7
7
|
# approximator classes
|
|
8
8
|
from .approximator import (
|
|
@@ -16,6 +16,7 @@ from .approximator import (
|
|
|
16
16
|
PermutationSamplingSII,
|
|
17
17
|
PermutationSamplingSTII,
|
|
18
18
|
PermutationSamplingSV,
|
|
19
|
+
RegressionFBII,
|
|
19
20
|
RegressionFSII,
|
|
20
21
|
StratifiedSamplingSV,
|
|
21
22
|
UnbiasedKernelSHAP,
|
|
@@ -86,6 +87,7 @@ __all__ = [
|
|
|
86
87
|
"OwenSamplingSV",
|
|
87
88
|
"KernelSHAP",
|
|
88
89
|
"RegressionFSII",
|
|
90
|
+
"RegressionFBII",
|
|
89
91
|
"KernelSHAPIQ",
|
|
90
92
|
"InconsistentKernelSHAPIQ",
|
|
91
93
|
"SHAPIQ",
|
|
@@ -6,7 +6,14 @@ from .montecarlo import SHAPIQ, SVARM, SVARMIQ, UnbiasedKernelSHAP
|
|
|
6
6
|
from .permutation.sii import PermutationSamplingSII
|
|
7
7
|
from .permutation.stii import PermutationSamplingSTII
|
|
8
8
|
from .permutation.sv import PermutationSamplingSV
|
|
9
|
-
from .regression import
|
|
9
|
+
from .regression import (
|
|
10
|
+
InconsistentKernelSHAPIQ,
|
|
11
|
+
KernelSHAP,
|
|
12
|
+
KernelSHAPIQ,
|
|
13
|
+
RegressionFBII,
|
|
14
|
+
RegressionFSII,
|
|
15
|
+
kADDSHAP,
|
|
16
|
+
)
|
|
10
17
|
|
|
11
18
|
# contains all SV approximators
|
|
12
19
|
SV_APPROXIMATORS: list[Approximator.__class__] = [
|
|
@@ -57,6 +64,11 @@ FSII_APPROXIMATORS: list[Approximator.__class__] = [
|
|
|
57
64
|
SHAPIQ,
|
|
58
65
|
]
|
|
59
66
|
|
|
67
|
+
# contains all approximators that can be used for FBII
|
|
68
|
+
FBII_APPROXIMATORS: list[Approximator.__class__] = [
|
|
69
|
+
RegressionFBII,
|
|
70
|
+
]
|
|
71
|
+
|
|
60
72
|
__all__ = [
|
|
61
73
|
"PermutationSamplingSII",
|
|
62
74
|
"PermutationSamplingSTII",
|
|
@@ -65,6 +77,7 @@ __all__ = [
|
|
|
65
77
|
"OwenSamplingSV",
|
|
66
78
|
"KernelSHAP",
|
|
67
79
|
"RegressionFSII",
|
|
80
|
+
"RegressionFBII",
|
|
68
81
|
"KernelSHAPIQ",
|
|
69
82
|
"InconsistentKernelSHAPIQ",
|
|
70
83
|
"SHAPIQ",
|
|
@@ -77,6 +90,7 @@ __all__ = [
|
|
|
77
90
|
"SII_APPROXIMATORS",
|
|
78
91
|
"STII_APPROXIMATORS",
|
|
79
92
|
"FSII_APPROXIMATORS",
|
|
93
|
+
"FBII_APPROXIMATORS",
|
|
80
94
|
]
|
|
81
95
|
|
|
82
96
|
# Path: shapiq/approximator/__init__.py
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
"""This module contains the base approximator classes for the shapiq package."""
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import warnings
|
|
4
4
|
from abc import ABC, abstractmethod
|
|
5
|
-
from
|
|
5
|
+
from collections.abc import Callable
|
|
6
6
|
|
|
7
7
|
import numpy as np
|
|
8
|
+
from scipy.special import binom
|
|
8
9
|
|
|
9
10
|
from ..approximator.sampling import CoalitionSampler
|
|
10
11
|
from ..game_theory.indices import (
|
|
11
12
|
AVAILABLE_INDICES_FOR_APPROXIMATION,
|
|
12
13
|
get_computation_index,
|
|
13
|
-
is_empty_value_the_baseline,
|
|
14
|
-
is_index_aggregated,
|
|
15
14
|
)
|
|
16
15
|
from ..interaction_values import InteractionValues
|
|
17
16
|
from ..utils.sets import generate_interaction_lookup
|
|
@@ -66,8 +65,8 @@ class Approximator(ABC):
|
|
|
66
65
|
top_order: bool,
|
|
67
66
|
min_order: int = 0,
|
|
68
67
|
pairing_trick: bool = False,
|
|
69
|
-
sampling_weights:
|
|
70
|
-
random_state:
|
|
68
|
+
sampling_weights: np.ndarray[float] | None = None,
|
|
69
|
+
random_state: int | None = None,
|
|
71
70
|
) -> None:
|
|
72
71
|
# check if index can be approximated
|
|
73
72
|
self.index: str = index
|
|
@@ -92,8 +91,8 @@ class Approximator(ABC):
|
|
|
92
91
|
)
|
|
93
92
|
|
|
94
93
|
# set up random state and random number generators
|
|
95
|
-
self._random_state:
|
|
96
|
-
self._rng:
|
|
94
|
+
self._random_state: int | None = random_state
|
|
95
|
+
self._rng: np.random.Generator | None = np.random.default_rng(seed=self._random_state)
|
|
97
96
|
|
|
98
97
|
# set up a coalition sampler
|
|
99
98
|
self._big_M: int = 100_000_000 # large number for sampling weights
|
|
@@ -110,7 +109,7 @@ class Approximator(ABC):
|
|
|
110
109
|
self, budget: int, game: Callable[[np.ndarray], np.ndarray], *args, **kwargs
|
|
111
110
|
) -> InteractionValues:
|
|
112
111
|
"""Calls the approximate method."""
|
|
113
|
-
return self.approximate(budget, game, *args, **kwargs)
|
|
112
|
+
return self.approximate(budget=budget, game=game, *args, **kwargs)
|
|
114
113
|
|
|
115
114
|
@abstractmethod
|
|
116
115
|
def approximate(
|
|
@@ -129,7 +128,9 @@ class Approximator(ABC):
|
|
|
129
128
|
Raises:
|
|
130
129
|
NotImplementedError: If the method is not implemented.
|
|
131
130
|
"""
|
|
132
|
-
raise NotImplementedError(
|
|
131
|
+
raise NotImplementedError(
|
|
132
|
+
"The approximate method must be implemented in the subclass."
|
|
133
|
+
) # pragma: no cover
|
|
133
134
|
|
|
134
135
|
def _init_sampling_weights(self) -> np.ndarray:
|
|
135
136
|
"""Initializes the weights for sampling subsets.
|
|
@@ -141,13 +142,29 @@ class Approximator(ABC):
|
|
|
141
142
|
The weights for sampling subsets of size ``s`` in shape ``(n + 1,)``.
|
|
142
143
|
"""
|
|
143
144
|
weight_vector = np.zeros(shape=self.n + 1)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
145
|
+
if self.index in ["FBII"]:
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
for coalition_size in range(0, self.n + 1):
|
|
149
|
+
weight_vector[coalition_size] = binom(self.n, coalition_size) / 2**self.n
|
|
150
|
+
except OverflowError:
|
|
151
|
+
for coalition_size in range(0, self.n + 1):
|
|
152
|
+
weight_vector[coalition_size] = (
|
|
153
|
+
1
|
|
154
|
+
/ np.sqrt(2 * np.pi * 0.5)
|
|
155
|
+
* np.exp(-(coalition_size - self.n / 2) * +2 / (self.n / 2))
|
|
156
|
+
)
|
|
157
|
+
warnings.warn(
|
|
158
|
+
"The weights are approximated for n > 1000. While this is very close to the truth for sets for size in the region n/2, the approximation is not exact for size n or 0."
|
|
159
|
+
)
|
|
160
|
+
else:
|
|
161
|
+
for coalition_size in range(0, self.n + 1):
|
|
162
|
+
if (coalition_size < self.max_order) or (coalition_size > self.n - self.max_order):
|
|
163
|
+
# prioritize these subsets
|
|
164
|
+
weight_vector[coalition_size] = self._big_M
|
|
165
|
+
else:
|
|
166
|
+
# KernelSHAP sampling weights
|
|
167
|
+
weight_vector[coalition_size] = 1 / (coalition_size * (self.n - coalition_size))
|
|
151
168
|
sampling_weight = weight_vector / np.sum(weight_vector)
|
|
152
169
|
return sampling_weight
|
|
153
170
|
|
|
@@ -173,65 +190,6 @@ class Approximator(ABC):
|
|
|
173
190
|
"""
|
|
174
191
|
return range(self.min_order, self.max_order + 1)
|
|
175
192
|
|
|
176
|
-
def _finalize_result(
|
|
177
|
-
self,
|
|
178
|
-
result,
|
|
179
|
-
baseline_value: float,
|
|
180
|
-
*,
|
|
181
|
-
estimated: Optional[bool] = None,
|
|
182
|
-
budget: Optional[int] = None,
|
|
183
|
-
) -> InteractionValues:
|
|
184
|
-
"""Finalizes the result dictionary.
|
|
185
|
-
|
|
186
|
-
Args:
|
|
187
|
-
result: Interaction values.
|
|
188
|
-
baseline_value: Baseline value.
|
|
189
|
-
estimated: Whether interaction values were estimated.
|
|
190
|
-
budget: The budget for the approximation.
|
|
191
|
-
|
|
192
|
-
Returns:
|
|
193
|
-
The interaction values.
|
|
194
|
-
|
|
195
|
-
Raises:
|
|
196
|
-
ValueError: If the baseline value is not provided for SII and k-SII.
|
|
197
|
-
"""
|
|
198
|
-
|
|
199
|
-
if budget is None: # try to get budget from sampler
|
|
200
|
-
budget = self._sampler.n_coalitions
|
|
201
|
-
if budget == 0:
|
|
202
|
-
raise ValueError("Budget is 0. Cannot finalize interaction values.")
|
|
203
|
-
# Note to developer: This should not happen, the finalize method should be called
|
|
204
|
-
# with a valid budget.
|
|
205
|
-
|
|
206
|
-
if estimated is None:
|
|
207
|
-
estimated = False if budget >= 2**self.n else True
|
|
208
|
-
|
|
209
|
-
# set empty value as baseline value if necessary
|
|
210
|
-
if tuple() in self._interaction_lookup:
|
|
211
|
-
idx = self._interaction_lookup[tuple()]
|
|
212
|
-
empty_value = result[idx]
|
|
213
|
-
# only for SII empty value is not the baseline value
|
|
214
|
-
if empty_value != baseline_value and is_empty_value_the_baseline(self.index):
|
|
215
|
-
result[idx] = baseline_value
|
|
216
|
-
|
|
217
|
-
interactions = InteractionValues(
|
|
218
|
-
values=result,
|
|
219
|
-
estimated=estimated,
|
|
220
|
-
estimation_budget=budget,
|
|
221
|
-
index=self.approximation_index, # can be different from self.index
|
|
222
|
-
min_order=self.min_order,
|
|
223
|
-
max_order=self.max_order,
|
|
224
|
-
n_players=self.n,
|
|
225
|
-
interaction_lookup=copy.deepcopy(self.interaction_lookup),
|
|
226
|
-
baseline_value=baseline_value,
|
|
227
|
-
)
|
|
228
|
-
|
|
229
|
-
# if index needs to be aggregated
|
|
230
|
-
if is_index_aggregated(self.index):
|
|
231
|
-
interactions = self.aggregate_interaction_values(interactions)
|
|
232
|
-
|
|
233
|
-
return interactions
|
|
234
|
-
|
|
235
193
|
@staticmethod
|
|
236
194
|
def _calc_iteration_count(budget: int, batch_size: int, iteration_cost: int) -> tuple[int, int]:
|
|
237
195
|
"""Computes the number of iterations and the size of the last batch given the batch size and
|
|
@@ -303,8 +261,7 @@ class Approximator(ABC):
|
|
|
303
261
|
@staticmethod
|
|
304
262
|
def aggregate_interaction_values(
|
|
305
263
|
base_interactions: InteractionValues,
|
|
306
|
-
order:
|
|
307
|
-
player_set: Optional[set[int]] = None,
|
|
264
|
+
order: int | None = None,
|
|
308
265
|
) -> InteractionValues:
|
|
309
266
|
"""Aggregates the interaction values.
|
|
310
267
|
|
|
@@ -312,33 +269,10 @@ class Approximator(ABC):
|
|
|
312
269
|
base_interactions: The base interaction values to aggregate.
|
|
313
270
|
order: The order of the aggregation. For example, the order of the k-SII aggregation.
|
|
314
271
|
If ``None`` (default), the maximum order of the base interactions is used.
|
|
315
|
-
player_set: The set of players to consider for the aggregation. If ``None`` (default),
|
|
316
|
-
all players are considered.
|
|
317
272
|
|
|
318
273
|
Returns:
|
|
319
274
|
The aggregated interaction values.
|
|
320
275
|
"""
|
|
321
|
-
from shapiq.game_theory.aggregation import
|
|
322
|
-
|
|
323
|
-
if player_set is not None:
|
|
324
|
-
raise NotImplementedError(
|
|
325
|
-
"Aggregating interaction values for a subset of players is not implemented."
|
|
326
|
-
)
|
|
327
|
-
|
|
328
|
-
return aggregate_interaction_values(base_interactions, order=order)
|
|
329
|
-
|
|
330
|
-
@staticmethod
|
|
331
|
-
def aggregate_to_one_dimension(
|
|
332
|
-
interaction_values: InteractionValues,
|
|
333
|
-
) -> tuple[np.ndarray, np.ndarray]:
|
|
334
|
-
"""Aggregates the interaction values to one dimension.
|
|
335
|
-
|
|
336
|
-
Args:
|
|
337
|
-
interaction_values: The interaction values to aggregate.
|
|
338
|
-
|
|
339
|
-
Returns:
|
|
340
|
-
tuple[np.ndarray, np.ndarray]: The positive and negative aggregated values.
|
|
341
|
-
"""
|
|
342
|
-
from shapiq.game_theory.aggregation import aggregate_to_one_dimension
|
|
276
|
+
from shapiq.game_theory.aggregation import aggregate_base_interaction
|
|
343
277
|
|
|
344
|
-
return
|
|
278
|
+
return aggregate_base_interaction(base_interactions, order=order)
|