Skip to content

liznerski/counterfactual-xad

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Reimagining Anomalies: What if Anomalies Were Normal?

Here we provide the implementation for the paper Reimagining Anomalies: What if Anomalies Were Normal?.

The implementation is based on PyTorch 2.1.2 and Python 3.10. The code is tested on Linux only.

The figure illustrates the benefit of counterfactual explanation of anomaly detectors over traditional methods, using a dataset of handwritten digits in various colors. The normal data (top left) consist of red digits and instances of the digit one in any color. An example anomaly---a green seven---is shown on the right. Conventional explanation methods localize the anomaly in the image and highlight it on a heatmap (bottom left). In contrast, the proposed method transforms the anomaly into multiple counterfactuals, addressing the crucial question: ``How must the anomaly be altered to appear normal to the detector?"

Abstract Deep learning-based methods have achieved a breakthrough in image anomaly detection, but their complexity introduces a considerable challenge to understanding why an instance is predicted to be anomalous. We introduce a novel explanation method that generates multiple alternative modifications for each anomaly, capturing diverse concepts of anomalousness. Each modification is trained to be perceived as normal by the anomaly detector. The method provides a semantic explanation of the mechanism that triggered the detector, allowing users to explore ``what-if scenarios.'' Qualitative and quantitative analyses across various image datasets demonstrate that applying this method to state-of-the-art detectors provides high-quality semantic explanations.

Citation

A PDF of our AAAI-26 paper is available at: https://arxiv.org/pdf/2402.14469.

If you use our work, please also cite the paper:

@inproceedings{
    liznerski2026reimagining,
    title={Reimagining Anomalies: {W}hat if Anomalies Were Normal?},
    author={Philipp Liznerski and Saurabh Varshneya and Ece Calikus and Puyu Wang and Alexander Bartscher and Sebastian Josef Vollmer and Sophie Fellenz and Marius Kloft},
    booktitle={Proceedings of the AAAI Conference on Artificial Intelligence},
    year={2026}
}

Table of contents

Installation

We recommend to use a virtual environment to install counterfactual-xad.

conda:

conda create -n xad python=3.10
conda activate xad
export PYTHONNOUSERSITE=1
python -m pip install -e counterfactual-xad/src

Datasets:

Apart from ImageNet-30 and ImageNet-22K, all datasets are automatically downloaded once requested.

The ImageNet-30 AD benchmark dataset can be downloaded from https://github.com/hendrycks/ss-ood, which is the data repository of the paper that introduced the benchmark. It needs to be placed in counterfactual-xad/data/datasets/imagenet_ad/train and counterfactual-xad/data/datasets/imagenet_ad/test, respectively. counterfactual-xad/ refers to the root directory of this repository.

The ImageNet-22K dataset can be downloaded from https://image-net.org/, which requires a registration. It needs to be placed in counterfactual-xad/data/datasets/imagenet22k/fall11_whole_extracted.

Training

There are several pre-configured runners available. All runners download datasets to counterfactual-xad/data/datasets and log results at counterfactual-xad/data/results. As before, counterfactual-xad/ refers to the root directory of this repository.

Train Anomaly Detector and Counterfactual Generator

All training scripts are located at counterfactual-xad/src/xad/main/. The scripts perform multiple trainings for a list of normal class sets. For each normal class set, they train separate models for different random seeds. Per default, the scripts train BCE for the one vs. rest benchmark (i.e., treats each class as a separate normal singleton). The scripts train first the AD model and then the counterfactual generator. The latter we call xtraining (for explanation training). All parameters for the xtraining have an x prefix, e.g., --x-epochs for the number of epochs.

Train with dataset {DS}:

python counterfactual-xad/src/xad/main/train_{DS}.py

For example, with colored MNIST:

python counterfactual-xad/src/xad/main/train_colored_mnist.py

There are several parameters that configure the training. Have a look at them with:

python counterfactual-xad/src/xad/main/train_colored_mnist.py -h

For example, you can train using semi-supervision with 5 samples for 50 epochs, just two different random seeds for the class sets {7,9} and {2,6}, by executing:

python counterfactual-xad/src/xad/main/train_colored_mnist.py -oe coloredmnist --epochs 50 --oe-size 5 --it 2 --classes 7+9 2+6

For another example, you can train models for CIFAR-10 with ships being normal, setting the counterfactual training epochs to 500 with an emphasis on the target anomaly score loss, by executing:

python counterfactual-xad/src/xad/main/train_cifar10.py --classes 8 --x-epochs 500 --x-lamb-asc 100

In principle, the scripts all execute the same code. They just differ in their default configuration (including network architectures and data pre-processing pipelines) for the specific datasets. Check the appendix at ArxiV for the hyperparameter configurations used for the experiments in the paper.

Log Data

All results are automatically logged in a newly created folder in counterfactual-xad/data/results/. The folder will have an auto-generated name starting with log_{YYYYMMDDHHMMSS}_, where {YYYYMMDDHHMMSS} is the current datetime (e.g., 20220128000000).

AD Training In this folder you can find all results, most importantly, a results.json file that contains the recorded class-wise AuROC scores along with some statistics like the standard deviation. There also plots for the ROCs, some figures containing image batches of the training and test loader, and network snapshots. You can find a precise enumeration below.

counterfactual-xad/data/results/log_{YYYYMMDDHHMMSS}_{COMMENT}
├── snapshots                       
│   ├── snapshot_cls{i}_it{j}.pt        # snapshot of the model and optimizer for class set {i} and the {j}-th random seed
│   ├── ...    
│   └── ...
├── hist                                # contains CDFs of the anomaly scores for training, (validation, ) and test samples for class set {i} and the {j}-th random seed   
│   ├── ...    
│   └── ...
├── scalars                             # contains training loss and training AuROC plots for each epoch             
│   ├── ...    
│   └── ...
├── eval_cls{i}-{clsname}_prc.pdf       # test precision-recall curve of cls {i} with a plot for each random seed and the legend showing the average precision
├── ...
├── eval_cls{i}-{clsname}_preview.png   # an image showing random images retrived from the test dataloader; first row for normal and second row for anomalous; with the number of samples printed on the left
├── ...
├── eval_cls{i}-{clsname}_roc.pdf       # test receiver-operator-characteristic of cls {i} with a plot for each random seedd and the legend showing the AUC
├── ...
├── eval_prc.pdf                        # test precision-recall curve over all classes
├── eval_roc.pdf                        # test receiver-operator-characteristic over all classes
├── logtxt.txt                          # contains all computed metrics in the form of human-readable text 
├── print.txt                           # a log containing most of the printed messages
├── results.json                        # contains all computed metrics in the form of computer-readable json lines (created at the end of the entire training of all models for all seeds and normal class sets)
├── setup.json                          # contains the configuration of the experiment in computer-readable format
├── meta_setup.json                     # contains the meta configuration (hostname, pid, devices, ...) of the experiment in computer-readable format
├── src.tar.gz                          # contains the complete code that was used for the experiment
├── warnings.txt                        # contains a log of certain xad warnings
├── ...
├── training__C{i}-{clsname}_preview.png
├── ...
├── training__C{i}-{clsname}_roc.pdf
└── ...

There is also a tensorboard logfile that contains most of the logged data.

Xtraining Log files for the counterfactual generator training can be found in a separate subfolder counterfactual.

counterfactual-xad/data/results/log_{YYYYMMDDHHMMSS}_{COMMENT}/counterfactual
├── conditional_generation                       
│   ├── test__C{i}-{clsname}-S{j}.pdf           # overview figure for some counterfactual generations for the test set, each row for a different condition with desired anomaly score *a* and concept *c*, the titles of the individual images show the actual anomaly score and classified concept
│   ├── test__C{i}-{clsname}-S{j}_3rows.pdf     # same as test__.. but omits all rows but the one with target anomaly score 0, which contains the counterfactuals
│   ├── test__C{i}-{clsname}-S{j}_3rows.ten     # same as above but as a raw tensor file that can be loaded via torch.load(...)
│   ├── testFix__C{i}-{clsname}-S{j}.pdf        # same as test__.. but for a fixed seed of random anomalies
│   ├── testLong__C{i}-{clsname}-S{j}.pdf       # same as test__.. but with more anomalies
│   ├── train__C{i}-{clsname}-S{j}.pdf          # overview figure for some counterfactual generations for the training set, each row for a different condition with desired anomaly score *a* and concept *c*, the titles of the individual images show the actual anomaly score and classified concept
│   └── ...
├── cycle_generation
│   ├── train__C{i}-{clsname}-S{j}.pdf          # some cycle-generated counterfactuals, i.e.; first row shows anomalies, second row a counterfactual, and the last two rows the reconstructed original with the true anomaly score 
│   └── ...
├── hist                       
│   ├── C{i}-{clsname}-S{j}__anomaly_scores.pdf  # CDF of anomaly scores for test data and counterfactuals, class set {i}, and the {j}-th random seed
│   ├── ...    
│   └── ...
├── reconstruction                       
│   ├── test__C{i}-{clsname}-S{j}.pdf           # some reconstructions of the generator for the test set, i.e., the generator is conditioned on a random concept and the true anomaly score
│   ├── train__C{i}-{clsname}-S{j}.pdf          # some reconstructions of the generator for the training set, i.e., the generator is conditioned on a random concept and the true anomaly score
│   └── ...
├── snapshots                       
│   ├── snapshot_concept-clf_cls{i}_it{j}.pt    # snapshot of the concept classifier and optimizer for class {i} and the {j}-th random seed
│   ├── snapshot_generator_cls{i}_it{j}.pt      # snapshot of the counterfactual generator and optimizer for class {i} and the {j}-th random seed
│   └── ...
├── misc.json                                   # contains miscellaneous log data
├── print.txt                                   # a log containing most of the printed messages
├── results.json                                # contains all computed counterfactual metrics in the form of computer-readable json lines (updated after each training for a seed and normal class set)
├── setup.json                                  # contains the configuration of the experiment in computer-readable format
├── meta_setup.json                             # contains the meta configuration (hostname, pid, devices, ...) of the experiment in computer-readable format
├── warnings.txt                                # contains a log of certain xad warnings
└── ...

There is also a tensorboard logfile that contains most of the logged data in more detail. Most of the figure folders also contain an "intermediate" subfolder with overview figures of reduced resolution at intermediate epochs of the xtraining.

About

This repository contains code for a method that interprets image anomaly detectors at a semantic level by modifying anomalies until they are perceived as normal by the detector.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages