A modular, ready-to-use Python implementation of the Search for EviDence Counterfactual algorithm (SEDC and its multiclass variant, SEDC-T) for explaining image classifiers.
Given an image and a trained classifier, SEDCT returns a counterfactual explanation: the smallest set of image regions that, when removed or replaced, flips the model's prediction. Instead of asking "why did the model predict this?", it answers "what would have to change in this image for the model to predict something else?" — a more human-interpretable framing than most post-hoc explainability methods.
This library was developed as part of a Bachelor's thesis in Artificial Intelligence, "Counterfactual Explanations for Image Classification: Implementation of a State of the Art Algorithm" (Marco Zennaro, supervised by Marco Calautti, University of Milan, 2025). The full thesis and defense presentation are included in docs/.
- How it works
- Project structure
- Installation
- Usage
- Supported frameworks
- Examples
- Limitations
- Documentation
- License
- Citation
SEDCT operates in three steps:
- Segmentation — the input image is split into segments (e.g. via superpixel algorithms), using a method of the user's choice.
- Replacement strategy — the user chooses how a removed segment is filled in (e.g. mean color, blur, a fixed value).
- Iterative search — at each iteration, the algorithm removes a candidate segment (or growing combination of segments) and re-classifies the resulting image. If the prediction flips, a counterfactual has been found. The search is greedy: it always expands the combination that has moved the classification score the most so far, without guaranteeing a globally optimal (i.e. smallest possible) result.
SEDC-T extends this to multiclass classifiers by letting the user specify a target class — the algorithm searches for the minimal perturbation that pushes the prediction specifically toward that class, rather than any class other than the original.
SEDCT/
├── sedct/ # the library
│ ├── __init__.py
│ ├── explainer.py # SEDCTExplainer — runs the algorithm
│ ├── model_wrappers.py # BaseModelWrapper, SKLearnModelWrapper, TorchModelWrapper
│ └── segmentation_wrappers.py # BaseImageSegmentation, SKLearnImageSegmentation, TorchImageSegmentation
├── examples/ # runnable notebooks showcasing the library
│ ├── classes_showcase.ipynb
│ ├── tests_sedct.ipynb
│ └── Models/ # pretrained weights used by the examples (Git LFS)
├── notebooks/
│ └── data_collection_and_visualization.ipynb # trains the demo classifiers from scratch
├── docs/
│ ├── thesis.pdf # full bachelor's thesis
│ ├── presentation.pdf # thesis defense slides
│ └── sedc-sedct-article.pdf # original SEDC / SEDC-T paper
├── pyproject.toml
├── requirements.txt
└── README.md
The library is deliberately split into three cooperating classes, following the same modularity described in the thesis (Ch. 3.2):
BaseImageSegmentation(and itsTorchImageSegmentation/SKLearnImageSegmentationsubclasses) handles image formats, segmentation, and segment replacement.BaseModelWrapper(and itsTorchModelWrapper/SKLearnModelWrappersubclasses) wraps a classifier so the algorithm can query predictions and scores without caring which framework trained the model.SEDCTExplainerties the two together and runs the SEDC/SEDC-T search.
git clone https://github.com/zenna7/SEDCT.git
cd SEDCT
pip install -e .This installs sedct as an importable package (editable mode, so local changes take effect immediately) along with its core dependencies (PyTorch, scikit-learn, NumPy, Pillow).
Some example notebooks additionally use TensorFlow, torchvision, scikit-image, and Matplotlib — install everything needed to run those with:
pip install -r requirements.txtfrom sedct import SEDCTExplainer, TorchModelWrapper, TorchImageSegmentation
# Wrap your trained PyTorch model
classifier = TorchModelWrapper(model=my_model, transform=my_preprocessing)
# Wrap the image and choose a segmentation + replacement strategy
image_segmentation = TorchImageSegmentation(
image=my_image,
segmentation_method="slic",
fill_method="mean",
)
# Run the explainer
explainer = SEDCTExplainer(classifier=classifier, image_segmentation=image_segmentation)
explainer.explain_instance(show=True)
counterfactual = explainer.get_counterfactual()
mask = explainer.get_counterfactual_mask()For multiclass models, pass target=<class_index> to explain_instance to search for a counterfactual toward a specific class (the SEDC-T variant).
See examples/ for complete, runnable notebooks against real trained classifiers.
The wrapper-based design means SEDCT isn't tied to one ML framework:
- Models: PyTorch (
TorchModelWrapper) and scikit-learn (SKLearnModelWrapper) classifiers, binary or multiclass. - Images: multiple input formats supported via
TorchImageSegmentation/SKLearnImageSegmentation(tensors, arrays, PIL images).
Extending SEDCT to a new framework means subclassing BaseModelWrapper or BaseImageSegmentation and implementing a handful of abstract methods (get_pred, get_score, compute_segmentation, remove_segment, etc.) — the core algorithm itself doesn't need to change.
examples/ contains notebooks that train and load real classifiers (a ResNet18 fine-tuned on Cats vs. Dogs, a multiclass ResNet18 on tf_flowers, and scikit-learn pipelines) and run SEDCT against them end-to-end. notebooks/data_collection_and_visualization.ipynb trains the MNIST/CIFAR-10/Cats-vs-Dogs classifiers used elsewhere in the thesis experiments from scratch, if you want to reproduce those instead of using the pretrained weights in examples/Models/.
- The search is greedy, not exhaustive — it isn't guaranteed to find the smallest possible counterfactual, only a locally optimal one at each step.
- Runtime scales with the number of segments and how many need to be combined before a flip is found;
max_iterinexplain_instancecaps this at the cost of a possible "no counterfactual found" result. - Explanation quality depends heavily on the chosen segmentation method and replacement strategy — there's no single best default across all image types.
A fuller discussion of these trade-offs is in the thesis, Section 3.4.2.
docs/thesis.pdf— full write-up: literature review, algorithm design, implementation details, and experimental results on MNIST, CIFAR-10, and Cats vs. Dogs.docs/presentation.pdf— condensed defense presentation.docs/sedc-sedct-article.pdf— the original paper introducing SEDC/SEDC-T that this implementation is based on.
MIT — see LICENSE.
If you use this library, please cite the accompanying thesis:
Marco Zennaro, "Counterfactual Explanations for Image Classification:
Implementation of a State of the Art Algorithm", Bachelor's Thesis,
Bachelor in Artificial Intelligence, 2025.

