oodeel 0.2.0__py3-none-any.whl → 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of oodeel might be problematic. Click here for more details.
- oodeel/__init__.py +1 -1
- oodeel/datasets/__init__.py +2 -1
- oodeel/datasets/data_handler.py +162 -94
- oodeel/datasets/deprecated/DEPRECATED_data_handler.py +236 -0
- oodeel/datasets/{ooddataset.py → deprecated/DEPRECATED_ooddataset.py} +14 -13
- oodeel/datasets/deprecated/DEPRECATED_tf_data_handler.py +671 -0
- oodeel/datasets/deprecated/DEPRECATED_torch_data_handler.py +769 -0
- oodeel/datasets/deprecated/__init__.py +31 -0
- oodeel/datasets/tf_data_handler.py +105 -167
- oodeel/datasets/torch_data_handler.py +109 -181
- oodeel/eval/metrics.py +7 -2
- oodeel/extractor/feature_extractor.py +11 -0
- oodeel/extractor/keras_feature_extractor.py +51 -1
- oodeel/extractor/torch_feature_extractor.py +103 -21
- oodeel/methods/__init__.py +16 -1
- oodeel/methods/base.py +72 -15
- oodeel/methods/dknn.py +20 -7
- oodeel/methods/energy.py +8 -0
- oodeel/methods/entropy.py +8 -0
- oodeel/methods/gen.py +118 -0
- oodeel/methods/gram.py +15 -4
- oodeel/methods/mahalanobis.py +9 -7
- oodeel/methods/mls.py +8 -0
- oodeel/methods/odin.py +8 -0
- oodeel/methods/rmds.py +122 -0
- oodeel/methods/she.py +197 -0
- oodeel/methods/vim.py +1 -1
- oodeel/preprocess/__init__.py +31 -0
- oodeel/preprocess/tf_preprocess.py +95 -0
- oodeel/preprocess/torch_preprocess.py +97 -0
- oodeel/utils/operator.py +17 -0
- oodeel/utils/tf_operator.py +15 -0
- oodeel/utils/tf_training_tools.py +2 -2
- oodeel/utils/torch_operator.py +19 -0
- {oodeel-0.2.0.dist-info → oodeel-0.3.0.dist-info}/METADATA +139 -105
- oodeel-0.3.0.dist-info/RECORD +57 -0
- {oodeel-0.2.0.dist-info → oodeel-0.3.0.dist-info}/WHEEL +1 -1
- tests/tests_tensorflow/tf_methods_utils.py +2 -1
- tests/tests_torch/torch_methods_utils.py +34 -27
- oodeel-0.2.0.dist-info/RECORD +0 -47
- {oodeel-0.2.0.dist-info → oodeel-0.3.0.dist-info/licenses}/LICENSE +0 -0
- {oodeel-0.2.0.dist-info → oodeel-0.3.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright IRT Antoine de Saint Exupéry et Université Paul Sabatier Toulouse III - All
|
|
3
|
+
# rights reserved. DEEL is a research program operated by IVADO, IRT Saint Exupéry,
|
|
4
|
+
# CRIAQ and ANITI - https://www.deel.ai/
|
|
5
|
+
#
|
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
# furnished to do so, subject to the following conditions:
|
|
12
|
+
#
|
|
13
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
# copies or substantial portions of the Software.
|
|
15
|
+
#
|
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
# SOFTWARE.
|
|
23
|
+
import numpy as np
|
|
24
|
+
import tensorflow as tf
|
|
25
|
+
|
|
26
|
+
from ..types import Optional
|
|
27
|
+
from ..types import Tuple
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class TFRandomPatchPermutation:
|
|
31
|
+
def __init__(self, patch_size: Tuple[int] = (8, 8)):
|
|
32
|
+
"""Randomly permute the patches of an image. This transformation is used in NMD
|
|
33
|
+
paper to artificially craft OOD data from ID images.
|
|
34
|
+
|
|
35
|
+
Source (NMD paper):
|
|
36
|
+
"Neural Mean Discrepancy for Efficient Out-of-Distribution Detection"
|
|
37
|
+
[link](https://arxiv.org/pdf/2104.11408.pdf)
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
patch_size (Tuple[int], optional): Patch dimensions (h, w), should be
|
|
41
|
+
divisors of the image dimensions (H, W). Defaults to (8, 8).
|
|
42
|
+
"""
|
|
43
|
+
self.patch_size = patch_size
|
|
44
|
+
|
|
45
|
+
def __call__(self, tensor: tf.Tensor, seed: Optional[int] = None):
|
|
46
|
+
"""Apply random patch permutation.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
tensor (tf.Tensor): Tensor of shape [H, W, C]
|
|
50
|
+
seed (Optinal[int]): Seed number to set for the permutation if not None.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
tf.Tensor: Transformed tensor.
|
|
54
|
+
"""
|
|
55
|
+
h, w = self.patch_size
|
|
56
|
+
H, W, C = tensor.shape
|
|
57
|
+
tensor_ = tensor
|
|
58
|
+
|
|
59
|
+
# raise warning if patch dimensions are not divisors of image dimensions
|
|
60
|
+
if H % h != 0:
|
|
61
|
+
print(
|
|
62
|
+
f"Warning! Patch height ({h}) should be a divisor of the image height"
|
|
63
|
+
+ f" ({H}). Zero padding will be added to get the correct output shape."
|
|
64
|
+
)
|
|
65
|
+
tensor_ = tensor[: -(H % h)]
|
|
66
|
+
if W % w != 0:
|
|
67
|
+
print(
|
|
68
|
+
f"Warning! Patch width ({w}) should be a divisor of the image width"
|
|
69
|
+
+ f" ({W}). Zero padding will be added to get the correct output shape."
|
|
70
|
+
)
|
|
71
|
+
tensor_ = tensor_[:, : -(W % w)]
|
|
72
|
+
|
|
73
|
+
# === patch permutation ===
|
|
74
|
+
# divide the batch of images into non-overlapping patches
|
|
75
|
+
# => [num_patches, h * w, C]
|
|
76
|
+
u = tf.transpose(
|
|
77
|
+
tf.reshape(tensor_, (H // h, h, W // w, w, C)), (0, 2, 1, 3, 4)
|
|
78
|
+
)
|
|
79
|
+
u = tf.reshape(u, (-1, h * w, C))
|
|
80
|
+
|
|
81
|
+
# permute the patches of each image in the batch
|
|
82
|
+
# => [num_patches, h * w, C]
|
|
83
|
+
# Note: we use numpy rng for deterministic index shuffling because
|
|
84
|
+
# `tf.stateless_shuffle` is still experimental
|
|
85
|
+
g = np.random.default_rng(seed=seed)
|
|
86
|
+
indices = np.arange(u.shape[0])
|
|
87
|
+
g.shuffle(indices)
|
|
88
|
+
pu = tf.gather(u, indices)
|
|
89
|
+
|
|
90
|
+
# fold the permuted patches back together
|
|
91
|
+
# => [H, W, C]
|
|
92
|
+
f = tf.transpose(tf.reshape(pu, (H // h, W // w, h, w, C)), (0, 2, 1, 3, 4))
|
|
93
|
+
f = tf.reshape(f, tensor_.shape)
|
|
94
|
+
f = tf.pad(f, tf.constant([[0, H % h], [0, W % w], [0, 0]]))
|
|
95
|
+
return f
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright IRT Antoine de Saint Exupéry et Université Paul Sabatier Toulouse III - All
|
|
3
|
+
# rights reserved. DEEL is a research program operated by IVADO, IRT Saint Exupéry,
|
|
4
|
+
# CRIAQ and ANITI - https://www.deel.ai/
|
|
5
|
+
#
|
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
# furnished to do so, subject to the following conditions:
|
|
12
|
+
#
|
|
13
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
# copies or substantial portions of the Software.
|
|
15
|
+
#
|
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
# SOFTWARE.
|
|
23
|
+
import torch
|
|
24
|
+
import torch.nn.functional as F
|
|
25
|
+
|
|
26
|
+
from ..types import Optional
|
|
27
|
+
from ..types import Tuple
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class TorchRandomPatchPermutation:
|
|
31
|
+
def __init__(self, patch_size: Tuple[int] = (8, 8)):
|
|
32
|
+
"""Randomly permute the patches of an image. This transformation is used in NMD
|
|
33
|
+
paper to artificially craft OOD data from ID images.
|
|
34
|
+
|
|
35
|
+
Source (NMD paper):
|
|
36
|
+
"Neural Mean Discrepancy for Efficient Out-of-Distribution Detection"
|
|
37
|
+
[link](https://arxiv.org/pdf/2104.11408.pdf)
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
patch_size (Tuple[int], optional): Patch dimensions (h, w), should be
|
|
41
|
+
divisors of the image dimensions (H, W). Defaults to (8, 8).
|
|
42
|
+
"""
|
|
43
|
+
self.patch_size = patch_size
|
|
44
|
+
|
|
45
|
+
def __call__(self, tensor: torch.Tensor, seed: Optional[int] = None):
|
|
46
|
+
"""Apply random patch permutation.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
tensor (torch.Tensor): Tensor of shape [C, H, W]
|
|
50
|
+
seed (Optinal[int]): Seed number to set for the permutation if not None.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
torch.Tensor: Transformed tensor.
|
|
54
|
+
"""
|
|
55
|
+
h, w = self.patch_size
|
|
56
|
+
H, W, _ = tensor.shape
|
|
57
|
+
|
|
58
|
+
# set generator if seed is not None
|
|
59
|
+
g = None
|
|
60
|
+
if seed is not None:
|
|
61
|
+
g = torch.Generator(device=tensor.device)
|
|
62
|
+
g.manual_seed(seed)
|
|
63
|
+
|
|
64
|
+
# raise warning if patch dimensions are not divisors of image dimensions
|
|
65
|
+
if H % h != 0:
|
|
66
|
+
print(
|
|
67
|
+
f"Warning! Patch height ({h}) should be a divisor of the image height"
|
|
68
|
+
+ f" ({H}). Zero padding will be added to get the correct output shape."
|
|
69
|
+
)
|
|
70
|
+
if W % w != 0:
|
|
71
|
+
print(
|
|
72
|
+
f"Warning! Patch width ({w}) should be a divisor of the image width"
|
|
73
|
+
+ f" ({W}). Zero padding will be added to get the correct output shape."
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# === patch permutation ===
|
|
77
|
+
# [C, H, W] => [1, C, H, W]
|
|
78
|
+
x = tensor.unsqueeze(0)
|
|
79
|
+
# divide the batch of images into non-overlapping patches
|
|
80
|
+
# => [1, h * w, num_patches]
|
|
81
|
+
u = F.unfold(x, kernel_size=self.patch_size, stride=self.patch_size, padding=0)
|
|
82
|
+
# permute the patches of each image in the batch
|
|
83
|
+
# => [1, h * w, num_patches]
|
|
84
|
+
pu = torch.cat(
|
|
85
|
+
[b_[:, torch.randperm(b_.shape[-1], generator=g)][None, ...] for b_ in u],
|
|
86
|
+
dim=0,
|
|
87
|
+
)
|
|
88
|
+
# fold the permuted patches back together
|
|
89
|
+
# => [1, C, H, W]
|
|
90
|
+
f = F.fold(
|
|
91
|
+
pu,
|
|
92
|
+
x.shape[-2:],
|
|
93
|
+
kernel_size=self.patch_size,
|
|
94
|
+
stride=self.patch_size,
|
|
95
|
+
padding=0,
|
|
96
|
+
)
|
|
97
|
+
return f.squeeze(0)
|
oodeel/utils/operator.py
CHANGED
|
@@ -221,6 +221,11 @@ class Operator(ABC):
|
|
|
221
221
|
"unsqueeze/expand_dim along dim"
|
|
222
222
|
raise NotImplementedError()
|
|
223
223
|
|
|
224
|
+
@staticmethod
|
|
225
|
+
def squeeze(tensor: TensorType, dim: int = None) -> TensorType:
|
|
226
|
+
"squeeze along dim"
|
|
227
|
+
raise NotImplementedError()
|
|
228
|
+
|
|
224
229
|
@staticmethod
|
|
225
230
|
def abs(tensor: TensorType) -> TensorType:
|
|
226
231
|
"compute absolute value"
|
|
@@ -234,3 +239,15 @@ class Operator(ABC):
|
|
|
234
239
|
) -> TensorType:
|
|
235
240
|
"Applies where function to condition"
|
|
236
241
|
raise NotImplementedError()
|
|
242
|
+
|
|
243
|
+
@staticmethod
|
|
244
|
+
@abstractmethod
|
|
245
|
+
def avg_pool_2d(tensor: TensorType) -> TensorType:
|
|
246
|
+
"""Perform avg pool in 2d as in torch.nn.functional.adaptive_avg_pool2d"""
|
|
247
|
+
raise NotImplementedError()
|
|
248
|
+
|
|
249
|
+
@staticmethod
|
|
250
|
+
@abstractmethod
|
|
251
|
+
def log(tensor: TensorType) -> TensorType:
|
|
252
|
+
"""Perform log"""
|
|
253
|
+
raise NotImplementedError()
|
oodeel/utils/tf_operator.py
CHANGED
|
@@ -231,6 +231,11 @@ class TFOperator(Operator):
|
|
|
231
231
|
"expand_dim along dim"
|
|
232
232
|
return tf.expand_dims(tensor, dim)
|
|
233
233
|
|
|
234
|
+
@staticmethod
|
|
235
|
+
def squeeze(tensor: TensorType, dim: int = None) -> tf.Tensor:
|
|
236
|
+
"expand_dim along dim"
|
|
237
|
+
return tf.squeeze(tensor, dim)
|
|
238
|
+
|
|
234
239
|
@staticmethod
|
|
235
240
|
def abs(tensor: TensorType) -> tf.Tensor:
|
|
236
241
|
"compute absolute value"
|
|
@@ -248,3 +253,13 @@ class TFOperator(Operator):
|
|
|
248
253
|
@staticmethod
|
|
249
254
|
def percentile(x, q):
|
|
250
255
|
return tfp.stats.percentile(x, q)
|
|
256
|
+
|
|
257
|
+
@staticmethod
|
|
258
|
+
def avg_pool_2d(tensor: TensorType) -> tf.Tensor:
|
|
259
|
+
"""Perform avg pool in 2d as in torch.nn.functional.adaptive_avg_pool2d"""
|
|
260
|
+
return tf.reduce_mean(tensor, axis=(-3, -2))
|
|
261
|
+
|
|
262
|
+
@staticmethod
|
|
263
|
+
def log(tensor: TensorType) -> tf.Tensor:
|
|
264
|
+
"""Perform log"""
|
|
265
|
+
return tf.math.log(tensor)
|
|
@@ -81,8 +81,8 @@ def get_toy_keras_convnet(num_classes: int) -> tf.keras.Model:
|
|
|
81
81
|
def train_tf_model(
|
|
82
82
|
train_data: tf.data.Dataset,
|
|
83
83
|
model: Union[tf.keras.Model, str],
|
|
84
|
-
input_shape: tuple,
|
|
85
|
-
num_classes: int,
|
|
84
|
+
input_shape: tuple = None,
|
|
85
|
+
num_classes: int = None,
|
|
86
86
|
batch_size: int = 128,
|
|
87
87
|
epochs: int = 50,
|
|
88
88
|
loss: str = "sparse_categorical_crossentropy",
|
oodeel/utils/torch_operator.py
CHANGED
|
@@ -254,6 +254,15 @@ class TorchOperator(Operator):
|
|
|
254
254
|
"unsqueeze along dim"
|
|
255
255
|
return torch.unsqueeze(tensor, dim)
|
|
256
256
|
|
|
257
|
+
@staticmethod
|
|
258
|
+
def squeeze(tensor: TensorType, dim: int = None) -> torch.Tensor:
|
|
259
|
+
"squeeze along dim"
|
|
260
|
+
|
|
261
|
+
if dim is None:
|
|
262
|
+
return torch.squeeze(tensor)
|
|
263
|
+
|
|
264
|
+
return torch.squeeze(tensor, dim)
|
|
265
|
+
|
|
257
266
|
@staticmethod
|
|
258
267
|
def abs(tensor: TensorType) -> torch.Tensor:
|
|
259
268
|
"compute absolute value"
|
|
@@ -267,3 +276,13 @@ class TorchOperator(Operator):
|
|
|
267
276
|
) -> torch.Tensor:
|
|
268
277
|
"Applies where function , to condition"
|
|
269
278
|
return torch.where(condition, input, other)
|
|
279
|
+
|
|
280
|
+
@staticmethod
|
|
281
|
+
def avg_pool_2d(tensor: TensorType) -> torch.Tensor:
|
|
282
|
+
"""Perform avg pool in 2d as in torch.nn.functional.adaptive_avg_pool2d"""
|
|
283
|
+
return torch.mean(tensor, dim=(-2, -1))
|
|
284
|
+
|
|
285
|
+
@staticmethod
|
|
286
|
+
def log(tensor: TensorType) -> torch.Tensor:
|
|
287
|
+
"""Perform log"""
|
|
288
|
+
return torch.log(tensor)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: oodeel
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Simple, compact, and hackable post-hoc deep OOD detection for alreadytrained tensorflow or pytorch image classifiers.
|
|
5
5
|
Author: DEEL Core Team
|
|
6
6
|
Author-email: paul.novello@irt-saintexupery.com
|
|
@@ -12,104 +12,126 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist:
|
|
15
|
+
Requires-Dist: faiss_cpu
|
|
16
16
|
Requires-Dist: numpy
|
|
17
|
-
Requires-Dist:
|
|
17
|
+
Requires-Dist: scikit_learn
|
|
18
18
|
Requires-Dist: scipy
|
|
19
19
|
Requires-Dist: setuptools
|
|
20
20
|
Requires-Dist: matplotlib
|
|
21
21
|
Requires-Dist: pandas
|
|
22
22
|
Requires-Dist: seaborn
|
|
23
23
|
Requires-Dist: plotly
|
|
24
|
+
Requires-Dist: tqdm
|
|
24
25
|
Provides-Extra: dev
|
|
25
|
-
Requires-Dist: mypy
|
|
26
|
-
Requires-Dist: ipywidgets
|
|
27
|
-
Requires-Dist: mkdocs-jupyter
|
|
28
|
-
Requires-Dist: mkdocstrings-python
|
|
29
|
-
Requires-Dist: flake8
|
|
30
|
-
Requires-Dist: setuptools
|
|
31
|
-
Requires-Dist: pre-commit
|
|
32
|
-
Requires-Dist: tox
|
|
33
|
-
Requires-Dist: black
|
|
34
|
-
Requires-Dist:
|
|
35
|
-
Requires-Dist:
|
|
36
|
-
Requires-Dist:
|
|
37
|
-
Requires-Dist:
|
|
38
|
-
Requires-Dist:
|
|
39
|
-
Requires-Dist:
|
|
40
|
-
Requires-Dist:
|
|
41
|
-
Requires-Dist:
|
|
42
|
-
Requires-Dist:
|
|
43
|
-
Requires-Dist:
|
|
44
|
-
Requires-Dist:
|
|
45
|
-
Requires-Dist:
|
|
46
|
-
Requires-Dist:
|
|
47
|
-
Requires-Dist:
|
|
48
|
-
Requires-Dist:
|
|
49
|
-
Requires-Dist:
|
|
50
|
-
Requires-Dist:
|
|
51
|
-
|
|
52
|
-
Requires-Dist:
|
|
53
|
-
Requires-Dist:
|
|
54
|
-
Requires-Dist:
|
|
55
|
-
Requires-Dist: mknotebooks ; extra == 'docs'
|
|
56
|
-
Requires-Dist: ipython ; extra == 'docs'
|
|
57
|
-
Provides-Extra: tensorflow
|
|
58
|
-
Requires-Dist: tensorflow ; extra == 'tensorflow'
|
|
59
|
-
Requires-Dist: tensorflow-datasets ; extra == 'tensorflow'
|
|
60
|
-
Requires-Dist: tensorflow-probability ; extra == 'tensorflow'
|
|
26
|
+
Requires-Dist: mypy; extra == "dev"
|
|
27
|
+
Requires-Dist: ipywidgets; extra == "dev"
|
|
28
|
+
Requires-Dist: mkdocs-jupyter; extra == "dev"
|
|
29
|
+
Requires-Dist: mkdocstrings-python; extra == "dev"
|
|
30
|
+
Requires-Dist: flake8; extra == "dev"
|
|
31
|
+
Requires-Dist: setuptools; extra == "dev"
|
|
32
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
33
|
+
Requires-Dist: tox; extra == "dev"
|
|
34
|
+
Requires-Dist: black; extra == "dev"
|
|
35
|
+
Requires-Dist: ruff; extra == "dev"
|
|
36
|
+
Requires-Dist: ipython; extra == "dev"
|
|
37
|
+
Requires-Dist: ipykernel; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest; extra == "dev"
|
|
39
|
+
Requires-Dist: pylint; extra == "dev"
|
|
40
|
+
Requires-Dist: mypy; extra == "dev"
|
|
41
|
+
Requires-Dist: mkdocs; extra == "dev"
|
|
42
|
+
Requires-Dist: mkdocs-material; extra == "dev"
|
|
43
|
+
Requires-Dist: mkdocstrings; extra == "dev"
|
|
44
|
+
Requires-Dist: mknotebooks; extra == "dev"
|
|
45
|
+
Requires-Dist: mike; extra == "dev"
|
|
46
|
+
Requires-Dist: bump2version; extra == "dev"
|
|
47
|
+
Requires-Dist: docsig; extra == "dev"
|
|
48
|
+
Requires-Dist: no_implicit_optional; extra == "dev"
|
|
49
|
+
Requires-Dist: numpy==1.26.4; extra == "dev"
|
|
50
|
+
Requires-Dist: tensorflow==2.11.0; extra == "dev"
|
|
51
|
+
Requires-Dist: tensorflow_datasets; extra == "dev"
|
|
52
|
+
Requires-Dist: tensorflow_probability==0.19.0; extra == "dev"
|
|
53
|
+
Requires-Dist: timm; extra == "dev"
|
|
54
|
+
Requires-Dist: torch==1.13.1; extra == "dev"
|
|
55
|
+
Requires-Dist: torchvision==0.14.1; extra == "dev"
|
|
61
56
|
Provides-Extra: tensorflow-dev
|
|
62
|
-
Requires-Dist: mypy
|
|
63
|
-
Requires-Dist: ipywidgets
|
|
64
|
-
Requires-Dist: mkdocs-jupyter
|
|
65
|
-
Requires-Dist: mkdocstrings-python
|
|
66
|
-
Requires-Dist: flake8
|
|
67
|
-
Requires-Dist: setuptools
|
|
68
|
-
Requires-Dist: pre-commit
|
|
69
|
-
Requires-Dist: tox
|
|
70
|
-
Requires-Dist: black
|
|
71
|
-
Requires-Dist:
|
|
72
|
-
Requires-Dist:
|
|
73
|
-
Requires-Dist:
|
|
74
|
-
Requires-Dist:
|
|
75
|
-
Requires-Dist:
|
|
76
|
-
Requires-Dist:
|
|
77
|
-
Requires-Dist:
|
|
78
|
-
Requires-Dist:
|
|
79
|
-
Requires-Dist:
|
|
80
|
-
Requires-Dist:
|
|
81
|
-
Requires-Dist:
|
|
82
|
-
Requires-Dist:
|
|
83
|
-
Requires-Dist:
|
|
84
|
-
Requires-Dist:
|
|
85
|
-
|
|
86
|
-
Requires-Dist:
|
|
87
|
-
Requires-Dist:
|
|
88
|
-
Requires-Dist:
|
|
57
|
+
Requires-Dist: mypy; extra == "tensorflow-dev"
|
|
58
|
+
Requires-Dist: ipywidgets; extra == "tensorflow-dev"
|
|
59
|
+
Requires-Dist: mkdocs-jupyter; extra == "tensorflow-dev"
|
|
60
|
+
Requires-Dist: mkdocstrings-python; extra == "tensorflow-dev"
|
|
61
|
+
Requires-Dist: flake8; extra == "tensorflow-dev"
|
|
62
|
+
Requires-Dist: setuptools; extra == "tensorflow-dev"
|
|
63
|
+
Requires-Dist: pre-commit; extra == "tensorflow-dev"
|
|
64
|
+
Requires-Dist: tox; extra == "tensorflow-dev"
|
|
65
|
+
Requires-Dist: black; extra == "tensorflow-dev"
|
|
66
|
+
Requires-Dist: ruff; extra == "tensorflow-dev"
|
|
67
|
+
Requires-Dist: ipython; extra == "tensorflow-dev"
|
|
68
|
+
Requires-Dist: ipykernel; extra == "tensorflow-dev"
|
|
69
|
+
Requires-Dist: pytest; extra == "tensorflow-dev"
|
|
70
|
+
Requires-Dist: pylint; extra == "tensorflow-dev"
|
|
71
|
+
Requires-Dist: mypy; extra == "tensorflow-dev"
|
|
72
|
+
Requires-Dist: mkdocs; extra == "tensorflow-dev"
|
|
73
|
+
Requires-Dist: mkdocs-material; extra == "tensorflow-dev"
|
|
74
|
+
Requires-Dist: mkdocstrings; extra == "tensorflow-dev"
|
|
75
|
+
Requires-Dist: mknotebooks; extra == "tensorflow-dev"
|
|
76
|
+
Requires-Dist: mike; extra == "tensorflow-dev"
|
|
77
|
+
Requires-Dist: bump2version; extra == "tensorflow-dev"
|
|
78
|
+
Requires-Dist: docsig; extra == "tensorflow-dev"
|
|
79
|
+
Requires-Dist: no_implicit_optional; extra == "tensorflow-dev"
|
|
80
|
+
Requires-Dist: numpy==1.26.4; extra == "tensorflow-dev"
|
|
81
|
+
Requires-Dist: tensorflow==2.11.0; extra == "tensorflow-dev"
|
|
82
|
+
Requires-Dist: tensorflow_datasets; extra == "tensorflow-dev"
|
|
83
|
+
Requires-Dist: tensorflow_probability==0.19.0; extra == "tensorflow-dev"
|
|
89
84
|
Provides-Extra: torch-dev
|
|
90
|
-
Requires-Dist: mypy
|
|
91
|
-
Requires-Dist: ipywidgets
|
|
92
|
-
Requires-Dist: mkdocs-jupyter
|
|
93
|
-
Requires-Dist: mkdocstrings-python
|
|
94
|
-
Requires-Dist: flake8
|
|
95
|
-
Requires-Dist: setuptools
|
|
96
|
-
Requires-Dist: pre-commit
|
|
97
|
-
Requires-Dist: tox
|
|
98
|
-
Requires-Dist: black
|
|
99
|
-
Requires-Dist:
|
|
100
|
-
Requires-Dist:
|
|
101
|
-
Requires-Dist:
|
|
102
|
-
Requires-Dist:
|
|
103
|
-
Requires-Dist:
|
|
104
|
-
Requires-Dist:
|
|
105
|
-
Requires-Dist:
|
|
106
|
-
Requires-Dist:
|
|
107
|
-
Requires-Dist:
|
|
108
|
-
Requires-Dist:
|
|
109
|
-
Requires-Dist:
|
|
110
|
-
Requires-Dist:
|
|
111
|
-
Requires-Dist:
|
|
112
|
-
Requires-Dist:
|
|
85
|
+
Requires-Dist: mypy; extra == "torch-dev"
|
|
86
|
+
Requires-Dist: ipywidgets; extra == "torch-dev"
|
|
87
|
+
Requires-Dist: mkdocs-jupyter; extra == "torch-dev"
|
|
88
|
+
Requires-Dist: mkdocstrings-python; extra == "torch-dev"
|
|
89
|
+
Requires-Dist: flake8; extra == "torch-dev"
|
|
90
|
+
Requires-Dist: setuptools; extra == "torch-dev"
|
|
91
|
+
Requires-Dist: pre-commit; extra == "torch-dev"
|
|
92
|
+
Requires-Dist: tox; extra == "torch-dev"
|
|
93
|
+
Requires-Dist: black; extra == "torch-dev"
|
|
94
|
+
Requires-Dist: ruff; extra == "torch-dev"
|
|
95
|
+
Requires-Dist: ipython; extra == "torch-dev"
|
|
96
|
+
Requires-Dist: ipykernel; extra == "torch-dev"
|
|
97
|
+
Requires-Dist: pytest; extra == "torch-dev"
|
|
98
|
+
Requires-Dist: pylint; extra == "torch-dev"
|
|
99
|
+
Requires-Dist: mypy; extra == "torch-dev"
|
|
100
|
+
Requires-Dist: mkdocs; extra == "torch-dev"
|
|
101
|
+
Requires-Dist: mkdocs-material; extra == "torch-dev"
|
|
102
|
+
Requires-Dist: mkdocstrings; extra == "torch-dev"
|
|
103
|
+
Requires-Dist: mknotebooks; extra == "torch-dev"
|
|
104
|
+
Requires-Dist: mike; extra == "torch-dev"
|
|
105
|
+
Requires-Dist: bump2version; extra == "torch-dev"
|
|
106
|
+
Requires-Dist: docsig; extra == "torch-dev"
|
|
107
|
+
Requires-Dist: no_implicit_optional; extra == "torch-dev"
|
|
108
|
+
Requires-Dist: numpy==1.26.4; extra == "torch-dev"
|
|
109
|
+
Requires-Dist: timm; extra == "torch-dev"
|
|
110
|
+
Requires-Dist: torch==1.13.1; extra == "torch-dev"
|
|
111
|
+
Requires-Dist: torchvision==0.14.1; extra == "torch-dev"
|
|
112
|
+
Provides-Extra: tensorflow
|
|
113
|
+
Requires-Dist: tensorflow==2.11.0; extra == "tensorflow"
|
|
114
|
+
Requires-Dist: tensorflow_datasets; extra == "tensorflow"
|
|
115
|
+
Requires-Dist: tensorflow_probability==0.19.0; extra == "tensorflow"
|
|
116
|
+
Provides-Extra: torch
|
|
117
|
+
Requires-Dist: timm; extra == "torch"
|
|
118
|
+
Requires-Dist: torch==1.13.1; extra == "torch"
|
|
119
|
+
Requires-Dist: torchvision==0.14.1; extra == "torch"
|
|
120
|
+
Provides-Extra: docs
|
|
121
|
+
Requires-Dist: mkdocs; extra == "docs"
|
|
122
|
+
Requires-Dist: mkdocs-material; extra == "docs"
|
|
123
|
+
Requires-Dist: mkdocstrings; extra == "docs"
|
|
124
|
+
Requires-Dist: mknotebooks; extra == "docs"
|
|
125
|
+
Requires-Dist: ipython; extra == "docs"
|
|
126
|
+
Dynamic: author
|
|
127
|
+
Dynamic: author-email
|
|
128
|
+
Dynamic: classifier
|
|
129
|
+
Dynamic: description
|
|
130
|
+
Dynamic: description-content-type
|
|
131
|
+
Dynamic: license-file
|
|
132
|
+
Dynamic: provides-extra
|
|
133
|
+
Dynamic: requires-dist
|
|
134
|
+
Dynamic: summary
|
|
113
135
|
|
|
114
136
|
|
|
115
137
|
<!-- Banner section -->
|
|
@@ -125,29 +147,23 @@ Requires-Dist: torchvision ; extra == 'torch-dev'
|
|
|
125
147
|
<!-- Badge section -->
|
|
126
148
|
<div align="center">
|
|
127
149
|
<a href="#">
|
|
128
|
-
<img src="https://img.shields.io/badge/python-3.8%2B-blue">
|
|
129
|
-
</a>
|
|
150
|
+
<img src="https://img.shields.io/badge/python-3.8%2B-blue"></a>
|
|
130
151
|
<a href="https://github.com/deel-ai/oodeel/actions/workflows/python-linters.yml">
|
|
131
|
-
<img alt="Flake8" src="https://github.com/deel-ai/oodeel/actions/workflows/python-linters.yml/badge.svg">
|
|
132
|
-
</a>
|
|
152
|
+
<img alt="Flake8" src="https://github.com/deel-ai/oodeel/actions/workflows/python-linters.yml/badge.svg"></a>
|
|
133
153
|
<a href="https://github.com/deel-ai/oodeel/actions/workflows/python-tests-tf.yml">
|
|
134
|
-
<img alt="Tests tf" src="https://github.com/deel-ai/oodeel/actions/workflows/python-tests-tf.yml/badge.svg">
|
|
135
|
-
</a>
|
|
154
|
+
<img alt="Tests tf" src="https://github.com/deel-ai/oodeel/actions/workflows/python-tests-tf.yml/badge.svg"></a>
|
|
136
155
|
<a href="https://github.com/deel-ai/oodeel/actions/workflows/python-tests-torch.yml">
|
|
137
|
-
<img alt="Tests torch" src="https://github.com/deel-ai/oodeel/actions/workflows/python-tests-torch.yml/badge.svg">
|
|
138
|
-
</a>
|
|
156
|
+
<img alt="Tests torch" src="https://github.com/deel-ai/oodeel/actions/workflows/python-tests-torch.yml/badge.svg"></a>
|
|
139
157
|
<a href="https://github.com/deel-ai/oodeel/actions/workflows/python-coverage-shield.yml">
|
|
140
|
-
<img alt="Coverage" src="https://github.com/deel-ai/oodeel/raw/gh-shields/coverage.svg">
|
|
141
|
-
</a>
|
|
158
|
+
<img alt="Coverage" src="https://github.com/deel-ai/oodeel/raw/gh-shields/coverage.svg"></a>
|
|
142
159
|
<a href="https://github.com/deel-ai/oodeel/blob/master/LICENSE">
|
|
143
|
-
<img alt="License MIT" src="https://img.shields.io/badge/License-MIT-efefef">
|
|
144
|
-
</a>
|
|
160
|
+
<img alt="License MIT" src="https://img.shields.io/badge/License-MIT-efefef"></a>
|
|
145
161
|
</div>
|
|
146
162
|
<br>
|
|
147
163
|
|
|
148
164
|
<!-- Short description of your library -->
|
|
149
165
|
|
|
150
|
-
<b>Oodeel</b> is a library that performs post-hoc deep OOD 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](https://deel-ai.github.io/oodeel/).
|
|
166
|
+
<b>Oodeel</b> 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](https://deel-ai.github.io/oodeel/).
|
|
151
167
|
|
|
152
168
|
```python
|
|
153
169
|
from oodeel.methods import MLS
|
|
@@ -167,7 +183,8 @@ scores, info = mls.score(ds) # ds is a tf.data.Dataset or a torch.DataLoader
|
|
|
167
183
|
- [Contributing](#contributing)
|
|
168
184
|
- [See Also](#see-also)
|
|
169
185
|
- [Acknowledgments](#acknowledgments)
|
|
170
|
-
- [
|
|
186
|
+
- [Creators](#creators)
|
|
187
|
+
- [Citation](#citation)
|
|
171
188
|
- [License](#license)
|
|
172
189
|
|
|
173
190
|
# Installation
|
|
@@ -294,7 +311,11 @@ Currently, **oodeel** includes the following baselines:
|
|
|
294
311
|
| ReAct | [ReAct: Out-of-distribution Detection With Rectified Activations](http://arxiv.org/abs/2111.12797) | NeurIPS 2021 | avail [tensorflow](docs/notebooks/tensorflow/demo_react_tf.ipynb) or [torch](docs/notebooks/torch/demo_react_torch.ipynb) |
|
|
295
312
|
| NMD | [Neural Mean Discrepancy for Efficient Out-of-Distribution Detection](https://openaccess.thecvf.com/content/CVPR2022/html/Dong_Neural_Mean_Discrepancy_for_Efficient_Out-of-Distribution_Detection_CVPR_2022_paper.html) | CVPR 2022 | planned |
|
|
296
313
|
| Gram | [Detecting Out-of-Distribution Examples with Gram Matrices](https://proceedings.mlr.press/v119/sastry20a.html) | ICML 2020 | avail [tensorflow](docs/notebooks/tensorflow/demo_gram_tf.ipynb) or [torch](docs/notebooks/torch/demo_gram_torch.ipynb) |
|
|
297
|
-
|
|
314
|
+
| GEN | [GEN: Pushing the Limits of Softmax-Based Out-of-Distribution Detection](https://openaccess.thecvf.com/content/CVPR2023/html/Liu_GEN_Pushing_the_Limits_of_Softmax-Based_Out-of-Distribution_Detection_CVPR_2023_paper.html) | CVPR 2023 | avail [tensorflow](docs/notebooks/tensorflow/demo_gen_tf.ipynb) or [torch](docs/notebooks/torch/demo_gen_torch.ipynb) |
|
|
315
|
+
| RMDS | [A Simple Fix to Mahalanobis Distance for Improving Near-OOD Detection](https://arxiv.org/abs/2106.09022) | preprint | avail [tensorflow](docs/notebooks/tensorflow/demo_rmds_tf.ipynb) or [torch](docs/notebooks/torch/demo_rmds_torch.ipynb) |
|
|
316
|
+
| SHE | [Out-of-Distribution Detection based on In-Distribution Data Patterns Memorization with Modern Hopfield Energy](https://openreview.net/forum?id=KkazG4lgKL) | ICLR 2023 | avail [tensorflow](docs/notebooks/tensorflow/demo_she_tf.ipynb) or [torch](docs/notebooks/torch/demo_she_torch.ipynb) |
|
|
317
|
+
| ASH | [Extremely Simple Activation Shaping for Out-of-Distribution Detection](http://arxiv.org/abs/2310.00227) | ICLR 2023 | avail [tensorflow](docs/notebooks/tensorflow/demo_ash_tf.ipynb) or [torch](docs/notebooks/torch/demo_ash_torch.ipynb) |
|
|
318
|
+
| SCALE | [Scaling for Training Time and Post-hoc Out-of-distribution Detection Enhancement](https://arxiv.org/abs/2111.12797) | ICLR 2024 | avail [tensorflow](docs/notebooks/tensorflow/demo_scale_tf.ipynb) or [torch](docs/notebooks/torch/demo_scale_torch.ipynb) |
|
|
298
319
|
|
|
299
320
|
|
|
300
321
|
|
|
@@ -344,6 +365,19 @@ This project received funding from the French ”Investing for the Future – PI
|
|
|
344
365
|
|
|
345
366
|
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.
|
|
346
367
|
|
|
368
|
+
# Citation
|
|
369
|
+
|
|
370
|
+
If you use OODEEL for your research project, please consider citing:
|
|
371
|
+
```
|
|
372
|
+
@misc{oodeel,
|
|
373
|
+
author = {Novello, Paul and Prudent, Yannick and Friedrich, Corentin and Pequignot, Yann and Le Goff, Matthieu},
|
|
374
|
+
title = {OODEEL, a simple, compact, and hackable post-hoc deep OOD detection for already trained tensorflow or pytorch image classifiers.},
|
|
375
|
+
year = {2023},
|
|
376
|
+
publisher = {GitHub},
|
|
377
|
+
journal = {GitHub repository},
|
|
378
|
+
howpublished = {\url{https://github.com/deel-ai/oodeel}},
|
|
379
|
+
}
|
|
380
|
+
```
|
|
347
381
|
# License
|
|
348
382
|
|
|
349
383
|
The package is released under [MIT license](LICENSE).
|