Skip to main content

Stable feature importance explanations under collinearity — works with any model and attribution method

Project description

DASH: Diversified Aggregation for Stable Hypotheses

PyPI ArXiv Python License: MIT

Stable feature importance when your features are correlated. SHAP rankings from a single model are partially random under collinearity — DASH fixes this by averaging explanations across independent models so the noise cancels and the signal remains. Works with any attribution method.

Install

pip install dash-shap

Quick Check — Is Your Model Affected?

from dash_shap import check
from sklearn.datasets import load_breast_cancer

data = load_breast_cancer()
result = check(data.data, data.target, task="binary",
               feature_names=list(data.feature_names))
print(result.report())
DASH Stability Check
========================================
Models trained: 25
Features: 30
Unstable pairs: 68
Correlated groups: 5

UNSTABLE PAIRS (rankings flip across retrains):
  worst radius vs worst perimeter: flip rate 48%, predicted 47%
  mean radius vs mean perimeter: flip rate 44%, predicted 43%
  ...

RECOMMENDATION: Use M=150 models for 5% flip rate target

TOP FEATURES (DASH consensus):
  1. worst concave points: 0.0831 (stable)
  2. worst perimeter: 0.0534 (UNSTABLE)
  3. worst radius: 0.0521 (UNSTABLE)
  ...

result.plot() shows the Importance-Stability plot. result.dash_importance() returns stable consensus rankings. result.to_dataframe() gives a full summary with SNR predictions.

Full Pipeline

For production use with diversity selection and full diagnostics:

from dash_shap import DASHPipeline
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split

X, y = load_breast_cancer(return_X_y=True)
X_temp, X_test, y_temp, y_test = train_test_split(X, y, test_size=0.15, random_state=42)
X_temp, X_ref, y_temp, _ = train_test_split(X_temp, y_temp, test_size=0.12, random_state=42)
X_train, X_val, y_train, y_val = train_test_split(X_temp, y_temp, test_size=0.18, random_state=42)

pipe = DASHPipeline(M=100, K=20, epsilon=0.05, epsilon_mode="relative",
                    task="binary", seed=42)
pipe.fit(X_train, y_train, X_val, y_val, X_ref=X_ref)

# Stable consensus importance
print(pipe.global_importance_)

# Importance-Stability plot: which features are stable vs. collinear?
pipe.plot_importance_stability()

# Feature Stability Index: per-feature stability scores
pipe.get_fsi().summary(top_k=10)

The IS plot places features in four quadrants:

Quadrant Importance Stability Action
I: Robust Drivers High Stable Report individually
II: Collinear Cluster High Unstable Report as a group
III: Unimportant Low Stable Safe to omit
IV: Fragile Low Unstable Investigate or drop

Using with Any Attribution Method

The default pipeline uses XGBoost + TreeSHAP, but DASH works with any attribution source — LIME, Integrated Gradients, attention maps, KernelSHAP, or custom methods:

# You have M attribution vectors from any source, shape (M, P)
# e.g., LIME importance from M independently trained neural networks
pipe = DASHPipeline(M=100, K=20, epsilon=0.05)
pipe.fit_from_attributions(attribution_matrices, val_scores)
print(pipe.global_importance_)

# Or use the lightweight stability workflow directly
from dash_shap import validate_from_attributions, consensus_from_attributions

results = validate_from_attributions(attribution_matrix)  # Z-tests + flip rates
stable = consensus_from_attributions(attribution_matrix)   # averaged importance

The underlying impossibility theorem — mechanically verified in Lean 4 (248 theorems, 0 unproved gaps) — proves that no single-model ranking can be simultaneously faithful and stable under collinearity (the bilemma). DASH's consensus averaging is the unique structural resolution: it enriches the binary output space with a neutral element (ties), which the resolution taxonomy proves is the only escape from the impossibility. This holds for all iterative optimizers (gradient boosting, Lasso, neural networks).

Extensions

After fitting, pipe.result_ is a DASHResult that supports additional analyses:

from dash_shap.extensions import (
    confidence_intervals, robust_certification, theory_bridge,
    causal_flags, audit_report, DriftMonitor, federated_consensus,
)

# Bootstrap confidence intervals on importance and FSI
ci = confidence_intervals(pipe.result_)
print(ci.summary())

# Certify which features are top-k across ALL models (worst-case guarantee)
cert = robust_certification(pipe.result_)
print(cert.certified[5])  # features certified top-5

# Theory bridge: predict flip rates from impossibility theorem formulas
tb = theory_bridge(pipe.result_)
print(tb.summary())       # SNR per pair, predicted flip rates, M recommendation

# Label each feature: robust / collinear / fragile / unimportant
flags = causal_flags(pipe.result_, X_ref=X_ref)
print(flags.summary())

# Structured audit report with warnings for stakeholders
report = audit_report(pipe.result_, X_ref=X_ref, causal=flags)
print(report.summary())

# Monitor explanation drift between model versions
monitor = DriftMonitor(pipe.result_, threshold=0.1)
alert = monitor.check(new_result, label="v2")
if alert.drifted:
    print(f"Drift: {alert.distance:.3f}, changed: {alert.changed_features}")

# Combine results from multiple sites without sharing data
fed = federated_consensus([result_site1, result_site2])
print(f"Cross-site agreement: {fed.cross_site_agreement:.3f}")

All 12 extensions: confidence_intervals, partial_order, feature_groups, stable_feature_selection, local_uncertainty, robust_certification, theory_bridge, causal_flags, audit_report, DriftMonitor, ParetoSelector, federated_consensus.

How It Works

DASH is a five-stage pipeline:

  1. Population — Train M independent models with random hyperparameters and restricted feature access, so each model explores different features
  2. Filtering — Keep models within ε of the best validation score
  3. Diversity Selection — Greedy MaxMin selection maximizing pairwise distance among importance vectors
  4. Consensus — Compute attributions for each selected model, then average
  5. Diagnostics — Feature Stability Index (FSI), IS plots, and coverage conflict (sign-stability diagnostic) for auditing without ground truth

The key insight: model independence — not model size — is what cancels the arbitrary noise. A colsample ablation confirms that forced low colsample_bytree (0.1–0.5) is the operative diversity mechanism: ensembles with unrestricted feature access achieve only single-best-level stability. See the paper for the full mechanism analysis (TMLR submission under review).

Documentation

Resource Description
API Reference Complete parameter and method documentation
Extensions Guide All 12 extensions with worked examples, organized by use case
FAQ Usage, troubleshooting, parameter guidance
Diagnostics Guide IS plots, FSI thresholds, disagreement maps
Getting Started Concept-first introduction with worked examples
Research & Benchmarks Full results, method comparisons, reproduction guide
Tutorials Step-by-step notebooks from basic to advanced

Citation

@misc{caraker2026firstmover,
  title={First-Mover Bias in Gradient Boosting Explanations: Mechanism, Detection, and Resolution},
  author={Caraker, Drake and Arnold, Bryan and Rhoads, David},
  year={2026},
  eprint={2603.22346},
  archiveprefix={arXiv},
  primaryclass={cs.LG},
  doi={10.5281/zenodo.19060132},
  url={https://arxiv.org/abs/2603.22346}
}

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dash_shap-0.2.1.tar.gz (116.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dash_shap-0.2.1-py3-none-any.whl (110.8 kB view details)

Uploaded Python 3

File details

Details for the file dash_shap-0.2.1.tar.gz.

File metadata

  • Download URL: dash_shap-0.2.1.tar.gz
  • Upload date:
  • Size: 116.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for dash_shap-0.2.1.tar.gz
Algorithm Hash digest
SHA256 6dfc94972cf8e345734630035091ccbce80a6abd640dce60748d0e788df38855
MD5 0c7040d8927805c0950bc41ec843dfed
BLAKE2b-256 852f862e6df82e5ec6a44dec258547338f4fd4ca0cb7e02cd510760a1b504e6b

See more details on using hashes here.

File details

Details for the file dash_shap-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: dash_shap-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 110.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for dash_shap-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d8aff1282c0c92b231d711f4e31b1c352dcff0eb0cbc87d14c42ba15cdaa7667
MD5 ff7ea2373818bf2ef124768a03d0084c
BLAKE2b-256 4d6cabf19778c52efaa57aa1e26899da85d6a81e8a0614ba0c89c7cbcdaf721d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page