Explainability Guide

Endgame provides a unified explainability layer that works with any sklearn-compatible model. Techniques range from one-line auto-explanation to detailed SHAP, LIME, partial dependence, interaction detection, and counterfactual generation.

Import convention: import endgame as eg


The explain() One-Liner

explain() is the fastest entry point. It inspects the model type, selects the most appropriate explanation method automatically, and returns a summary plot plus a pandas.DataFrame of feature importances.

from endgame.explain import explain

# Works with tree models, linear models, neural nets, or black-box estimators
report = explain(model, X_test)

# report.importances  — DataFrame, one row per feature
# report.plot()       — displays a bar chart of global importances

Auto-detection rules:

Model type

Method selected

Tree-based (GBDT, RF, etc.)

TreeSHAP

Linear / GLM

LinearSHAP

Neural network (PyTorch)

DeepSHAP

Any other estimator

KernelSHAP (slower, model-agnostic)

Pass method='lime' or method='shap' to override auto-detection.


SHAP Explanations

SHAPExplainer wraps the four SHAP backends behind a single class. It selects the correct backend at fit time based on the model type.

from endgame.explain import SHAPExplainer

explainer = SHAPExplainer(model)
explainer.fit(X_train)           # background dataset for KernelSHAP / DeepSHAP

# Global explanation — mean absolute SHAP value per feature
global_imp = explainer.global_importance(X_test)
explainer.plot_bar(X_test)       # bar chart of global importances
explainer.plot_beeswarm(X_test)  # beeswarm (violin-style) summary plot

# Local explanation — SHAP values for a single prediction
shap_values = explainer.explain(X_test)   # shape: (n_samples, n_features)
explainer.plot_waterfall(X_test[0])       # waterfall for the first sample
explainer.plot_force(X_test[0])           # force plot

Interaction values

# Pairwise SHAP interaction values (TreeSHAP only)
interactions = explainer.interaction_values(X_test)  # (n, n_features, n_features)
explainer.plot_interaction_heatmap(X_test)

LIME Explanations

LIMEExplainer fits a local linear model around each prediction using perturbed samples. It is model-agnostic and works with any predict_proba or predict method.

from endgame.explain import LIMEExplainer

lime = LIMEExplainer(model, mode='classification')  # 'classification' | 'regression'
lime.fit(X_train)

# Explain one instance
explanation = lime.explain(X_test[0], num_features=10)
explanation.show_in_notebook()       # interactive HTML widget
print(explanation.as_dataframe())    # feature weights as DataFrame

# Explain a batch and aggregate
batch_exp = lime.explain_batch(X_test[:50], num_features=10)
lime.plot_summary(batch_exp)

Partial Dependence

PartialDependence computes marginal effect of one or two features while averaging over all other features. Use this to understand the shape of a feature’s relationship with the target.

from endgame.explain import PartialDependence

pdp = PartialDependence(model)
pdp.fit(X_train)

# 1D partial dependence
pdp.plot(X_test, feature='age')

# 2D interaction surface (two features simultaneously)
pdp.plot_2d(X_test, features=['age', 'income'])

# Individual Conditional Expectation (ICE) curves
pdp.plot_ice(X_test, feature='age', n_samples=50, center=True)

# Return raw values without plotting
grid, avg, individual = pdp.compute(X_test, feature='age')

Feature Interactions

FeatureInteraction measures pairwise and higher-order interactions using Friedman’s H-statistic. High H-statistic values indicate that the joint effect of two features cannot be decomposed into separate individual effects.

from endgame.explain import FeatureInteraction

fi = FeatureInteraction(model)
fi.fit(X_train)

# Overall interaction strength for every feature (one number per feature)
h_overall = fi.overall_strength(X_test)

# Pairwise H-statistic matrix
h_matrix = fi.pairwise(X_test)          # DataFrame, (n_features, n_features)
fi.plot_heatmap(X_test)                  # colour-coded interaction matrix

# Top-k interacting pairs
top_pairs = fi.top_pairs(X_test, k=5)
print(top_pairs)
# feature_a  feature_b  h_statistic
# age        income       0.34
# ...

Counterfactual Explanations

CounterfactualExplainer generates the smallest-change perturbation of an input that flips the model prediction to a desired outcome class. The implementation is based on DiCE (Diverse Counterfactual Explanations).

from endgame.explain import CounterfactualExplainer

cf = CounterfactualExplainer(
    model,
    feature_names=X_train.columns.tolist(),
    categorical_features=['gender', 'education'],
)
cf.fit(X_train)

# Generate counterfactuals for one instance
counterfactuals = cf.explain(
    X_test[0],
    desired_class=1,         # the outcome we want
    n_counterfactuals=5,     # number of diverse alternatives
    proximity_weight=0.5,    # penalise large changes
    diversity_weight=1.0,    # encourage variety
)
print(counterfactuals.as_dataframe())

# Feature ranges can be constrained to realistic values
cf_constrained = CounterfactualExplainer(
    model,
    feature_names=X_train.columns.tolist(),
    feature_ranges={'age': (18, 80), 'income': (0, 500_000)},
    immutable_features=['gender'],
)
cf_constrained.fit(X_train)
result = cf_constrained.explain(X_test[0], desired_class=1)

Comparing Multiple Explanation Methods

Use explain() with method='all' to run every applicable method and return a side-by-side comparison:

from endgame.explain import explain

report = explain(model, X_test, method='all', n_samples=100)
report.compare()    # prints agreement metrics across methods
report.plot_all()   # grid of summary plots

Saving Explanation Reports

report = explain(model, X_test)
report.save_html('explanation_report.html')   # standalone HTML with plots
report.save_json('explanation_report.json')   # feature importances as JSON

API Reference

Full parameter documentation for explain, SHAPExplainer, LIMEExplainer, PartialDependence, FeatureInteraction, and CounterfactualExplainer is available in the auto-generated API reference at docs/api/explain.rst or by calling help(ClassName) at the Python prompt.