Repository navigation
v1.7.0 (2026-08-27)
v1.7.0 (2026-08-27)
New and Improved Tree support.
This release focuses on a greatly improved support of tree-based models as provided by sklearn, XGBoost, LightGBM, or CatBoost.
TreeExplainer remains the single entry point for explaining tree-based models and routes to the fastest available algorithms.
With this release, tree explanations are numerically stable at any tree depth and substantially faster on all kinds of trees, in both pathdependent and interventional mode.
In mode="pathdependent", explanations are now computed by the new QuadratureTreeSHAP algorithm, which replaces the polynomial algorithms LinearTreeSHAP and TreeSHAPIQ as the default.
In mode="interventional", smaller inputs are computed by InterventionalTreeSHAPIQ and larger inputs route to the new vectorized Woodelf fast path.
All four algorithms share a common interface and can also be used directly, independently of TreeExplainer.
Woodelf-IQ integration #572
Together with Ron Wettenstein, we add a Woodelf fast path to shapiq.tree.TreeExplainer (Nadel and Wettenstein, 2026; Wettenstein et al., 2026).
Woodelf is very fast. It computes explanations fully vectorized over all explained instances and reference rows scaling much more favorably with large explanation points or reference data than existing algorithms.
It is also not limited to Shapley values and also computes interaction indices "SII" and "k-SII" and Banzhaf values "BV" "BII".
TreeExplainer.explain_X explains all instances in one vectorized run and returns the new InteractionValuesBatch: a lazy sequence of one InteractionValues per instance whose .values attribute exposes the raw vectorized arrays (Explainer.explain_X is now typed as returning a Sequence[InteractionValues]).
The fast path requires the new optional tree dependency group (pip install shapiq[tree] — woodelf-explainer); without it, the explainer falls back to the shapiq implementation with a WoodelfNotAvailableWarning.
The new backend parameter ("auto", "woodelf", "shapiq") overrides the automatic routing, whose cut-off between the two backends was benchmarked and set to n * m >= 100_000 (n explained instances × m reference rows) #591.
QuadratureSHAP #588
We add QuadratureTreeSHAP in shapiq.tree.quadrature as the default path-dependent algorithm of TreeExplainer, computing all supported indices ("SV", "SII", "k-SII", "BV", "BII") at any order natively replacing LinearTreeSHAP and TreeSHAPIQ.
QuadratureTreeSHAP is a new efficient pathdependent TreeSHAP algorithm (Wettenstein et al., 2026; Li et al., 2026) computing Shapley values and any-order Shapley interactions ("SV", "SII", "k-SII") as well as the Banzhaf indices ("BV"/"BII") numerically exact in float64 at any tree depth and any number of features per decision path.
This resolves the numerical instability of the existing polynomial algorithms which started at around 28 unique features per path #545.
QuadratureTreeSHAP is implemented with a C++ kernel that benchmarks substantially faster than the existing explainers at every measured setting.
We see about 2× improvements vs LinearTreeSHAP, which is the fastest algorithm for Shapley values and 100×+ vs TreeSHAPIQ for interactions.
We can compute order-4 interactions in milliseconds.
Ensembles are computed in a single batched C++ kernel invocation over a shared feature space, which benchmarks at parity with XGBoost's native pred_contribs TreeSHAP on a single thread.
New LeverageSHAP Approximator #524, #583
Adds the LeverageSHAP approximator in shapiq.approximator.regression for Shapley value estimation via leverage score sampling (Musco and Witter, 2025).
LeverageSHAP is the modernized variant of KernelSHAP and should be used as a direct replacement improving sample-efficiency without additional costs.
The implementation follows the paper's released implementation: a functional pairing_trick, deterministic per-size sample counts (deterministic_counts=True by default), and exact budget accounting #583.
Additional new Features
- adds support of any-order
BIIandSTIItoProxySHAP(in addition toSV,BV,SII,k-SII,FSII, andFBII).ProxySHAPis registered for both indices whereversetup_approximatorresolves the"proxyshap"string.MoebiusConvertergained the matchingBIIconversion, and computesBVthrough it. #587 - adds a
k_foldsparameter toProxySHAPandRegressionMSRfor out-of-fold proxy residuals, i.e. the cross-fitting variant of Witter et al. (2025). The defaultk_folds=1fits a single proxy on all sampled coalitions, which the paper recommends in practice. #587 - aligns
RegressionMSRmore with the theory of the paper by adding sampling weights for theRegressionMSRestimator which are coherent to the papers proposed sampling Witter et al. (2025). #587 - adds
TreeExplainersupport for scikit-learn gradient boosting models:GradientBoostingRegressor,GradientBoostingClassifier,HistGradientBoostingRegressor, andHistGradientBoostingClassifiercan now be converted to the internal tree format. #577 - adds categorical split support to the tree explainers: models trained with native categorical features -- sklearn
HistGradientBoosting*(categorical_features), LightGBM (categorical_feature), and XGBoost (enable_categorical) -- are now converted and explained exactly on all paths (TreeSHAP-IQ, LinearTreeSHAP, Interventional TreeSHAP-IQ, and QuadratureSHAP).TreeModelstores per-node category sets in a CSR layout (cat_values/cat_start/cat_size) with the unified routing rule "category in set → left child, NaN → missing child". #577 - adds the
ConfoundingSHAPlocal and global explanation game inshapiq_games.benchmark.causal_xaifor the first causal machine learning based value functions (Brockschmidt et al., 2026) based on the paper. #551
Breaking Changes
- renames
InterventionalTreeExplainertoInterventionalTreeSHAPIQinshapiq.tree.interventionalfor consistency withTreeSHAPIQ,LinearTreeSHAP, and the newly addedQuadratureSHAP. The old name is no longer available; importshapiq.tree.InterventionalTreeSHAPIQinstead. #580 - turns
ProxySHAP'sadjustmentparameter into a boolean (defaultFalse;RegressionMSRalways applies it). The residual correction is now a built-in closed-form MSR routine rather than a second approximator, so the"svarm"and"kernel"variants are no longer available.random_state=Noneis also no longer silently replaced by a fixed seed, which the single shared coalition sampler makes unnecessary. #587 - changes
RegressionMSR's defaultsampling_weightsto the closed-form kernel of Witter et al. (2025), including their separate Leverage-SHAP kernel for linear proxies withindex="SV". Passingsampling_weightsexplicitly still overrides the default. #587
Bugfix
- fixes wrong explanations for XGBoost and CatBoost models on instances whose float64 feature values round across a split threshold in float32: both libraries cast prediction inputs to float32 before routing, which the converted trees now reproduce via
TreeModel.input_precision/cast_input(LightGBM compares in float64 and is untouched; sklearn's thresholds are exact midpoints of adjacent float32 values, making its internal cast unobservable). Previously all tree explainers could explain a different leaf than the model actually predicts — on measured XGBoosthistmodels roughly half the instances routed differently somewhere in the ensemble #588 - fixes silently permuted attributions for trees whose feature-id set iterates in non-ascending order (e.g. features
{6, 14}):reduce_feature_complexityassigned reduced ids in rawsetiteration order while the returnedinteraction_lookupsorts players, pairing values with the wrong features inTreeSHAPIQ. #588 - fixes a bug with categorical LightGBM/XGBoost models, which were silently mis-parsed (bitset indices read as numeric thresholds), producing wrong explanations without any error #577
- fixes missing-value (NaN) routing in the LinearTreeSHAP and interventional C++ kernels:
-ffast-mathhad compiled away thestd::isnanchecks (now built with-fno-finite-math-only), and TreeSHAP-IQ now routes NaN values through the per-node missing direction exactly likepredict_one#577 - removes the stale and broken
STII/FSII/BIIcode path from the path-dependentTreeSHAPIQalgorithm, which crashed with broadcasting errors on wider trees.TreeSHAPIQnow raises a clearValueErrorfor indices other thanSV,SII, andk-SII. #571 #575 - removes
KernelSHAPIQandInconsistentKernelSHAPIQfrom theSTII_APPROXIMATORSandFSII_APPROXIMATORSregistries inshapiq.approximator, since both only support theSV,SII, andk-SIIindices #571 #575 - fixes the
BVindex losingestimatedandestimation_budgetwhen interactions are read out of a linear proxy:MoebiusConverternow computesBVthrough the base-interaction routine (as it already did forSV) instead of the faithful-index routine, which did not carry those fields through. #587
Maintenance
- adds numerical precision guards to the polynomial tree explainers:
LinearTreeSHAPandTreeSHAPIQnow emit aTreeNumericalPrecisionWarningfrom 24 distinct features per decision path (they become numerically unstable there) and raise aTreeNumericalPrecisionErrorfrom 30 (unreliable values), instead of silently returning wrong attributions or crashing with an unexplainedLinAlgError#545. #588 - rewrites
ProxySHAP's MSR residual adjustment as a self-contained vectorized routine that estimates all interactions in a single matrix product over the coalitions already sampled, instead of re-sampling an independentCoalitionSamplerand running a second Monte Carlo pass on a residual game. #587 - removes the dead non-log weight computations from the approximator base classes, which were superseded by their log-space counterparts:
Regression._init_kernel_weights(superseded by_init_log_kernel_weights) and theMonteCarlofamily_get_standard_form_weights/_weight/_sii_weight/_bii_weight/_chii_weight/_stii_weight/_fsii_weight/_fbii_weight(superseded by_get_standard_form_log_weightsand the_log_*_weightmethods). #578 - vectorizes the k-SII aggregation (
aggregate_base_attributions): all subset projections and Bernoulli weightings are built as array operations and summed per subset via integer-codedbincount, ~12–27× faster than the previous per-subset dict loop. #590 KNNExplainer,WeightedKNNExplainer, and their ground-truth games now raise aValueErrorat construction when the model was fitted on fewer training samples thann_neighbors, mirroring scikit-learn's own "Expected n_neighbors <= n_samples_fit" error onpredict. Previously,KNNExplainersilently returned Shapley values that disagreed withKNNExplainerGamein this regime #582- moves the hot paths of
InterventionalTreeSHAPIQfor non-boolean trees to C++, for a ~263× end-to-end speedup: a fused dense kernel (compute_interactions_cohort) replaces the per-explanation Python E/R preprocessing with one DFS per tree that shares the walk across all reference samples, and the interventionalbaseline_valuenow routes the reference data through a C++ ensemble-prediction kernel (predict_ensemble_sum) instead of a Python per-(row, tree) loop (up to ~500× on large backgrounds). #590 - harmonizes the tree computation algorithms:
LinearTreeSHAP,TreeSHAPIQ,QuadratureTreeSHAP, andInterventionalTreeSHAPIQnow all validate their own models, accept ensembles as well as single trees (aggregating internally), take aclass_indexargument, and expose a commonexplain(x)entry point — each algorithm can be used independently ofTreeExplainer, which now simply instantiates one explainer per mode. Note that TreeExplainer is still the intended access points for users. Their modules are namedcomputer(shapiq.tree.linear.computer,shapiq.tree.quadrature.computer,shapiq.tree.interventional.computer), keepingshapiq.tree.explainerunambiguous as the user-facingTreeExplainerentry point. #588 - the interventional TreeSHAP-IQ C kernels now compute in float64 (previously float32 inputs, thresholds, and accumulation on the dense path); the three unused kernel entry points (
compute_interactions,compute_interactions_batched,compute_interactions_sparse) were removed #588
New Contributors
- @mariebrockschmidt made their first contribution in #551
- @FabianK-Dev made their first contribution in #524
- @ron-wettenstein made their first contribution in #572
- @rtealwitter made their first contribution in #583
Full Changelog: v1.6.0...v1.7.0