Awesome
Provably Robust Detection of Out-of-distribution Data (almost) for free
<p align="center"><img src="teaser.png" width="600"></p>This repo contains the code that accompanies our NeurIPS 2022 paper Provably Robust Detection of Out-of-distribution Data (almost) for free. We give both local as well as global guarantees that a classifier makes low-confidence predictions on out-of-distribution data. And here's the kicker: you can get these guarantees without loosing performance on either classification or clean OOD performance. We do this by splitting the work between a provable binary discriminator between in- and out-distribution and an off-the-shelf classifier.
Configuration
Install requirements (honestly, they are likely pretty overkill).
pip install -r requirements.txt
Configure the paths to your datasets within paths_config.py. If you want to configure different test out-distributions, please do so in the val_loader_out_dicts under utils/dataloaders/dataloading.py.
Training
All training is using the train_ProoD.py function with the hyperparameters being managed with hydra. We show code for plain training, OE and our Prood-Disc on CIFAR10:
python train_ProoD.py gpu=0 experimental=plain dataset=CIFAR10 train.train_type=plain
python train_ProoD.py gpu=0 experimental=plain dataset=CIFAR10 train.train_type=oe
python train_ProoD.py gpu=0 experimental=schedule_long dataset=CIFAR10
For Restricted ImageNet use experimental=schedule for training the binary discriminator. When a model is trained to completion it automatically gets registered in a json file in the evals/ folder. Specifically, all hyperparameters are saved and the location of the final weights is saved. These json files are managed using TinyDB. When running semi-joint training you have to provide the doc_id of the binary discriminator that you wish to use. For example, using doc_id=1 and a bias shift of 3:
python train_ProoD.py gpu=0 experimental=joint dataset=CIFAR10 train.train_type=oe architecture.detector_path=1 architecture.bias_shift=3
Evaluation
All models (trained on a single GPU) are evaluated automatically after training. If you have unevaluated models registered in the TinyDB database you can evaluate them by running
python gen_eval.py --gpu 0 --dataset CIFAR10 --doc_id 1
The evaluations are saved under the same database entry that the model is loaded from. If you want to register a model in the database that was not trained in the pipeline you have to do so manually by providing architecture args that can be understood by utils/factories.py and utils/eval_pipeline.py (adavanced usage).
For the experiments in Appendix B you can run
python gen_eval.py --gpu 0 --dataset CIFAR10 --disc_id 1 --class_id 2 --bias_shift 3
which registers a new model in the database that consists of a discriminator (loaded from doc_id=1) and a classifier (with doc_id=2) and combines them under a bias shift of 3. This new model then automatically gets evaluated.
Pre-Trained Models
The databases come pre-configured with the models shown in Table 2 in the paper. The pre-trained weights can be found here. Some weights are taken directly from ATOM or GOOD and just rehosted here for convenience. Put them under models/<dataset>/<name>.pt or reconfigure args.architecture.file_path in the respective database in order to use them. You can conveniently load models by using the function utils.model_zoo.from_database.
Cite Us
@inproceedings{meinke2022provably,
title={Provably Robust Detection of Out-of-distribution Data (almost) for free},
author={Meinke, Alexander and Bitterwolf, Julian and Hein, Matthias},
booktitle={NeurIPS},
year={2022}
}