Skip to main content
Use FPDEEngine for most workflows. It stores prototypes, anchors, the baseline vector, and label lookup state so you can reuse them across explanations.

Explain one sample

from fpde import FPDEEngine

engine = FPDEEngine.fit(X_train, y_train, model=model)
attributions, details = engine.explain_one(X_test[0], lambda_hyb=0.5)

print(details["target_label"])
print(details["rival_label"])
print(details["evidence"])
details["target_label"] is the model’s highest-probability class. details["rival_label"] is the second-highest-probability class.

Explain a batch

Use explain_batch when you need both attribution rows and per-sample metadata.
attribution_matrix, details = engine.explain_batch(
    X_test[:10],
    lambda_hyb=0.5,
    normalize="l1",
)

print(attribution_matrix.shape)
print(details[0]["exactness_residual"])
Use explain_matrix when you only need the attribution matrix.
attribution_matrix = engine.explain_matrix(X_test[:10], lambda_hyb=0.5)

Select lambda_hyb

Use held-out validation data to select a fixed Hyb-FPDE mixture. The selection score combines deletion and insertion perturbation curves.
selection = engine.select_lambda(
    X_val,
    lambda_hyb_grid=(0.0, 0.25, 0.5, 0.75, 1.0),
    fractions=(0.0, 0.1, 0.3, 0.5, 0.7, 1.0),
)

best_lambda = selection.best_lambda
attributions, details = engine.explain_batch(X_test, lambda_hyb=best_lambda)
Save selection.rows with your experiment results so you can inspect the score for each candidate later. Use grid_search to compare Diff-FPDE, Cos-FPDE, and Hyb-FPDE candidate settings.
result = engine.grid_search(
    X_eval,
    lambda_hyb_grid=(0.0, 0.5, 1.0),
    normalize_grid=("l1", "none"),
    objective="blackbox_agreement",
)

print(result.best_config)
print(result.best_score)

Direct prototype functions

Use lower-level functions when you want direct control over prototypes and labels.
from fpde import class_mean_prototypes, explain_with_selected_prototypes

prototypes, labels = class_mean_prototypes(X_train, y_train)
explanation = explain_with_selected_prototypes(
    X_test[0],
    prototypes,
    labels,
    positive_label=target_label,
    negative_label=rival_label,
    mode="diff",
)

print(explanation.attributions)
print(explanation.evidence)
For repeated work, prefer FPDEEngine.

Visualize explanations

The plotting helpers exported from fpde and the compact fpde.plots namespace render FPDE attributions, prototype similarities, and perturbation curves with matplotlib. Install the optional plot extra first:
python -m pip install "fpde[plot]"
Each helper returns a matplotlib Axes you can save or arrange in a subplot.

Local attribution bar and waterfall

Use plot_attributions for a signed bar chart of one explanation, and plot_attribution_waterfall for a cumulative view.
from fpde import plot_attributions, plot_attribution_waterfall

attributions, details = engine.explain_one(X_test[0], lambda_hyb=0.5)

plot_attributions(
    attributions,
    feature_names=feature_names,
    top_k=10,
    title="Top FPDE contributions",
)

plot_attribution_waterfall(
    attributions,
    feature_names=feature_names,
    title="Cumulative FPDE evidence",
)

Batch summary with beeswarm

Use fpde.plots.beeswarm to summarize per-sample contributions across a batch, colored by feature value.
from fpde.plots import FPDEPlotExplanation, beeswarm

batch_attributions = engine.explain_matrix(X_test[:50], lambda_hyb=0.5)
plot_exp = FPDEPlotExplanation(
    values=batch_attributions,
    data=X_test[:50],
    feature_names=feature_names,
)

ax = beeswarm(plot_exp, show=False, title="FPDE contribution summary")
ax.figure.savefig("fpde_beeswarm.png", dpi=150, bbox_inches="tight")

Prototype similarity distribution

Use plot_prototype_similarity_distribution to see how the explained sample sits between the target and rival prototypes.
import numpy as np
from fpde import plot_prototype_similarity_distribution

target_idx = np.where(engine.prototype_labels == details["target_label"])[0][0]
rival_idx = np.where(engine.prototype_labels == details["rival_label"])[0][0]

plot_prototype_similarity_distribution(
    X_train,
    target_prototype=engine.prototypes[target_idx],
    rival_prototype=engine.prototypes[rival_idx],
    x=X_test[0],
    title="Prototype similarity distribution",
)

Attribution heatmap for image features

When features form an image, reshape the attribution vector with plot_attribution_image.
from fpde import plot_attribution_image

plot_attribution_image(
    attributions,
    shape=(28, 28),
    title="FPDE pixel attributions",
)

Perturbation curves

After computing deletion and insertion curves, visualize them with plot_perturbation_curves.
from fpde import perturbation_curves, plot_perturbation_curves

curves = perturbation_curves(
    model,
    X_test[0],
    attributions,
    details["target_label"],
    baseline=engine.baseline,
)

plot_perturbation_curves(curves, title="Deletion vs. insertion")

Full notebook

For an end-to-end walkthrough covering bar, waterfall, beeswarm, similarity, image, and perturbation plots on the breast cancer dataset, see examples/plot_fpde_example.ipynb in the FPDE repository.