shapiq: any-order Shapley interactions on top of the SHAP workflow
Shapley Interactions and Shapley Values for Machine Learning
At a glance
- What is it?
- shapiq is an MIT-licensed Python package that extends Shapley values to interactions between features, data points, or ensemble members. It is aimed at people who already read SHAP output and want to know where two features act together rather than in isolation.
- Who is it for?
- Adopt shapiq if your explanations already use Shapley values and the question you keep hitting is whether two features matter together, not just how much each one matters alone. Do not adopt it if you need a stable explanation contract for a production dashboard and cannot absorb index changes or re-tuning of max_order between releases.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 15 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap shapiq fills: main effects hide the interesting part
A Shapley value tells you how much a single feature contributes to a prediction on average over all orderings of the other features. That is a marginal contribution, and it is defined so that the individual values sum to the difference between the prediction and a baseline. What it cannot tell you is whether two features only matter in combination. A model can split credit between two correlated inputs in a way that looks unremarkable feature by feature while the pair carries most of the signal. shapiq targets exactly that case. The README frames it as extending shap by quantifying the synergy effect between players, where players can be explanatory features, data points, or weak learners in an ensemble. The package name expands to Shapley Interaction Quantification, and the stated scope has three parts: approximating any-order Shapley interactions, benchmarking game-theoretic algorithms for machine learning, and explaining feature interactions of model predictions. The audience is split in two by the README itself: researchers working on game theory in machine learning, and end users explaining models. Those two groups want different things from the same codebase, and the module layout reflects it. If you only ever want per-feature numbers, you do not need this package; the value appears when the interaction terms are the thing you are trying to read.
How the interaction values are produced: explainer, approximator, game
The README describes three layers. The explainer layer is what most users touch: you hand a model, some background data, an index name, and a maximum order, and you get back an InteractionValues object. The approximator layer is where the game-theoretic work happens, and it is exposed directly for cases where the explainer wrapper is in the way. The games layer sits underneath and defines the cooperative game being solved. The data flow is visible in the quickstart. shapiq.load_california_housing returns X and y, a scikit-learn RandomForestRegressor is fitted on them, and a TabularExplainer is constructed with model, data, index='k-SII', and max_order=4. Calling explainer.explain(X[0], budget=256) returns an object whose repr shows index=k-SII, max_order=4, min_order=0, estimated=False, estimation_budget=256, n_players=8, and a baseline_value of about 2.07. The printed top terms mix single features such as (0,) at roughly 1.70 with pairs such as (0, 5) at roughly 0.48 and triples such as (0, 3, 6) at roughly -0.32. That mixed output is the whole point: attributions and interactions of several orders land in one structure, and negative interaction terms are reported alongside positive ones. The estimated flag matters. When the computation is exhaustive the flag is False; when an approximator is used, the values are estimates, and the budget you pass is the knob that controls how much sampling work is spent. The n_players field is 8 in the example, which is the number of features in that dataset, and it is the dimension that drives cost.
Installing and configuring shapiq, including the ProxySPEX path
The README states the package targets Python 3.12 and above, which is a narrower support window than many ML libraries carry, so check your interpreter before anything else. Installation is either uv add shapiq or pip install shapiq. The configuration surface that appears in the material is small and lives in the explainer constructor: model, data, index, max_order, and approximator. The index accepts 'SV' for plain Shapley values, 'k-SII' for interaction values, and 'FBII' in the large-scale example. max_order controls how deep the interaction terms go; the quickstart uses 4 with TabularExplainer and 2 in the SV-to-interaction example. The budget argument on explain() sets the estimation budget, shown as 256 in the quickstart and 2000 in the ProxySPEX example. For wide feature spaces the README points at ProxySPEX, described as a sparse explainer for large-scale use cases. It can be driven directly, with shapiq.ProxySPEX(n=n_features, index="FBII", max_order=2) followed by approximator.approximate(budget=2000, game=model.predict), or through the explainer by setting approximator="proxyspex". Note the direct call passes game=model.predict, so the callable you supply is the game. Visualisation is a separate step: shapiq.network_plot takes first_order_values and second_order_values, which you extract with interaction_values.get_n_order_values(1) and get_n_order_values(2), or you can call interaction_values.plot_network(). The force plot path is interaction_values.plot_force(feature_names=...).
Cost, order, and the budget trade-off you cannot avoid
The number of interaction terms grows combinatorially with max_order. At order 2 over n features you have n choose 2 pairs; at order 4 you are enumerating quadruples. The README does not state a complexity bound, but the structure of the output makes the pressure obvious, and the presence of an estimation_budget field confirms that exact computation is not always the mode. This is the central trade-off of the package. Raising max_order widens what you can see and shrinks how reliably you see it at a fixed budget. The quickstart prints estimated=False at budget 256 for 8 players, which is a small problem; the same settings on a few hundred features would not be exact, and the README's answer for that regime is ProxySPEX rather than a bigger budget on the dense path. There is a second limitation worth naming: interaction values are harder to communicate than main effects. A ranked list of pairs and triples with signs is not a chart most stakeholders will read without help, which is presumably why network_plot and plot_force exist. If your audience only ever asks which feature mattered most, the interaction machinery adds computation and interpretation load for output they will not use. The README also does not document failure modes, convergence guarantees, or how to tell whether an estimated interaction is real rather than sampling noise. That gap is on the user to close, and it is not small.
shapiq against SHAP, and against reporting interactions by hand
The obvious alternative is the shap package itself, which shapiq explicitly extends. The difference in approach is scope, not speed. SHAP gives you per-feature attributions under an additive assumption: the explanation is a set of individual scores. shapiq keeps the same interface for that case, since index="SV" returns Shapley values and the README shows plot_force working on them, but it also represents the explanation as a set of terms indexed by subsets of players, which is what lets (0, 5) and (0, 3, 6) appear next to (0,). If you have already built dashboards on SHAP values, the migration is not a rewrite: you change the index string and the max_order, and you get a richer object back. The cost is that downstream code consuming a flat array of feature scores has to learn the subset-keyed structure, including calls like get_n_order_values(1) to recover the old view. The other alternative is to approximate interactions yourself, for example by fitting a surrogate or by differencing SHAP values across feature subsets. That path avoids a new dependency but gives you no index with defined properties and no shared vocabulary for what a reported interaction means. shapiq's indexes are named and specified, which is the part that is hard to reproduce ad hoc. The README does not compare shapiq to specific competing interaction libraries, so any claim about relative accuracy would have to come from the project's own benchmarking module rather than from this material.
Licence, maintenance, and what upgrading actually involves
shapiq is MIT licensed, which permits commercial use, modification, and redistribution provided the copyright notice and permission notice are retained. That is a permissive arrangement and it does not impose copyleft obligations on your own code. This is a description of the licence text, not legal advice; if the package ends up inside a distributed product, have counsel confirm the notice requirements are met. On maintenance, the release history shows three releases in roughly two months: v1.5.2 in June 2026, v1.6.0 in July 2026, and v1.7.0 in August 2026. The last push to the default branch was 2026-09-01, and the repository is not archived. A cadence of minor releases every few weeks means you should expect the API surface to move, and the README's own pointer to a GitHub Project Board for upcoming explainers, performance work, and expanded model support confirms that new functionality is planned rather than frozen. The practical upgrade cost is therefore re-validation: an interaction value that changed between versions is hard to distinguish from a real change in the model, so pin the version in your environment and re-run your explanation checks when you bump it. The README does not publish a deprecation policy or a compatibility guarantee across minor versions, so treat each upgrade as something to verify rather than assume.
Where shapiq is the wrong tool
Three cases argue against it. First, latency-bound serving. If an explanation has to be produced inside a request path with a tight budget, the estimation budget becomes a hard constraint, and the README's own large-scale answer, ProxySPEX with budget=2000, is not a request-path number. Precompute instead. Second, regulated or audited reporting where the explanation must be reproducible bit for bit. Estimated interaction values depend on a sampling budget, and the material does not describe a seeding or determinism mechanism, so you cannot assume two runs at budget 256 produce identical numbers. Third, teams without an existing Shapley workflow. The README positions shapiq as an extension of shap, and the quickstart leans on that familiarity. Arriving without it means learning Shapley values, the index taxonomy, and the interaction output format at the same time, which is a lot of surface for a problem that a simpler attribution method might answer. There is also the Python 3.12 floor. If you are pinned to an older interpreter for other dependency reasons, shapiq is simply unavailable until that changes, and the README gives no fallback.
Editorial conclusion
Adopt shapiq if your explanations already use Shapley values and the question you keep hitting is whether two features matter together, not just how much each one matters alone. Do not adopt it if you need a stable explanation contract for a production dashboard and cannot absorb index changes or re-tuning of max_order between releases. Verify first that your Python is 3.12 or newer, that the index you pick (SV, k-SII, or FBII) matches the property you actually want to report, and that the budget you pass to explain() is large enough for the order you request, since a higher max_order at a fixed budget trades accuracy for coverage.
Community notes