oodeel 0.1.1__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/eval/plots/features.py +2 -2
- oodeel/eval/plots/plotly.py +2 -2
- oodeel/extractor/feature_extractor.py +30 -9
- oodeel/extractor/keras_feature_extractor.py +70 -13
- oodeel/extractor/torch_feature_extractor.py +120 -33
- oodeel/methods/__init__.py +17 -1
- oodeel/methods/base.py +103 -17
- oodeel/methods/dknn.py +22 -9
- oodeel/methods/energy.py +8 -0
- oodeel/methods/entropy.py +8 -0
- oodeel/methods/gen.py +118 -0
- oodeel/methods/gram.py +307 -0
- oodeel/methods/mahalanobis.py +14 -12
- 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 +5 -5
- oodeel/preprocess/__init__.py +31 -0
- oodeel/preprocess/tf_preprocess.py +95 -0
- oodeel/preprocess/torch_preprocess.py +97 -0
- oodeel/utils/operator.py +72 -2
- oodeel/utils/tf_operator.py +72 -4
- oodeel/utils/tf_training_tools.py +26 -3
- oodeel/utils/torch_operator.py +75 -4
- oodeel/utils/torch_training_tools.py +31 -2
- {oodeel-0.1.1.dist-info → oodeel-0.3.0.dist-info}/METADATA +141 -107
- oodeel-0.3.0.dist-info/RECORD +57 -0
- {oodeel-0.1.1.dist-info → oodeel-0.3.0.dist-info}/WHEEL +1 -1
- tests/tests_tensorflow/tf_methods_utils.py +2 -1
- tests/tests_torch/tools_torch.py +9 -9
- tests/tests_torch/torch_methods_utils.py +34 -27
- tests/tools_operator.py +10 -1
- oodeel-0.1.1.dist-info/RECORD +0 -46
- {oodeel-0.1.1.dist-info → oodeel-0.3.0.dist-info/licenses}/LICENSE +0 -0
- {oodeel-0.1.1.dist-info → oodeel-0.3.0.dist-info}/top_level.txt +0 -0
oodeel/methods/base.py
CHANGED
|
@@ -20,11 +20,13 @@
|
|
|
20
20
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
21
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
22
|
# SOFTWARE.
|
|
23
|
+
import inspect
|
|
23
24
|
from abc import ABC
|
|
24
25
|
from abc import abstractmethod
|
|
25
26
|
from typing import get_args
|
|
26
27
|
|
|
27
28
|
import numpy as np
|
|
29
|
+
from tqdm import tqdm
|
|
28
30
|
|
|
29
31
|
from ..extractor.feature_extractor import FeatureExtractor
|
|
30
32
|
from ..types import Callable
|
|
@@ -38,25 +40,65 @@ from ..utils import import_backend_specific_stuff
|
|
|
38
40
|
|
|
39
41
|
|
|
40
42
|
class OODBaseDetector(ABC):
|
|
41
|
-
"""
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
"""OODBaseDetector is an abstract base class for Out-of-Distribution (OOD)
|
|
44
|
+
detection.
|
|
45
|
+
|
|
46
|
+
Attributes:
|
|
47
|
+
feature_extractor (FeatureExtractor): The feature extractor instance.
|
|
48
|
+
use_react (bool): Flag to indicate if ReAct method is used.
|
|
49
|
+
use_scale (bool): Flag to indicate if scaling method is used.
|
|
50
|
+
use_ash (bool): Flag to indicate if ASH method is used.
|
|
51
|
+
react_quantile (float): Quantile value for ReAct threshold.
|
|
52
|
+
scale_percentile (float): Percentile value for scaling.
|
|
53
|
+
ash_percentile (float): Percentile value for ASH.
|
|
54
|
+
react_threshold (float): Threshold value for ReAct.
|
|
55
|
+
postproc_fns (List[Callable]): List of post-processing functions.
|
|
56
|
+
|
|
57
|
+
Methods:
|
|
58
|
+
__init__: Initializes the OODBaseDetector with specified parameters.
|
|
59
|
+
_score_tensor: Abstract method to compute OOD score for input samples.
|
|
60
|
+
_sanitize_posproc_fns: Sanitizes post-processing functions used at each layer
|
|
61
|
+
output.
|
|
62
|
+
fit: Prepares the detector for scoring by constructing the feature extractor
|
|
63
|
+
and calibrating on ID data.
|
|
64
|
+
_load_feature_extractor: Loads the feature extractor based on the model and
|
|
65
|
+
specified layers.
|
|
66
|
+
_fit_to_dataset: Abstract method to fit the OOD detector to a dataset.
|
|
67
|
+
score: Computes an OOD score for input samples.
|
|
68
|
+
compute_react_threshold: Computes the ReAct threshold using the fit dataset.
|
|
69
|
+
__call__: Convenience wrapper for the score method.
|
|
70
|
+
requires_to_fit_dataset: Property indicating if the detector needs a fit
|
|
71
|
+
dataset.
|
|
72
|
+
requires_internal_features: Property indicating if the detector acts on
|
|
73
|
+
internal model features.
|
|
49
74
|
"""
|
|
50
75
|
|
|
51
76
|
def __init__(
|
|
52
77
|
self,
|
|
53
|
-
use_react: bool = False,
|
|
54
|
-
|
|
78
|
+
use_react: Optional[bool] = False,
|
|
79
|
+
use_scale: Optional[bool] = False,
|
|
80
|
+
use_ash: Optional[bool] = False,
|
|
81
|
+
react_quantile: Optional[float] = None,
|
|
82
|
+
scale_percentile: Optional[float] = None,
|
|
83
|
+
ash_percentile: Optional[float] = None,
|
|
84
|
+
postproc_fns: Optional[List[Callable]] = None,
|
|
55
85
|
):
|
|
56
86
|
self.feature_extractor: FeatureExtractor = None
|
|
57
87
|
self.use_react = use_react
|
|
88
|
+
self.use_scale = use_scale
|
|
89
|
+
self.use_ash = use_ash
|
|
58
90
|
self.react_quantile = react_quantile
|
|
91
|
+
self.scale_percentile = scale_percentile
|
|
92
|
+
self.ash_percentile = ash_percentile
|
|
59
93
|
self.react_threshold = None
|
|
94
|
+
self.postproc_fns = self._sanitize_posproc_fns(postproc_fns)
|
|
95
|
+
|
|
96
|
+
if use_scale and use_react:
|
|
97
|
+
raise ValueError("Cannot use both ReAct and scale at the same time")
|
|
98
|
+
if use_scale and use_ash:
|
|
99
|
+
raise ValueError("Cannot use both ASH and scale at the same time")
|
|
100
|
+
if use_ash and use_react:
|
|
101
|
+
raise ValueError("Cannot use both ReAct and ASH at the same time")
|
|
60
102
|
|
|
61
103
|
@abstractmethod
|
|
62
104
|
def _score_tensor(self, inputs: TensorType) -> np.ndarray:
|
|
@@ -66,18 +108,44 @@ class OODBaseDetector(ABC):
|
|
|
66
108
|
|
|
67
109
|
Args:
|
|
68
110
|
inputs (TensorType): tensor to score
|
|
69
|
-
|
|
70
111
|
Returns:
|
|
71
112
|
Tuple[TensorType]: OOD scores, predicted logits
|
|
72
113
|
"""
|
|
73
114
|
raise NotImplementedError()
|
|
74
115
|
|
|
116
|
+
def _sanitize_posproc_fns(
|
|
117
|
+
self,
|
|
118
|
+
postproc_fns: Union[List[Callable], None],
|
|
119
|
+
) -> List[Callable]:
|
|
120
|
+
"""Sanitize postproc fns used at each layer output of the feature extractor.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
postproc_fns (Optional[List[Callable]], optional): List of postproc
|
|
124
|
+
functions, one per output layer. Defaults to None.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
List[Callable]: Sanitized postproc_fns list
|
|
128
|
+
"""
|
|
129
|
+
if postproc_fns is not None:
|
|
130
|
+
assert len(postproc_fns) == len(
|
|
131
|
+
self.output_layers_id
|
|
132
|
+
), "len of postproc_fns and output_layers_id must match"
|
|
133
|
+
|
|
134
|
+
def identity(x):
|
|
135
|
+
return x
|
|
136
|
+
|
|
137
|
+
postproc_fns = [identity if fn is None else fn for fn in postproc_fns]
|
|
138
|
+
|
|
139
|
+
return postproc_fns
|
|
140
|
+
|
|
75
141
|
def fit(
|
|
76
142
|
self,
|
|
77
143
|
model: Callable,
|
|
78
144
|
fit_dataset: Optional[Union[ItemType, DatasetType]] = None,
|
|
79
145
|
feature_layers_id: List[Union[int, str]] = [],
|
|
80
146
|
input_layer_id: Optional[Union[int, str]] = None,
|
|
147
|
+
verbose: bool = False,
|
|
148
|
+
**kwargs,
|
|
81
149
|
) -> None:
|
|
82
150
|
"""Prepare the detector for scoring:
|
|
83
151
|
* Constructs the feature extractor based on the model
|
|
@@ -95,6 +163,7 @@ class OODBaseDetector(ABC):
|
|
|
95
163
|
layer of the feature extractor.
|
|
96
164
|
If int, the rank of the layer in the layer list
|
|
97
165
|
If str, the name of the layer. Defaults to None.
|
|
166
|
+
verbose (bool): if True, display a progress bar. Defaults to False.
|
|
98
167
|
"""
|
|
99
168
|
(
|
|
100
169
|
self.backend,
|
|
@@ -117,7 +186,7 @@ class OODBaseDetector(ABC):
|
|
|
117
186
|
" provided to compute react activation threshold"
|
|
118
187
|
)
|
|
119
188
|
else:
|
|
120
|
-
self.compute_react_threshold(model, fit_dataset)
|
|
189
|
+
self.compute_react_threshold(model, fit_dataset, verbose=verbose)
|
|
121
190
|
|
|
122
191
|
if (feature_layers_id == []) and (self.requires_internal_features):
|
|
123
192
|
raise ValueError(
|
|
@@ -133,7 +202,9 @@ class OODBaseDetector(ABC):
|
|
|
133
202
|
)
|
|
134
203
|
|
|
135
204
|
if fit_dataset is not None:
|
|
136
|
-
self._fit_to_dataset(
|
|
205
|
+
if "verbose" in inspect.signature(self._fit_to_dataset).parameters.keys():
|
|
206
|
+
kwargs.update({"verbose": verbose})
|
|
207
|
+
self._fit_to_dataset(fit_dataset, **kwargs)
|
|
137
208
|
|
|
138
209
|
def _load_feature_extractor(
|
|
139
210
|
self,
|
|
@@ -158,11 +229,18 @@ class OODBaseDetector(ABC):
|
|
|
158
229
|
Returns:
|
|
159
230
|
FeatureExtractor: a feature extractor instance
|
|
160
231
|
"""
|
|
232
|
+
if not self.use_ash:
|
|
233
|
+
self.ash_percentile = None
|
|
234
|
+
if not self.use_scale:
|
|
235
|
+
self.scale_percentile = None
|
|
236
|
+
|
|
161
237
|
feature_extractor = self.FeatureExtractorClass(
|
|
162
238
|
model,
|
|
163
239
|
feature_layers_id=feature_layers_id,
|
|
164
240
|
input_layer_id=input_layer_id,
|
|
165
241
|
react_threshold=self.react_threshold,
|
|
242
|
+
scale_percentile=self.scale_percentile,
|
|
243
|
+
ash_percentile=self.ash_percentile,
|
|
166
244
|
)
|
|
167
245
|
return feature_extractor
|
|
168
246
|
|
|
@@ -180,12 +258,14 @@ class OODBaseDetector(ABC):
|
|
|
180
258
|
def score(
|
|
181
259
|
self,
|
|
182
260
|
dataset: Union[ItemType, DatasetType],
|
|
261
|
+
verbose: bool = False,
|
|
183
262
|
) -> np.ndarray:
|
|
184
263
|
"""
|
|
185
264
|
Computes an OOD score for input samples "inputs".
|
|
186
265
|
|
|
187
266
|
Args:
|
|
188
267
|
dataset (Union[ItemType, DatasetType]): dataset or tensors to score
|
|
268
|
+
verbose (bool): if True, display a progress bar. Defaults to False.
|
|
189
269
|
|
|
190
270
|
Returns:
|
|
191
271
|
tuple: scores or list of scores (depending on the input) and a dictionary
|
|
@@ -209,7 +289,7 @@ class OODBaseDetector(ABC):
|
|
|
209
289
|
scores = np.array([])
|
|
210
290
|
logits = None
|
|
211
291
|
|
|
212
|
-
for item in dataset:
|
|
292
|
+
for item in tqdm(dataset, desc="Scoring", disable=not verbose):
|
|
213
293
|
tensor = self.data_handler.get_input_from_dataset_item(item)
|
|
214
294
|
score_batch = self._score_tensor(tensor)
|
|
215
295
|
logits_batch = self.op.convert_to_numpy(
|
|
@@ -240,10 +320,16 @@ class OODBaseDetector(ABC):
|
|
|
240
320
|
info = dict(labels=labels, logits=logits)
|
|
241
321
|
return scores, info
|
|
242
322
|
|
|
243
|
-
def compute_react_threshold(
|
|
323
|
+
def compute_react_threshold(
|
|
324
|
+
self, model: Callable, fit_dataset: DatasetType, verbose: bool = False
|
|
325
|
+
):
|
|
244
326
|
penult_feat_extractor = self._load_feature_extractor(model, [-2])
|
|
245
|
-
unclipped_features, _ = penult_feat_extractor.predict(
|
|
246
|
-
|
|
327
|
+
unclipped_features, _ = penult_feat_extractor.predict(
|
|
328
|
+
fit_dataset, verbose=verbose
|
|
329
|
+
)
|
|
330
|
+
self.react_threshold = self.op.quantile(
|
|
331
|
+
unclipped_features[0], self.react_quantile
|
|
332
|
+
)
|
|
247
333
|
|
|
248
334
|
def __call__(self, inputs: Union[ItemType, DatasetType]) -> np.ndarray:
|
|
249
335
|
"""
|
oodeel/methods/dknn.py
CHANGED
|
@@ -38,30 +38,43 @@ class DKNN(OODBaseDetector):
|
|
|
38
38
|
Args:
|
|
39
39
|
nearest: number of nearest neighbors to consider.
|
|
40
40
|
Defaults to 1.
|
|
41
|
+
use_gpu (bool): Flag to enable GPU acceleration for FAISS. Defaults to False.
|
|
41
42
|
"""
|
|
42
43
|
|
|
43
|
-
def __init__(
|
|
44
|
-
self,
|
|
45
|
-
nearest: int = 1,
|
|
46
|
-
):
|
|
44
|
+
def __init__(self, nearest: int = 50, use_gpu: bool = False):
|
|
47
45
|
super().__init__()
|
|
48
|
-
|
|
49
46
|
self.index = None
|
|
50
47
|
self.nearest = nearest
|
|
48
|
+
self.use_gpu = use_gpu
|
|
49
|
+
|
|
50
|
+
if self.use_gpu:
|
|
51
|
+
try:
|
|
52
|
+
self.res = faiss.StandardGpuResources()
|
|
53
|
+
except AttributeError as e:
|
|
54
|
+
raise ImportError(
|
|
55
|
+
"faiss-gpu is not installed, but use_gpu was set to True."
|
|
56
|
+
+ "Please install faiss-gpu or set use_gpu to False."
|
|
57
|
+
) from e
|
|
51
58
|
|
|
52
59
|
def _fit_to_dataset(self, fit_dataset: Union[TensorType, DatasetType]) -> None:
|
|
53
60
|
"""
|
|
54
61
|
Constructs the index from ID data "fit_dataset", which will be used for
|
|
55
|
-
nearest neighbor search.
|
|
62
|
+
nearest neighbor search. Can operate on CPU or GPU based on the `use_gpu` flag.
|
|
56
63
|
|
|
57
64
|
Args:
|
|
58
65
|
fit_dataset: input dataset (ID) to construct the index with.
|
|
59
66
|
"""
|
|
60
67
|
fit_projected, _ = self.feature_extractor.predict(fit_dataset)
|
|
61
|
-
fit_projected = self.op.convert_to_numpy(fit_projected)
|
|
68
|
+
fit_projected = self.op.convert_to_numpy(fit_projected[0])
|
|
62
69
|
fit_projected = fit_projected.reshape(fit_projected.shape[0], -1)
|
|
63
70
|
norm_fit_projected = self._l2_normalization(fit_projected)
|
|
64
|
-
|
|
71
|
+
|
|
72
|
+
if self.use_gpu:
|
|
73
|
+
cpu_index = faiss.IndexFlatL2(norm_fit_projected.shape[1])
|
|
74
|
+
self.index = faiss.index_cpu_to_gpu(self.res, 0, cpu_index)
|
|
75
|
+
else:
|
|
76
|
+
self.index = faiss.IndexFlatL2(norm_fit_projected.shape[1])
|
|
77
|
+
|
|
65
78
|
self.index.add(norm_fit_projected)
|
|
66
79
|
|
|
67
80
|
def _score_tensor(self, inputs: TensorType) -> Tuple[np.ndarray]:
|
|
@@ -77,7 +90,7 @@ class DKNN(OODBaseDetector):
|
|
|
77
90
|
"""
|
|
78
91
|
|
|
79
92
|
input_projected, _ = self.feature_extractor.predict_tensor(inputs)
|
|
80
|
-
input_projected = self.op.convert_to_numpy(input_projected)
|
|
93
|
+
input_projected = self.op.convert_to_numpy(input_projected[0])
|
|
81
94
|
input_projected = input_projected.reshape(input_projected.shape[0], -1)
|
|
82
95
|
norm_input_projected = self._l2_normalization(input_projected)
|
|
83
96
|
scores, _ = self.index.search(norm_input_projected, self.nearest)
|
oodeel/methods/energy.py
CHANGED
|
@@ -59,11 +59,19 @@ class Energy(OODBaseDetector):
|
|
|
59
59
|
def __init__(
|
|
60
60
|
self,
|
|
61
61
|
use_react: bool = False,
|
|
62
|
+
use_scale: bool = False,
|
|
63
|
+
use_ash: bool = False,
|
|
62
64
|
react_quantile: float = 0.8,
|
|
65
|
+
scale_percentile: float = 0.85,
|
|
66
|
+
ash_percentile: float = 0.90,
|
|
63
67
|
):
|
|
64
68
|
super().__init__(
|
|
65
69
|
use_react=use_react,
|
|
70
|
+
use_scale=use_scale,
|
|
71
|
+
use_ash=use_ash,
|
|
66
72
|
react_quantile=react_quantile,
|
|
73
|
+
scale_percentile=scale_percentile,
|
|
74
|
+
ash_percentile=ash_percentile,
|
|
67
75
|
)
|
|
68
76
|
|
|
69
77
|
def _score_tensor(self, inputs: TensorType) -> Tuple[np.ndarray]:
|
oodeel/methods/entropy.py
CHANGED
|
@@ -52,11 +52,19 @@ class Entropy(OODBaseDetector):
|
|
|
52
52
|
def __init__(
|
|
53
53
|
self,
|
|
54
54
|
use_react: bool = False,
|
|
55
|
+
use_scale: bool = False,
|
|
56
|
+
use_ash: bool = False,
|
|
55
57
|
react_quantile: float = 0.8,
|
|
58
|
+
scale_percentile: float = 0.85,
|
|
59
|
+
ash_percentile: float = 0.90,
|
|
56
60
|
):
|
|
57
61
|
super().__init__(
|
|
58
62
|
use_react=use_react,
|
|
63
|
+
use_scale=use_scale,
|
|
64
|
+
use_ash=use_ash,
|
|
59
65
|
react_quantile=react_quantile,
|
|
66
|
+
scale_percentile=scale_percentile,
|
|
67
|
+
ash_percentile=ash_percentile,
|
|
60
68
|
)
|
|
61
69
|
|
|
62
70
|
def _score_tensor(self, inputs: TensorType) -> Tuple[np.ndarray]:
|
oodeel/methods/gen.py
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
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
|
+
|
|
25
|
+
from ..types import DatasetType
|
|
26
|
+
from ..types import TensorType
|
|
27
|
+
from ..types import Tuple
|
|
28
|
+
from .base import OODBaseDetector
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class GEN(OODBaseDetector):
|
|
32
|
+
"""
|
|
33
|
+
Generalized Entropy method for OOD detection.
|
|
34
|
+
"GEN: Pushing the Limits of Softmax-Based Out-of-Distribution Detection"
|
|
35
|
+
https://openaccess.thecvf.com/content/CVPR2023/html/Liu_GEN_Pushing_the_Limits_of_Softmax-Based_Out-of-Distribution_Detection_CVPR_2023_paper.html,
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
gamma (float): parameter for the generalized entropy. Must be between 0 and 1.
|
|
39
|
+
Defaults to 0.1.
|
|
40
|
+
k (int): number of softmax values to keep for the entropy computation. Only the
|
|
41
|
+
top-k softmax probabilities will be used. Defaults to 100.
|
|
42
|
+
use_react (bool): if true, apply ReAct method by clipping penultimate
|
|
43
|
+
activations under a threshold value.
|
|
44
|
+
react_quantile (Optional[float]): q value in the range [0, 1] used to compute
|
|
45
|
+
the react clipping threshold defined as the q-th quantile penultimate layer
|
|
46
|
+
activations. Defaults to 0.8.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
def __init__(
|
|
50
|
+
self,
|
|
51
|
+
gamma: float = 0.1,
|
|
52
|
+
k: int = 100,
|
|
53
|
+
use_react: bool = False,
|
|
54
|
+
use_scale: bool = False,
|
|
55
|
+
use_ash: bool = False,
|
|
56
|
+
react_quantile: float = 0.8,
|
|
57
|
+
scale_percentile: float = 0.85,
|
|
58
|
+
ash_percentile: float = 0.90,
|
|
59
|
+
):
|
|
60
|
+
super().__init__(
|
|
61
|
+
use_react=use_react,
|
|
62
|
+
use_scale=use_scale,
|
|
63
|
+
use_ash=use_ash,
|
|
64
|
+
react_quantile=react_quantile,
|
|
65
|
+
scale_percentile=scale_percentile,
|
|
66
|
+
ash_percentile=ash_percentile,
|
|
67
|
+
)
|
|
68
|
+
self.gamma = gamma
|
|
69
|
+
self.k = k
|
|
70
|
+
|
|
71
|
+
def _score_tensor(self, inputs: TensorType) -> Tuple[np.ndarray]:
|
|
72
|
+
"""
|
|
73
|
+
Computes an OOD score for input samples "inputs" based on
|
|
74
|
+
the distance to nearest neighbors in the feature space of self.model
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
inputs: input samples to score
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Tuple[np.ndarray]: scores, logits
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
_, logits = self.feature_extractor.predict_tensor(inputs)
|
|
84
|
+
probs = self.op.softmax(logits)
|
|
85
|
+
probs = self.op.convert_to_numpy(probs)
|
|
86
|
+
probs = np.sort(probs)[:, -self.k :] # Keep the k largest probabilities
|
|
87
|
+
scores = np.sum(probs**self.gamma * (1 - probs) ** (self.gamma), axis=-1)
|
|
88
|
+
return scores
|
|
89
|
+
|
|
90
|
+
def _fit_to_dataset(self, fit_dataset: DatasetType) -> None:
|
|
91
|
+
"""
|
|
92
|
+
Fits the OOD detector to fit_dataset.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
fit_dataset: dataset to fit the OOD detector on
|
|
96
|
+
"""
|
|
97
|
+
pass
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def requires_to_fit_dataset(self) -> bool:
|
|
101
|
+
"""
|
|
102
|
+
Whether an OOD detector needs a `fit_dataset` argument in the fit function.
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
bool: True if `fit_dataset` is required else False.
|
|
106
|
+
"""
|
|
107
|
+
return False
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def requires_internal_features(self) -> bool:
|
|
111
|
+
"""
|
|
112
|
+
Whether an OOD detector acts on internal model features.
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
bool: True if the detector perform computations on an intermediate layer
|
|
116
|
+
else False.
|
|
117
|
+
"""
|
|
118
|
+
return False
|