Skip to content

Commit 74c31bc

Browse files
authored
Rename t parameter in SPEX and Sparse (mmschlk#392)
* updated description and name of ``t`` to be ``degree_parameter`` * updated attr description * updated README.md * updated readme to include SPEX * updated degree_parameter description * updated README.md * updated README.md * fixed logo_path * Update README.md
1 parent 6b27861 commit 74c31bc

File tree

4 files changed

+65
-24
lines changed

4 files changed

+65
-24
lines changed

README.md

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919
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.
2020

2121
## 🛠️ Install
22-
`shapiq` is intended to work with **Python 3.10 and above**. Installation can be done via `uv` and `pip`:
23-
22+
`shapiq` is intended to work with **Python 3.10 and above**.
23+
Installation can be done via `uv` :
2424
```sh
2525
uv add shapiq
2626
```
2727

28+
or via `pip`:
29+
2830
```sh
2931
pip install shapiq
3032
```
@@ -37,6 +39,7 @@ If you are interested in the underlying game theoretic algorithms, then check ou
3739
### Compute any-order feature interactions
3840

3941
Explain your models with Shapley interactions:
42+
Just load your data and model, and then use a `shapiq.Explainer` to compute Shapley interactions.
4043

4144
```python
4245
import shapiq
@@ -135,7 +138,7 @@ The pseudo-code above can produce the following plot (here also an image is adde
135138

136139
### Explain TabPFN
137140

138-
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``.
139142

140143
```python
141144
import tabpfn, shapiq
@@ -148,14 +151,36 @@ explainer = shapiq.TabPFNExplainer( # setup the explainer
148151
labels=labels,
149152
index="FSII"
150153
)
151-
fsii_values = explainer.explain(X[0]) # explain with Faithful Shapley values
154+
fsii_values = explainer.explain(data[0]) # explain with Faithful Shapley values
152155
fsii_values.plot_force() # plot the force plot
153156
```
154157

155158
<p align="center">
156159
<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">
157160
</p>
158161

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+
159184

160185
## 📖 Documentation with tutorials
161186
The documentation of ``shapiq`` can be found at https://shapiq.readthedocs.io.

shapiq/approximator/sparse/_base.py

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,16 @@ class Sparse(Approximator):
3838
3939
Attributes:
4040
transform_type: Type of transform used (currently only ``"fourier"`` is supported).
41-
transform_tolerance: Error tolerance parameter for the sparse Fourier transform.
41+
42+
degree_parameter: A parameter that controls the maximum degree of the interactions to
43+
extract during execution of the algorithm. Note that this is a soft limit, and in
44+
practice, the algorithm may extract interactions of any degree. We typically find
45+
that there is little value going beyond ``5``. Defaults to ``5``. Note that
46+
increasing this parameter will need more ``budget`` in the :meth:`approximate`
47+
method.
48+
4249
query_args: Parameters for querying the signal.
50+
4351
decoder_args: Parameters for decoding the transform.
4452
4553
Raises:
@@ -60,7 +68,7 @@ def __init__(
6068
random_state: int | None = None,
6169
transform_type: Literal["fourier"] = "fourier",
6270
decoder_type: Literal["soft", "hard"] = "soft",
63-
transform_tolerance: int = 5,
71+
degree_parameter: int = 5,
6472
) -> None:
6573
"""Initialize the Sparse approximator.
6674
@@ -83,15 +91,19 @@ def __init__(
8391
8492
decoder_type: Type of decoder to use, either "soft" or "hard". Defaults to "soft".
8593
86-
transform_tolerance: Error tolerance parameter for the sparse Fourier transform.
87-
Higher values increase accuracy but require more samples. Defaults to ``5``.
94+
degree_parameter: A parameter that controls the maximum degree of the interactions to
95+
extract during execution of the algorithm. Note that this is a soft limit, and in
96+
practice, the algorithm may extract interactions of any degree. We typically find
97+
that there is little value going beyond ``5``. Defaults to ``5``. Note that
98+
increasing this parameter will need more ``budget`` in the :meth:`approximate`
99+
method.
88100
89101
"""
90102
if transform_type.lower() not in ["fourier"]:
91103
msg = "transform_type must be 'fourier'"
92104
raise ValueError(msg)
93105
self.transform_type = transform_type.lower()
94-
self.transform_tolerance = transform_tolerance
106+
self.degree_parameter = degree_parameter
95107
self.decoder_type = "hard" if decoder_type is None else decoder_type.lower()
96108
if self.decoder_type not in ["soft", "hard"]:
97109
msg = "decoder_type must be 'soft' or 'hard'"
@@ -104,7 +116,7 @@ def __init__(
104116
"subsampling_method": "qsft",
105117
"delays_method_channel": "identity-siso",
106118
"num_repeat": 1,
107-
"t": self.transform_tolerance,
119+
"t": self.degree_parameter,
108120
}
109121
self.decoder_args = {
110122
"num_subsample": 3,
@@ -116,7 +128,7 @@ def __init__(
116128
else "identity",
117129
"regress": "lasso",
118130
"res_energy_cutoff": 0.9,
119-
"source_decoder": get_bch_decoder(n, self.transform_tolerance, self.decoder_type),
131+
"source_decoder": get_bch_decoder(n, self.degree_parameter, self.decoder_type),
120132
}
121133
super().__init__(
122134
n=n,
@@ -245,31 +257,31 @@ def _set_transform_budget(self, budget: int) -> int:
245257
ValueError: If the budget is too low to compute the transform with acceptable parameters.
246258
"""
247259
b = SubsampledSignalFourier.get_b_for_sample_budget(
248-
budget, self.n, self.transform_tolerance, 2, self.query_args
260+
budget, self.n, self.degree_parameter, 2, self.query_args
249261
)
250262
used_budget = SubsampledSignalFourier.get_number_of_samples(
251-
self.n, b, self.transform_tolerance, 2, self.query_args
263+
self.n, b, self.degree_parameter, 2, self.query_args
252264
)
253265

254266
if b <= 2:
255-
while self.transform_tolerance > 2:
256-
self.transform_tolerance -= 1
257-
self.query_args["t"] = self.transform_tolerance
267+
while self.degree_parameter > 2:
268+
self.degree_parameter -= 1
269+
self.query_args["t"] = self.degree_parameter
258270

259271
# Recalculate 'b' with the updated 't'
260272
b = SubsampledSignalFourier.get_b_for_sample_budget(
261-
budget, self.n, self.transform_tolerance, 2, self.query_args
273+
budget, self.n, self.degree_parameter, 2, self.query_args
262274
)
263275

264276
# Compute the used budget
265277
used_budget = SubsampledSignalFourier.get_number_of_samples(
266-
self.n, b, self.transform_tolerance, 2, self.query_args
278+
self.n, b, self.degree_parameter, 2, self.query_args
267279
)
268280

269281
# Break if 'b' is now sufficient
270282
if b > 2:
271283
self.decoder_args["source_decoder"] = get_bch_decoder(
272-
self.n, self.transform_tolerance, self.decoder_type
284+
self.n, self.degree_parameter, self.decoder_type
273285
)
274286
break
275287

shapiq/approximator/sparse/spex.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def __init__(
2727
top_order: bool = False,
2828
random_state: int | None = None,
2929
decoder_type: Literal["soft", "hard"] = "soft",
30-
transform_tolerance: int = 5,
30+
degree_parameter: int = 5,
3131
) -> None:
3232
"""Initialize the SPEX approximator.
3333
@@ -47,8 +47,12 @@ def __init__(
4747
4848
decoder_type: Type of decoder to use, either "soft" or "hard". Defaults to "soft".
4949
50-
transform_tolerance: Error tolerance parameter for the sparse Fourier transform.
51-
Higher values increase accuracy but require more samples. Defaults to ``5``.
50+
degree_parameter: A parameter that controls the maximum degree of the interactions to
51+
extract during execution of the algorithm. Note that this is a soft limit, and in
52+
practice, the algorithm may extract interactions of any degree. We typically find
53+
that there is little value going beyond ``5``. Defaults to ``5``. Note that
54+
increasing this parameter will need more ``budget`` in the :meth:`approximate`
55+
method.
5256
5357
"""
5458
super().__init__(
@@ -59,5 +63,5 @@ def __init__(
5963
random_state=random_state,
6064
transform_type="fourier",
6165
decoder_type=decoder_type,
62-
transform_tolerance=transform_tolerance,
66+
degree_parameter=degree_parameter,
6367
)

tests/tests_approximators/test_approximator_spex.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def test_sparsity_parameter(n, interaction, budget, correct_b, correct_t):
149149
_ = spex.approximate(budget, game)
150150

151151
assert spex.query_args["b"] == correct_b
152-
assert spex.transform_tolerance == correct_t
152+
assert spex.degree_parameter == correct_t
153153

154154

155155
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)