Explain

Explainability module: unified API for SHAP, LIME, PDP, interactions, and counterfactuals.

Provides a consistent interface for model explanation methods with automatic method selection based on model type.

Example

>>> import endgame as eg
>>> from endgame.explain import explain, SHAPExplainer, LIMEExplainer
>>>
>>> # One-line explanation with auto-detection
>>> explanation = explain(model, X_test)
>>> explanation.plot(kind='bar')
>>> df = explanation.to_dataframe()
>>>
>>> # Explicit SHAP
>>> shap_exp = SHAPExplainer(model)
>>> explanation = shap_exp.explain(X_test)
>>>
>>> # Explicit LIME (local)
>>> lime_exp = LIMEExplainer(model)
>>> explanation = lime_exp.explain(X_test[:1])
>>>
>>> # Partial dependence
>>> from endgame.explain import PartialDependence
>>> pdp = PartialDependence(model)
>>> explanation = pdp.explain(X_train, features=[0, 1, 2])
>>>
>>> # Feature interactions
>>> from endgame.explain import FeatureInteraction
>>> fi = FeatureInteraction(model)
>>> explanation = fi.explain(X_train)
>>>
>>> # Counterfactuals
>>> from endgame.explain import CounterfactualExplainer
>>> cf = CounterfactualExplainer(model, X_train)
>>> explanation = cf.explain(X_test[:1], desired_class=1)
endgame.explain.explain(model, X, *, method='auto', feature_names=None, random_state=None, verbose=False, **kwargs)[source]

One-line model explanation with automatic method selection.

Selects the most appropriate explanation method based on the model type and data characteristics:

  • Tree-based models (LightGBM, XGBoost, CatBoost, RandomForest, etc.) -> SHAPExplainer with TreeExplainer.

  • Linear models (LogisticRegression, Ridge, Lasso, etc.) -> SHAPExplainer with LinearExplainer.

  • Other models with n_samples <= 500 -> SHAPExplainer with KernelExplainer.

  • Other models with n_samples > 500 -> SHAPExplainer with KernelExplainer (subsampled).

Parameters:
  • model (sklearn-compatible estimator) – A fitted model.

  • X (array-like of shape (n_samples, n_features)) – Data to explain.

  • method (str, default='auto') – Explanation method: - 'auto': Auto-select (see above). - 'shap': Force SHAP. - 'lime': Force LIME. - 'pdp': Partial dependence.

  • feature_names (list of str, optional) – Feature names.

  • random_state (int, optional) – Random seed.

  • verbose (bool, default=False) – Verbose output.

  • **kwargs (Any) – Forwarded to the underlying explainer’s explain() method.

Return type:

Explanation

Returns:

Explanation – The computed explanation.

Examples

>>> from endgame.explain import explain
>>> explanation = explain(model, X_test)
>>> explanation.plot(kind='bar')
>>> print(explanation.top_features(5))
>>> df = explanation.to_dataframe()
class endgame.explain.Explanation(values, base_value=None, feature_names=None, method='', metadata=<factory>)[source]

Bases: object

Container for feature-attribution explanations.

Holds SHAP values, LIME weights, partial dependence grids, or any other per-feature attribution output. Provides convenience methods for plotting and DataFrame export.

Parameters:
values

Attribution values. Shape depends on the method: - Global: (n_features,) (mean absolute attributions). - Local: (n_samples, n_features) or (n_features,) for a

single instance.

  • PDP: (n_grid_points,) or (n_grid_1, n_grid_2) for 2-D.

Type:

np.ndarray

base_value

Expected value / base prediction the attributions are relative to.

Type:

float or np.ndarray or None

feature_names

Names corresponding to the feature axis of values.

Type:

list of str or None

method

Name of the explanation method (e.g. 'shap', 'lime').

Type:

str

metadata

Arbitrary extra information (explainer params, timings, etc.).

Type:

dict

Examples

>>> explanation.plot(kind='bar')
>>> df = explanation.to_dataframe()
values: ndarray
base_value: float | ndarray | None = None
feature_names: list[str] | None = None
method: str = ''
metadata: dict[str, Any]
plot(kind='bar', max_display=20, show=True, **kwargs)[source]

Plot the explanation.

Parameters:
  • kind (str, default='bar') – Plot type. Supported values depend on the explanation method: - 'bar': Horizontal bar chart of mean |attributions| (all methods). - 'beeswarm': SHAP beeswarm summary plot (SHAP only). - 'waterfall': Waterfall plot for a single prediction (SHAP only). - 'heatmap': SHAP heatmap of sample-level attributions. - 'force': SHAP force plot for a single prediction.

  • max_display (int, default=20) – Maximum number of features to display.

  • show (bool, default=True) – Whether to call matplotlib.pyplot.show().

  • **kwargs (Any) – Forwarded to the underlying plotting function.

Return type:

Any

Returns:

matplotlib.figure.Figure or None – The figure object when show is False.

to_dataframe()[source]

Convert explanation to a pandas DataFrame.

Return type:

DataFrame

Returns:

pd.DataFrame – DataFrame with feature names as the index and attribution values as columns.

Raises:

ImportError – If pandas is not installed.

top_features(n=10)[source]

Return the top-n most important feature names.

Parameters:

n (int, default=10) – Number of top features to return.

Return type:

list[Text]

Returns:

list of str – Feature names ordered by descending mean |attribution|.

class endgame.explain.BaseExplainer(model, feature_names=None, random_state=None, verbose=False)[source]

Bases: ABC

Abstract base class for all Endgame explainers.

Subclasses must implement explain() which returns an Explanation object.

Parameters:
  • model (sklearn-compatible estimator) – A fitted model to explain.

  • feature_names (list of str, optional) – Feature names. If None, generic names are generated.

  • random_state (int, optional) – Random seed for reproducibility.

  • verbose (bool, default=False) – Enable verbose logging.

abstractmethod explain(X, **kwargs)[source]

Generate an explanation for the given data.

Parameters:
  • X (array-like of shape (n_samples, n_features)) – Data to explain.

  • **kwargs (Any) – Method-specific arguments.

Return type:

Explanation

Returns:

Explanation – The computed explanation.

class endgame.explain.SHAPExplainer(model, explainer_type='auto', background_samples=100, max_samples=None, check_additivity=False, feature_names=None, random_state=None, verbose=False)[source]

Bases: BaseExplainer

SHAP-based explainer with automatic backend selection.

Supports TreeExplainer, LinearExplainer, DeepExplainer, and KernelExplainer. By default the most efficient backend is chosen automatically based on the model type.

Parameters:
  • model (sklearn-compatible estimator) – A fitted model.

  • explainer_type (str, default='auto') – SHAP explainer backend: - 'auto': Auto-detect from model type. - 'tree': shap.TreeExplainer (tree-based models). - 'linear': shap.LinearExplainer (linear models). - 'deep': shap.DeepExplainer (neural networks). - 'kernel': shap.KernelExplainer (model-agnostic).

  • background_samples (int, default=100) – Number of background samples for Kernel / Linear / Deep explainers.

  • max_samples (int, optional) – If set, subsample X to at most this many rows before computing SHAP values (useful for large datasets with KernelExplainer).

  • check_additivity (bool, default=False) – Whether to verify the SHAP additivity property.

  • feature_names (list of str, optional) – Feature names.

  • random_state (int, optional) – Random seed.

  • verbose (bool, default=False) – Verbose output.

Examples

>>> from endgame.explain import SHAPExplainer
>>> explainer = SHAPExplainer(model, explainer_type='auto')
>>> explanation = explainer.explain(X_test)
>>> explanation.plot(kind='beeswarm')
>>> print(explanation.top_features(5))
explain(X, *, check_additivity=None)[source]

Compute SHAP values for X.

Parameters:
  • X (array-like of shape (n_samples, n_features)) – Data to explain.

  • check_additivity (bool, optional) – Override the instance-level check_additivity setting.

Return type:

Explanation

Returns:

Explanation – An Explanation containing sample-level SHAP values of shape (n_samples, n_features).

explain_interaction(X)[source]

Compute SHAP interaction values (tree models only).

Parameters:

X (array-like of shape (n_samples, n_features)) – Data to explain.

Return type:

Explanation

Returns:

Explanation – An Explanation with values of shape (n_samples, n_features, n_features).

Raises:

ValueError – If the model is not tree-based.

class endgame.explain.LIMEExplainer(model, mode='auto', num_features=10, num_samples=5000, kernel_width=None, discretize_continuous=True, feature_names=None, random_state=None, verbose=False)[source]

Bases: BaseExplainer

LIME (Local Interpretable Model-agnostic Explanations) wrapper.

Generates local explanations by fitting an interpretable model in the neighbourhood of each instance.

Parameters:
  • model (sklearn-compatible estimator) – A fitted model with predict (regression) or predict_proba (classification).

  • mode (str, default='auto') –

    Explanation mode: - 'auto': Infer from the model (uses predict_proba when

    available).

    • 'classification': Force classification mode.

    • 'regression': Force regression mode.

  • num_features (int, default=10) – Maximum number of features in each local explanation.

  • num_samples (int, default=5000) – Size of the neighbourhood sample used by LIME.

  • kernel_width (float, optional) – Width of the exponential kernel. If None, LIME uses its default (sqrt(n_features) * 0.75).

  • discretize_continuous (bool, default=True) – Whether to discretize continuous features (LIME default).

  • feature_names (list of str, optional) – Feature names.

  • random_state (int, optional) – Random seed.

  • verbose (bool, default=False) – Verbose output.

Examples

>>> from endgame.explain import LIMEExplainer
>>> explainer = LIMEExplainer(model, mode='classification')
>>> explanation = explainer.explain(X_test[:10])
>>> explanation.plot(kind='bar')
explain(X, *, labels=None, top_labels=None)[source]

Generate LIME explanations for the rows of X.

When X has a single row, the explanation values have shape (n_features,). For multiple rows, the values have shape (n_samples, n_features) where each row is the local weight vector for that instance.

Parameters:
  • X (array-like of shape (n_samples, n_features)) – Instances to explain.

  • labels (tuple of int, optional) – Class labels to explain (classification only). Defaults to the predicted class.

  • top_labels (int, optional) – Number of top predicted classes to explain.

Return type:

Explanation

Returns:

Explanation – An Explanation with local attribution values.

class endgame.explain.PartialDependence(model, grid_resolution=50, percentiles=(0.05, 0.95), kind='average', feature_names=None, random_state=None, verbose=False)[source]

Bases: BaseExplainer

Partial Dependence computation for 1-D and 2-D feature effects.

Uses sklearn.inspection.partial_dependence() when available, with a brute-force fallback for models that do not expose the predict contract sklearn expects.

Parameters:
  • model (sklearn-compatible estimator) – A fitted model with predict (regression) or predict_proba (classification).

  • grid_resolution (int, default=50) – Number of evenly-spaced grid points along each feature axis.

  • percentiles (tuple of float, default=(0.05, 0.95)) – Lower and upper percentile bounds of the grid.

  • kind (str, default='average') – 'average' for the marginal expectation (classic PDP), or 'individual' for Individual Conditional Expectation (ICE).

  • feature_names (list of str, optional) – Feature names.

  • random_state (int, optional) – Random seed.

  • verbose (bool, default=False) – Verbose output.

Examples

>>> pdp = PartialDependence(model)
>>> # 1-D partial dependence for feature 0
>>> exp1d = pdp.explain(X_train, features=[0])
>>> exp1d.plot()
>>>
>>> # 2-D partial dependence for feature pair (0, 1)
>>> exp2d = pdp.explain(X_train, features=[(0, 1)])
>>> exp2d.plot()
explain(X, *, features=None, target_class=None)[source]

Compute partial dependence for the requested features.

Parameters:
  • X (array-like of shape (n_samples, n_features)) – Data used to marginalise over.

  • features (list of int or list of (int, int), optional) – Feature indices to compute PDP for. Each element is either a single int (1-D PDP) or a pair of ints (2-D PDP). If None, computes 1-D PDP for all features.

  • target_class (int, optional) – For classifiers, the index of the class to explain. Defaults to class 1 for binary classification.

Return type:

Explanation

Returns:

Explanation – An Explanation whose values and metadata contain PDP grids for each requested feature (set).

plot_feature(explanation, feature, *, ax=None, show=True, **kwargs)[source]

Plot partial dependence for a single feature (or pair).

Parameters:
  • explanation (Explanation) – Result from explain().

  • feature (int or (int, int)) – Feature index (or pair for 2-D).

  • ax (matplotlib.axes.Axes, optional) – Axes to plot on. If None, a new figure is created.

  • show (bool, default=True) – Whether to call plt.show().

  • **kwargs (Any) – Forwarded to matplotlib plotting functions.

Return type:

Any

Returns:

matplotlib.figure.Figure

class endgame.explain.FeatureInteraction(model, grid_resolution=25, percentiles=(0.05, 0.95), feature_names=None, random_state=None, verbose=False)[source]

Bases: BaseExplainer

Feature interaction strength via the H-statistic.

The H-statistic measures the proportion of variance in the joint partial dependence that cannot be explained by the sum of the individual partial dependences. A value of 0 means no interaction; values near 1 indicate strong interaction.

Parameters:
  • model (sklearn-compatible estimator) – A fitted model.

  • grid_resolution (int, default=25) – Number of grid points per feature for PDP estimation. Kept lower than PDP defaults for speed since we evaluate many pairs.

  • percentiles (tuple of float, default=(0.05, 0.95)) – Feature range bounds.

  • feature_names (list of str, optional) – Feature names.

  • random_state (int, optional) – Random seed.

  • verbose (bool, default=False) – Verbose output.

Examples

>>> fi = FeatureInteraction(model)
>>> explanation = fi.explain(X_train, features=[(0, 1), (2, 3)])
>>> explanation.to_dataframe()
explain(X, *, features=None, top_k=10)[source]

Compute pairwise H-statistics.

Parameters:
  • X (array-like of shape (n_samples, n_features)) – Data used for PDP computation.

  • features (list of (int, int), optional) – Feature pairs to evaluate. If None, evaluates the top_k most important features (by variance of 1-D PDP) crossed with each other.

  • top_k (int, default=10) – When features is None, use the top-k features to form pairs.

Return type:

Explanation

Returns:

Explanation – An Explanation with H-statistic values and metadata containing per-pair results.

plot_interaction_matrix(explanation, *, ax=None, show=True, **kwargs)[source]

Plot the pairwise interaction matrix as a heatmap.

Parameters:
  • explanation (Explanation) – Result from explain().

  • ax (matplotlib.axes.Axes, optional) – Axes to plot on.

  • show (bool, default=True) – Whether to call plt.show().

  • **kwargs (Any) – Forwarded to matplotlib.pyplot.imshow.

Return type:

Any

Returns:

matplotlib.figure.Figure

class endgame.explain.CounterfactualExplainer(model, training_data, continuous_features=None, outcome_name='outcome', feature_names=None, random_state=None, verbose=False)[source]

Bases: BaseExplainer

Counterfactual explanation generator using DiCE.

Finds diverse sets of minimal feature perturbations that change the model’s prediction to a desired outcome.

Parameters:
  • model (sklearn-compatible estimator) – A fitted classifier or regressor.

  • training_data (array-like or pd.DataFrame) – Training data used to define feature ranges and constraints.

  • continuous_features (list of str, optional) – Names of continuous features. If None, all features are assumed continuous.

  • outcome_name (str, default='outcome') – Name of the target column (used internally by DiCE).

  • feature_names (list of str, optional) – Feature names.

  • random_state (int, optional) – Random seed.

  • verbose (bool, default=False) – Verbose output.

Examples

>>> cf = CounterfactualExplainer(model, X_train)
>>> explanation = cf.explain(X_test[:1], desired_class=1, n_counterfactuals=3)
>>> print(explanation.metadata['counterfactuals'])
explain(X, *, desired_class='opposite', n_counterfactuals=3, method='random', features_to_vary=None, permitted_range=None)[source]

Generate counterfactual explanations.

Parameters:
  • X (array-like of shape (n_instances, n_features)) – Instance(s) to explain. Typically a single row.

  • desired_class (int or str, default='opposite') – Target class for the counterfactual. 'opposite' flips a binary prediction.

  • n_counterfactuals (int, default=3) – Number of diverse counterfactuals to generate per instance.

  • method (str, default='random') – DiCE generation method: - 'random': Random perturbation search. - 'genetic': Genetic algorithm search. - 'kdtree': KD-tree nearest-neighbour search.

  • features_to_vary (list of str, optional) – Restrict changes to these features only. If None, all features may be varied.

  • permitted_range (dict, optional) – Per-feature permitted ranges, e.g. {'age': [18, 65], 'income': [0, 200000]}.

Return type:

Explanation

Returns:

Explanation – An Explanation with: - values: Mean absolute change across counterfactuals

(feature-level importance of change).

  • metadata['counterfactuals']: DataFrame of generated counterfactuals.

  • metadata['original']: The original instance(s).