Coder Social home page Coder Social logo

deel-ai / oodeel Goto Github PK

View Code? Open in Web Editor NEW
51.0 4.0 2.0 40.7 MB

Simple, compact, and hackable post-hoc deep OOD detection for already trained tensorflow or pytorch image classifiers.

Home Page: https://deel-ai.github.io/oodeel/

License: MIT License

Python 99.40% Makefile 0.60%
deep-neural-networks out-of-distribution-detection post-hoc-analysis pytorch robustness tensorflow

oodeel's Introduction

Library Banner


Oodeel is a library that performs post-hoc deep OOD (Out-of-Distribution) detection on already trained neural network image classifiers. The philosophy of the library is to favor quality over quantity and to foster easy adoption. As a result, we provide a simple, compact and easily customizable API and carefully integrate and test each proposed baseline into a coherent framework that is designed to enable their use in tensorflow and pytorch. You can find the documentation here.

from oodeel.methods import MLS

mls = MLS()
mls.fit(model) # A tensorflow or torch model
scores, info = mls.score(ds) # ds is a tf.data.Dataset or a torch.DataLoader

Table of contents

Installation

Installation can be done using:

pip install oodeel

oodeel requires either tensorflow or pytorch to be already installed (it will not install them automatically not to mess-up with existing installations). It is regularly tested with:

Python version Pytorch version Tensorflow version
3.8 1.11 2.5
3.9 1.13 2.8
3.10 2.00 2.11

Quick Start

Now that oodeel is installed, here are some basic examples of what you can do with the available modules. See also the notebooks directory for more advanced examples.

For benchmarking with one dataset as in-distribution and another as out-of-distribution

Load in-distribution and out-of-distribution datasets.

from oodeel.datasets import OODDataset

ds_in = OODDataset(
  'mnist', load_kwargs={"split":"test"},
  backend="tensorflow").prepare(batch_size) # use backend="torch" if you prefer torch.DataLoader
ds_out = OODDataset(
  'fashion_mnist', load_kwargs={"split":"test"},
  backend="tensorflow").prepare(batch_size)

For benchmarking with a classes subset as in-distribution and another classes subset as out-of-distribution

Load a dataset and split it into an in-distribution dataset and ou-of-distribution dataset depending on its label values (a common practice of anomaly detection and open set recognition).

from oodeel.datasets import OODDataset

in_labels = [0, 1, 2, 3, 4]
oods_in, oods_out = oods_test.split_by_class(in_labels=in_labels)
ds_in = oods_in.prepare(batch_size=batch_size)
ds_out = oods_out.prepare(batch_size=batch_size)

Run an OOD method

Load an OOD method and use it on an already-trained model

from oodeel.methods import MLS

mls = MLS()
mls.fit(model)
# info contains model predictions and labels if avail
scores_in, info_in = mls.score(ds_in)
scores_out, info_out = mls.score(ds_out)

Evaluate the method

from oodeel.eval.metrics import bench_metrics

metrics = bench_metrics(
    (scores_in, scores_out),
    metrics = ["auroc", "fpr95tpr"],
    )

And visualize the results!

2D t-SNE (3D is also available).

plot_2D_features(
    model=model,
    in_dataset=ds_in,
    out_dataset=ds_out,
    output_layer_id=-2,
)

TSNE

Classical histograms and AUROC curve.

plot_ood_scores(scores_in, scores_out, log_scale=False)
plot_roc_curve(scores_in, scores_out)

AUROC

Tutorials

We propose some tutorials to get familiar with the library and its API. See the Tutorial section of the doc

What's Included

The library is based on a class, OODBaseDetector, that fits a model and then scores new samples. Some baselines use extra data, so OODBaseDetector can also fit additional data if needed. The library uses OODDataset to properly load data from different sources and prepare it for OOD detection. It can perform OOD-specific operations like adding extra OOD data for tuning with Outlier Exposure or filters according to label values for anomaly detection or open set recognition benchmarks.

Currently, oodeel includes the following baselines:

Name Link Venue Status
MLS Open-Set Recognition: a Good Closed-Set Classifier is All You Need? ICLR 2022 avail tensorflow & torch
MSP A Baseline for Detecting Misclassified and Out-of-Distribution Examples in Neural Networks ICLR 2017 avail tensorflow & torch
Mahalanobis A Simple Unified Framework for Detecting Out-of-Distribution Samples and Adversarial Attacks NeurIPS 2018 avail tensorflow or torch
Energy Energy-based Out-of-distribution Detection NeurIPS 2020 avail tensorflow or torch
Odin Enhancing The Reliability of Out-of-distribution Image Detection in Neural Networks ICLR 2018 avail tensorflow or torch
DKNN Out-of-Distribution Detection with Deep Nearest Neighbors ICML 2022 avail tensorflow or torch
VIM ViM: Out-Of-Distribution with Virtual-logit Matching CVPR 2022 avail tensorflow or torch
Entropy Likelihood Ratios for Out-of-Distribution Detection NeurIPS 2019 avail tensorflow or torch
GODIN Generalized ODIN: Detecting Out-of-Distribution Image Without Learning From Out-of-Distribution Data CVPR 2020 planned
ReAct ReAct: Out-of-distribution Detection With Rectified Activations NeurIPS 2021 avail tensorflow or torch
NMD Neural Mean Discrepancy for Efficient Out-of-Distribution Detection CVPR 2022 planned
Gram Detecting Out-of-Distribution Examples with Gram Matrices ICML 2020 avail tensorflow or torch
GEN GEN: Pushing the Limits of Softmax-Based Out-of-Distribution Detection CVPR 2023 avail tensorflow or torch
RMDS A Simple Fix to Mahalanobis Distance for Improving Near-OOD Detection preprint avail tensorflow or torch
SHE Out-of-Distribution Detection based on In-Distribution Data Patterns Memorization with Modern Hopfield Energy ICLR 2023 avail tensorflow or torch

Oodeel also includes standard training functions with data augmentation and learning rate scheduler for toy convnet models or models from keras.applications in tf_training_tools.py and torchvision.models in torch_training_tools.py files. These functions come in handy for benchmarks like leave-k-classes-out that requires retraining models on a subset of dataset classes.

Development Roadmap

  • More baselines!
  • A module for thorough visualizations (result plots and feature space visualizations)
  • Integrate model loading and uploading with hugginface's transformers library for pretraining
  • Extend the library to more diverse tasks like object detection, segmentation, NLP ...
  • Towards OOD Generalization?

Contributing

Feel free to propose your ideas or come and contribute with us on the oodeel toolbox! We have a specific document where we describe in a simple way how to make your first pull request: just here.

See Also

Other great tools in the field of OOD:

  • OpenOOD: Benchmarking Generalized Out-of-Distribution Detection
  • Pytorch-OOD: Out-of-Distribution (OOD) Detection with Deep Neural Networks based on PyTorch.
  • ADBench: Official Implement of "ADBench: Anomaly Detection Benchmark".
  • PyOD: A Comprehensive and Scalable Python Library for Outlier Detection (Anomaly Detection)
  • Anomalib: An anomaly detection library comprising state-of-the-art algorithms and features such as experiment management, hyper-parameter optimization, and edge inference.

More from the DEEL project:

  • Xplique a Python library exclusively dedicated to explaining neural networks.
  • deel-lip a Python library for training k-Lipschitz neural networks on TF.
  • Influenciae Python toolkit dedicated to computing influence values for the discovery of potentially problematic samples in a dataset.
  • deel-torchlip a Python library for training k-Lipschitz neural networks on PyTorch.
  • DEEL White paper a summary of the DEEL team on the challenges of certifiable AI and the role of data quality, representativity and explainability for this purpose.

Acknowledgments

DEEL Logo
This project received funding from the French ”Investing for the Future – PIA3” program within the Artificial and Natural Intelligence Toulouse Institute (ANITI). The authors gratefully acknowledge the support of the DEEL , a research project jointly conducted in France and Quebec.

Creators

The library was created by Paul Novello to streamline DEEL research on post-hoc deep OOD methods and foster their adoption by DEEL industrial partners. He was soon joined by Yann Pequignot, Yannick Prudent, Corentin Friedrich and Matthieu Le Goff.

Citation

If you use OODEEL for your research project, please consider citing:

@misc{oodeel,
  author = {Novello, Paul and Prudent, Yannick and Friedrich, Corentin and Pequignot, Yann and Le Goff, Matthieu},
  title = {OODEEL, a simple, compact, and hackable post-hoc deep OOD detection for already trained tensorflow or pytorch image classifiers.},
  year = {2023},
  publisher = {GitHub},
  journal = {GitHub repository},
  howpublished = {\url{https://github.com/deel-ai/oodeel}},
}

License

The package is released under MIT license.

oodeel's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

oodeel's Issues

React automatically applies to the -2th layer of the model

React is supposed to apply to the penultimate layer of the input model. However, it is not always the -2th layer because for instance:

  • there can be dropout,
  • the last layer can be a softmax alone (so the -2th a linear)
  • ...

Maybe we could add an argument when we use react to explicitly indicate the actual penultimate layer.

Feature concatenation

Concatenate the internal features, e.g. to be able to perform DKNN on several internal layers at the same time.

Solid training_funs

  • optimizer is not really an option for train_torch_models (solved in #49 )
  • Preproc and aug are in keras_app but not torch_models (solved in #65)

Clarify that we expect models without softmax activation at the end

Some methods can raise an error which is difficult to understand when a model with softmax is used. For example, VIM tries to get weights of the last layer. If last layer is Softmax, an error is raised:

W, b = self.feature_extractor.get_weights(-1)

Moreover, other methods (e.g. VIM, Energy) do not throw an error if softmax is present. But the performance are very poor and not as expected.

Suggestions:

  • clarify documentation/docstrings/etc. to force users to end their models with logits
  • OR ensure that models used do not end with activation (error assertion)
  • OR automatically remove last activation of model when fit().

Manage notebooks

At the very least, harmonise the notebooks. Perhaps host them on gcolab ?

Logits as attribute of the FeatureExtractor?

We should think about that because right now, in _score_tensor, we have to gather the logits after a forward and return it at the end of the method:

      _, logits = self.feature_extractor.predict_tensor(inputs)
      pred = logits
      pred = self.op.convert_to_numpy(pred)
      scores = -np.max(pred, axis=1)
      logits = self.op.convert_to_numpy(logits)
      return scores, logits

Also, in many baselines we need to perform a forward, e.g. in .fit, without using the logits.
Hence, automatically setting an attribute FeatureExtractor.logits when calling .predict could make the code more logical and encapsulated since we would be able not to bother with getting the logits or not, and only use them when needed.

output_layer_id should be required in the fit instead of instanciation of ood detector

Before:

dknn = DKNN(output_layer_id=[-2])
dknn.fit(model, ds_fit)

After:

dknn = DKNN()
dknn.fit(model, ds_fit, output_layer_id=[-2])

[Update]
Also, for improved clarity output_layers_id should be renamed feature_layers_id. The feature extractor would then return separately in a tuple: (1) the features (identified by feature_layers_id) and (2) the logits (output of last layer).

After v2:

dknn = DKNN()
dknn.fit(model, ds_fit, feature_layers_id=[-2])

Incompatibility ODIN and TorchFeatureExtractor

Code to reproduce:

import os
import pprint
import warnings
from dataclasses import dataclass
from typing import Iterator

import numpy as np
import tensorflow as tf
import torch
from sklearn.metrics import accuracy_score, roc_auc_score
from torch.utils.data import IterableDataset, DataLoader

from oodeel.datasets import OODDataset
from oodeel.eval.metrics import bench_metrics
from oodeel.methods import DKNN, ODIN
from oodeel.methods.mahalanobis import Mahalanobis

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

warnings.filterwarnings("ignore")

pp = pprint.PrettyPrinter()


@dataclass
class TFDSPytorchConverter(IterableDataset):
    tf_ds: tf.data.Dataset

    def __iter__(self) -> Iterator:
        for batch_x, batch_y in self.tf_ds.as_numpy_iterator():
            for sample_idx in range(batch_x.shape[0]):
                yield np.stack([batch_x[sample_idx, :, :, 0] for _ in range(3)], axis=0), batch_y[sample_idx]


if __name__ == '__main__':
    oods_in = OODDataset('mnist', split="test")
    oods_out = OODDataset('fashion_mnist', split="test")
    oods_fit = OODDataset('mnist', split="train")


    def preprocess_fn(*inputs):
        x = inputs[0] / 255
        return tuple([x] + list(inputs[1:]))


    batch_size = 8
    ds_in = oods_in.prepare(batch_size=batch_size, preprocess_fn=preprocess_fn)
    ds_out = oods_out.prepare(batch_size=batch_size, preprocess_fn=preprocess_fn)
    ds_fit = oods_fit.prepare(batch_size=batch_size, preprocess_fn=preprocess_fn, shuffle=True)

    model = torch.hub.load("chenyaofo/pytorch-cifar-models", "cifar10_resnet20", pretrained=True)

    ds_fit_pt = DataLoader(TFDSPytorchConverter(ds_fit.take(1_000)), batch_size=8)
    ds_in_pt = DataLoader(TFDSPytorchConverter(ds_in.take(500)), batch_size=8)
    ds_out_pt = DataLoader(TFDSPytorchConverter(ds_out.take(500)), batch_size=8)


    oodmodel = ODIN()
    oodmodel.fit(model, ds_fit_pt)
    scores_in = oodmodel.score(ds_in_pt)
    scores_out = oodmodel.score(ds_out_pt)

    metrics = bench_metrics(
        (scores_in, scores_out),
        metrics=["auroc", "fpr95tpr", accuracy_score, roc_auc_score],
        threshold=None
    )

    pp.pprint(metrics)

ODIN forces some default parameters (input_layer_id and maybe others) that conflicts with arguments in TorchFeatureExtractor.

Modifications may involve both ODIN and TorchFeatureExtractor. A better model trained on MNIST will be more useful to debug this.

Add VIM

Add VIM method based on:

  • PCA on feature space
  • Computation of Residuals
  • Construction of a virtual logit

General remarks on docs

We should mention that feature extractor automatically set the last activation as linear.

Add feature extractor for torch

Translate KerasFeatureExtractor into TorchFeatureExtractor.
It is unnecessary to translate the methods gradient_pred, gradient_index, and gradient_full for now because they are likely to be deprecated soon.

The class should:

  • Include the same remaining methods as KerasFeatureExtractor (an abstraction BaseFeatureExtractor will probably be created later but it is outside the scope of this MR)
  • handle pytorch data loaders (equivalent of tf.data.Datasets).

On taking the maximum projection on SHE patterns

In the original paper, SHE projects the features on all the patterns and takes the projection on that which corresponds to the predicted class. In our implementation, we simply take the maximum projection (as in mahalanobis) for implementation reasons. It does not seem to affect the results. it should be further checked.

Ref: #87 (comment)

OODDataset name is confusing

  • It lets believe the user that this is a dataset object, like tf.data.Dataset or torch.DataLoader and that it can be used like a dataset in the detectors or elsewhere.
  • The methods of OODDataset look more like utils functions to load/modify/filter/merge/prepare TF or Torch datasets.

Make the feature extractor output layer a required argument of oodmodel

Currently, output_layers_id is an Optional argument with a default value often chosen as [-2] to enforce the feature extractor to project onto the penultimate layer. However, often, the layer identified as -2 can be something else. For instance, -1 can be a softmax layer and -2 the linear layer, in which case layer[-2] is not the penultimate layer.

Proposed solution: make this argument non optional with a link to a doc tutorial showing how to properly fill this argument as an error message thrown by

assert output_layers_id is not None, "error msg with link"

[Additional suggestion, YP] : In torch, when the model is not a Sequential and the output layer id is an integer, send a warning message recommanding the user to use a string layer id instead.

Reformat doc section relative to OOD methods

OOD methods documentation: https://deel-ai.github.io/oodeel/api/methods/

The API documentation of OOD methods is messy and difficult to read. Some suggestions:

  • Do not display irrelevant private methods.
  • Find a way to make the fit method appear in the docstring. It would also be nice to have a personalized fit docstring per method.
  • Create one markdown page per method to add some examples and guidelines.

`is_from` failing on pytorch model

is_from method is only looling at the first element of the dependency model.

model = torch.hub.load("chenyaofo/pytorch-cifar-models", "cifar10_resnet20", pretrained=True)
is_from(model, "torch")
# returns False instead of True
# > class_parents = ['pytorch_cifar_models', 'torch', 'object']

It should look at all elements from class_parents and check if torch is in it. Maybe a unit test on models defined in the test of the TorchFeatureExtractor could be useful and reproduce the bug above.

Improve VIM

Improving VIM:

  • Sometimes tests do not pass
  • Hard code PCA with matmuls
  • Remove kneed ?

Create Dataset class

The Dataset class aims at making the API library agnostic, and introduces some attributes/methods specific to OOD (e.g. ood labels, filter dataset, merge dataset...). It should include functions that are currently either in utils/tool.py (dataset_length .. etc) or in data_handler (filter, merge), in which they do not fit very well.

The Dataset class:

  • is built upon tf, or numpy datasets
  • is the input of OODModel.score() method

Pytorch support might be part of this issue / PR, depending on the time spent on development.

make oodeel library agnostic

library = tensorflow or pytorch

Tasks:

  • Remove library-specific syntax from OODmodel
  • Implement other baselines with pytorch
  • Test everything on new notebooks

Improve feature extractor for intermediate outputs

Setting output_layers_id as intermediate layers can cause OOD when calling feature_extractor.predict because the obtained tensor causes OOM errors.

  • Maybe add the possibility to put an avgpooling.
  • See what other do (e.g. Hugginface)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.