dataeval 0.72.2__tar.gz → 0.73.1__tar.gz
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.
- {dataeval-0.72.2 → dataeval-0.73.1}/PKG-INFO +3 -3
- {dataeval-0.72.2 → dataeval-0.73.1}/pyproject.toml +13 -8
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/__init__.py +3 -3
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/__init__.py +1 -1
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/drift/__init__.py +1 -1
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/drift/base.py +2 -2
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/linters/clusterer.py +1 -1
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/__init__.py +1 -1
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/ae.py +14 -6
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/aegmm.py +14 -6
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/base.py +9 -3
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/llr.py +22 -16
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/vae.py +14 -6
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/vaegmm.py +14 -6
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/interop.py +9 -7
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/bias/balance.py +50 -44
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/bias/coverage.py +38 -6
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/bias/diversity.py +117 -65
- dataeval-0.73.1/src/dataeval/metrics/bias/metadata.py +440 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/bias/parity.py +68 -54
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/__init__.py +4 -3
- dataeval-0.73.1/src/dataeval/utils/lazy.py +26 -0
- dataeval-0.73.1/src/dataeval/utils/metadata.py +258 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/shared.py +1 -1
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/split_dataset.py +12 -6
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/tensorflow/_internal/gmm.py +8 -2
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/tensorflow/_internal/loss.py +20 -11
- dataeval-0.72.2/src/dataeval/utils/tensorflow/_internal/pixelcnn.py → dataeval-0.73.1/src/dataeval/utils/tensorflow/_internal/models.py +371 -77
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/tensorflow/_internal/trainer.py +12 -5
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/tensorflow/_internal/utils.py +70 -71
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/torch/datasets.py +2 -2
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/workflows/__init__.py +1 -1
- dataeval-0.72.2/src/dataeval/metrics/bias/metadata.py +0 -275
- dataeval-0.72.2/src/dataeval/utils/tensorflow/_internal/autoencoder.py +0 -316
- {dataeval-0.72.2 → dataeval-0.73.1}/LICENSE.txt +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/README.md +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/drift/cvm.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/drift/ks.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/drift/mmd.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/drift/torch.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/drift/uncertainty.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/drift/updates.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/linters/__init__.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/linters/duplicates.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/linters/merged_stats.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/linters/outliers.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/metadata_ks_compare.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/metadata_least_likely.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/metadata_ood_mi.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/__init__.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/bias/__init__.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/estimators/__init__.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/estimators/ber.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/estimators/divergence.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/estimators/uap.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/__init__.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/base.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/boxratiostats.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/datasetstats.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/dimensionstats.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/hashstats.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/labelstats.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/pixelstats.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/visualstats.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/output.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/py.typed +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/image.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/tensorflow/__init__.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/tensorflow/loss/__init__.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/torch/__init__.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/torch/blocks.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/torch/models.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/torch/trainer.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/torch/utils.py +0 -0
- {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/workflows/sufficiency.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: dataeval
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.73.1
|
4
4
|
Summary: DataEval provides a simple interface to characterize image data and its impact on model performance across classification and object-detection tasks
|
5
5
|
Home-page: https://dataeval.ai/
|
6
6
|
License: MIT
|
@@ -31,8 +31,8 @@ Requires-Dist: pillow (>=10.3.0)
|
|
31
31
|
Requires-Dist: scikit-learn (>=1.5.0)
|
32
32
|
Requires-Dist: scipy (>=1.10)
|
33
33
|
Requires-Dist: tensorflow (>=2.16,<2.18) ; extra == "tensorflow" or extra == "all"
|
34
|
-
Requires-Dist: tensorflow_probability (>=0.24) ; extra == "tensorflow" or extra == "all"
|
35
|
-
Requires-Dist: tf-keras (>=2.16) ; extra == "tensorflow" or extra == "all"
|
34
|
+
Requires-Dist: tensorflow_probability (>=0.24,<0.25) ; extra == "tensorflow" or extra == "all"
|
35
|
+
Requires-Dist: tf-keras (>=2.16,<2.18) ; extra == "tensorflow" or extra == "all"
|
36
36
|
Requires-Dist: torch (>=2.2.0) ; extra == "torch" or extra == "all"
|
37
37
|
Requires-Dist: torchvision (>=0.17.0) ; extra == "torch" or extra == "all"
|
38
38
|
Requires-Dist: tqdm
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "dataeval"
|
3
|
-
version = "0.
|
3
|
+
version = "0.73.1" # dynamic
|
4
4
|
description = "DataEval provides a simple interface to characterize image data and its impact on model performance across classification and object-detection tasks"
|
5
5
|
license = "MIT"
|
6
6
|
readme = "README.md"
|
@@ -55,8 +55,8 @@ xxhash = {version = ">=3.3"}
|
|
55
55
|
matplotlib = {version = "*", optional = true}
|
56
56
|
markupsafe = {version = "<3.0.2", optional = true}
|
57
57
|
tensorflow = {version = ">=2.16,<2.18", optional = true}
|
58
|
-
tensorflow_probability = {version = ">=0.24", optional = true}
|
59
|
-
tf-keras = {version = ">=2.16", optional = true}
|
58
|
+
tensorflow_probability = {version = ">=0.24,<0.25", optional = true}
|
59
|
+
tf-keras = {version = ">=2.16,<2.18", optional = true}
|
60
60
|
torch = {version = ">=2.2.0", source = "pytorch", optional = true}
|
61
61
|
torchvision = {version = ">=0.17.0", source = "pytorch", optional = true}
|
62
62
|
|
@@ -69,8 +69,7 @@ all = ["matplotlib", "markupsafe", "tensorflow", "tensorflow_probability", "tf-k
|
|
69
69
|
optional = true
|
70
70
|
|
71
71
|
[tool.poetry.group.dev.dependencies]
|
72
|
-
|
73
|
-
tox-uv = {version = "*"}
|
72
|
+
nox = {version = "*", extras = ["uv"]}
|
74
73
|
uv = {version = "*"}
|
75
74
|
poetry = {version = "*"}
|
76
75
|
poetry-lock-groups-plugin = {version = "*"}
|
@@ -122,7 +121,6 @@ files = ["src/dataeval/__init__.py"]
|
|
122
121
|
name = "dataeval"
|
123
122
|
|
124
123
|
[tool.poetry2conda.dependencies]
|
125
|
-
nvidia-cudnn-cu11 = { name = "cudnn" }
|
126
124
|
tensorflow_probability = { name = "tensorflow-probability" }
|
127
125
|
torch = { name = "pytorch" }
|
128
126
|
xxhash = { name = "python-xxhash" }
|
@@ -142,12 +140,18 @@ concurrency = ["multiprocessing"]
|
|
142
140
|
parallel = true
|
143
141
|
|
144
142
|
[tool.coverage.report]
|
145
|
-
exclude_also = [
|
143
|
+
exclude_also = [
|
144
|
+
"raise NotImplementedError",
|
145
|
+
"if TYPE_CHECKING:",
|
146
|
+
"if _IS_TENSORFLOW_AVAILABLE",
|
147
|
+
"if _IS_TORCH_AVAILABLE",
|
148
|
+
"if _IS_TORCHVISION_AVAILABLE",
|
149
|
+
]
|
146
150
|
include = ["*/src/dataeval/*"]
|
147
151
|
omit = [
|
148
152
|
"*/torch/blocks.py",
|
149
153
|
"*/torch/utils.py",
|
150
|
-
"*/tensorflow/_internal/
|
154
|
+
"*/tensorflow/_internal/models.py",
|
151
155
|
]
|
152
156
|
fail_under = 90
|
153
157
|
|
@@ -161,6 +165,7 @@ exclude = [
|
|
161
165
|
"*env*",
|
162
166
|
"output",
|
163
167
|
"_build",
|
168
|
+
".nox",
|
164
169
|
".tox",
|
165
170
|
"prototype",
|
166
171
|
]
|
@@ -1,4 +1,4 @@
|
|
1
|
-
__version__ = "0.
|
1
|
+
__version__ = "0.73.1"
|
2
2
|
|
3
3
|
from importlib.util import find_spec
|
4
4
|
|
@@ -12,12 +12,12 @@ from dataeval import detectors, metrics # noqa: E402
|
|
12
12
|
|
13
13
|
__all__ = ["detectors", "metrics"]
|
14
14
|
|
15
|
-
if _IS_TORCH_AVAILABLE:
|
15
|
+
if _IS_TORCH_AVAILABLE:
|
16
16
|
from dataeval import workflows
|
17
17
|
|
18
18
|
__all__ += ["workflows"]
|
19
19
|
|
20
|
-
if _IS_TENSORFLOW_AVAILABLE or _IS_TORCH_AVAILABLE:
|
20
|
+
if _IS_TENSORFLOW_AVAILABLE or _IS_TORCH_AVAILABLE:
|
21
21
|
from dataeval import utils
|
22
22
|
|
23
23
|
__all__ += ["utils"]
|
@@ -10,7 +10,7 @@ from dataeval.detectors.drift.ks import DriftKS
|
|
10
10
|
|
11
11
|
__all__ = ["DriftCVM", "DriftKS", "DriftOutput", "updates"]
|
12
12
|
|
13
|
-
if _IS_TORCH_AVAILABLE:
|
13
|
+
if _IS_TORCH_AVAILABLE:
|
14
14
|
from dataeval.detectors.drift.mmd import DriftMMD, DriftMMDOutput
|
15
15
|
from dataeval.detectors.drift.torch import preprocess_drift
|
16
16
|
from dataeval.detectors.drift.uncertainty import DriftUncertainty
|
@@ -18,7 +18,7 @@ from typing import Any, Callable, Literal, TypeVar
|
|
18
18
|
import numpy as np
|
19
19
|
from numpy.typing import ArrayLike, NDArray
|
20
20
|
|
21
|
-
from dataeval.interop import as_numpy
|
21
|
+
from dataeval.interop import as_numpy
|
22
22
|
from dataeval.output import OutputMetadata, set_metadata
|
23
23
|
|
24
24
|
R = TypeVar("R")
|
@@ -196,7 +196,7 @@ class BaseDrift:
|
|
196
196
|
if correction not in ["bonferroni", "fdr"]:
|
197
197
|
raise ValueError("`correction` must be `bonferroni` or `fdr`.")
|
198
198
|
|
199
|
-
self._x_ref =
|
199
|
+
self._x_ref = as_numpy(x_ref)
|
200
200
|
self.x_ref_preprocessed: bool = x_ref_preprocessed
|
201
201
|
|
202
202
|
# Other attributes
|
@@ -480,7 +480,7 @@ class Clusterer:
|
|
480
480
|
samples = self.clusters[level][cluster_id].samples
|
481
481
|
if len(samples) >= self._min_num_samples_per_cluster:
|
482
482
|
duplicates_std.append(self.clusters[level][cluster_id].dist_std)
|
483
|
-
diag_mask = np.ones_like(self._sqdmat, dtype=
|
483
|
+
diag_mask = np.ones_like(self._sqdmat, dtype=np.bool_)
|
484
484
|
np.fill_diagonal(diag_mask, 0)
|
485
485
|
diag_mask = np.triu(diag_mask)
|
486
486
|
|
@@ -4,7 +4,7 @@ Out-of-distribution (OOD)` detectors identify data that is different from the da
|
|
4
4
|
|
5
5
|
from dataeval import _IS_TENSORFLOW_AVAILABLE
|
6
6
|
|
7
|
-
if _IS_TENSORFLOW_AVAILABLE:
|
7
|
+
if _IS_TENSORFLOW_AVAILABLE:
|
8
8
|
from dataeval.detectors.ood.ae import OOD_AE
|
9
9
|
from dataeval.detectors.ood.aegmm import OOD_AEGMM
|
10
10
|
from dataeval.detectors.ood.base import OODOutput, OODScoreOutput
|
@@ -10,18 +10,26 @@ from __future__ import annotations
|
|
10
10
|
|
11
11
|
__all__ = ["OOD_AE"]
|
12
12
|
|
13
|
-
from typing import Callable
|
13
|
+
from typing import TYPE_CHECKING, Callable
|
14
14
|
|
15
15
|
import numpy as np
|
16
|
-
import tensorflow as tf
|
17
|
-
import tf_keras as keras
|
18
16
|
from numpy.typing import ArrayLike
|
19
17
|
|
20
18
|
from dataeval.detectors.ood.base import OODBase, OODScoreOutput
|
21
19
|
from dataeval.interop import as_numpy
|
22
|
-
from dataeval.utils.
|
20
|
+
from dataeval.utils.lazy import lazyload
|
23
21
|
from dataeval.utils.tensorflow._internal.utils import predict_batch
|
24
22
|
|
23
|
+
if TYPE_CHECKING:
|
24
|
+
import tensorflow as tf
|
25
|
+
import tf_keras as keras
|
26
|
+
|
27
|
+
import dataeval.utils.tensorflow._internal.models as tf_models
|
28
|
+
else:
|
29
|
+
tf = lazyload("tensorflow")
|
30
|
+
keras = lazyload("tf_keras")
|
31
|
+
tf_models = lazyload("dataeval.utils.tensorflow._internal.models")
|
32
|
+
|
25
33
|
|
26
34
|
class OOD_AE(OODBase):
|
27
35
|
"""
|
@@ -33,7 +41,7 @@ class OOD_AE(OODBase):
|
|
33
41
|
An :term:`autoencoder<Autoencoder>` model.
|
34
42
|
"""
|
35
43
|
|
36
|
-
def __init__(self, model: AE) -> None:
|
44
|
+
def __init__(self, model: tf_models.AE) -> None:
|
37
45
|
super().__init__(model)
|
38
46
|
|
39
47
|
def fit(
|
@@ -41,7 +49,7 @@ class OOD_AE(OODBase):
|
|
41
49
|
x_ref: ArrayLike,
|
42
50
|
threshold_perc: float = 100.0,
|
43
51
|
loss_fn: Callable[..., tf.Tensor] | None = None,
|
44
|
-
optimizer: keras.optimizers.Optimizer =
|
52
|
+
optimizer: keras.optimizers.Optimizer | None = None,
|
45
53
|
epochs: int = 20,
|
46
54
|
batch_size: int = 64,
|
47
55
|
verbose: bool = True,
|
@@ -10,19 +10,27 @@ from __future__ import annotations
|
|
10
10
|
|
11
11
|
__all__ = ["OOD_AEGMM"]
|
12
12
|
|
13
|
-
from typing import Callable
|
13
|
+
from typing import TYPE_CHECKING, Callable
|
14
14
|
|
15
|
-
import tensorflow as tf
|
16
|
-
import tf_keras as keras
|
17
15
|
from numpy.typing import ArrayLike
|
18
16
|
|
19
17
|
from dataeval.detectors.ood.base import OODGMMBase, OODScoreOutput
|
20
18
|
from dataeval.interop import to_numpy
|
21
|
-
from dataeval.utils.
|
19
|
+
from dataeval.utils.lazy import lazyload
|
22
20
|
from dataeval.utils.tensorflow._internal.gmm import gmm_energy
|
23
21
|
from dataeval.utils.tensorflow._internal.loss import LossGMM
|
24
22
|
from dataeval.utils.tensorflow._internal.utils import predict_batch
|
25
23
|
|
24
|
+
if TYPE_CHECKING:
|
25
|
+
import tensorflow as tf
|
26
|
+
import tf_keras as keras
|
27
|
+
|
28
|
+
import dataeval.utils.tensorflow._internal.models as tf_models
|
29
|
+
else:
|
30
|
+
tf = lazyload("tensorflow")
|
31
|
+
keras = lazyload("tf_keras")
|
32
|
+
tf_models = lazyload("dataeval.utils.tensorflow._internal.models")
|
33
|
+
|
26
34
|
|
27
35
|
class OOD_AEGMM(OODGMMBase):
|
28
36
|
"""
|
@@ -34,7 +42,7 @@ class OOD_AEGMM(OODGMMBase):
|
|
34
42
|
An AEGMM model.
|
35
43
|
"""
|
36
44
|
|
37
|
-
def __init__(self, model: AEGMM) -> None:
|
45
|
+
def __init__(self, model: tf_models.AEGMM) -> None:
|
38
46
|
super().__init__(model)
|
39
47
|
|
40
48
|
def fit(
|
@@ -42,7 +50,7 @@ class OOD_AEGMM(OODGMMBase):
|
|
42
50
|
x_ref: ArrayLike,
|
43
51
|
threshold_perc: float = 100.0,
|
44
52
|
loss_fn: Callable[..., tf.Tensor] | None = None,
|
45
|
-
optimizer: keras.optimizers.Optimizer =
|
53
|
+
optimizer: keras.optimizers.Optimizer | None = None,
|
46
54
|
epochs: int = 20,
|
47
55
|
batch_size: int = 64,
|
48
56
|
verbose: bool = True,
|
@@ -12,18 +12,24 @@ __all__ = ["OODOutput", "OODScoreOutput"]
|
|
12
12
|
|
13
13
|
from abc import ABC, abstractmethod
|
14
14
|
from dataclasses import dataclass
|
15
|
-
from typing import Callable, Literal, cast
|
15
|
+
from typing import TYPE_CHECKING, Callable, Literal, cast
|
16
16
|
|
17
17
|
import numpy as np
|
18
|
-
import tensorflow as tf
|
19
|
-
import tf_keras as keras
|
20
18
|
from numpy.typing import ArrayLike, NDArray
|
21
19
|
|
22
20
|
from dataeval.interop import to_numpy
|
23
21
|
from dataeval.output import OutputMetadata, set_metadata
|
22
|
+
from dataeval.utils.lazy import lazyload
|
24
23
|
from dataeval.utils.tensorflow._internal.gmm import GaussianMixtureModelParams, gmm_params
|
25
24
|
from dataeval.utils.tensorflow._internal.trainer import trainer
|
26
25
|
|
26
|
+
if TYPE_CHECKING:
|
27
|
+
import tensorflow as tf
|
28
|
+
import tf_keras as keras
|
29
|
+
else:
|
30
|
+
tf = lazyload("tensorflow")
|
31
|
+
keras = lazyload("tf_keras")
|
32
|
+
|
27
33
|
|
28
34
|
@dataclass(frozen=True)
|
29
35
|
class OODOutput(OutputMetadata):
|
@@ -11,25 +11,31 @@ from __future__ import annotations
|
|
11
11
|
__all__ = ["OOD_LLR"]
|
12
12
|
|
13
13
|
from functools import partial
|
14
|
-
from typing import Callable
|
14
|
+
from typing import TYPE_CHECKING, Callable
|
15
15
|
|
16
16
|
import numpy as np
|
17
|
-
import tensorflow as tf
|
18
|
-
import tf_keras as keras
|
19
17
|
from numpy.typing import ArrayLike, NDArray
|
20
|
-
from tf_keras.layers import Input
|
21
|
-
from tf_keras.models import Model
|
22
18
|
|
23
19
|
from dataeval.detectors.ood.base import OODBase, OODScoreOutput
|
24
20
|
from dataeval.interop import to_numpy
|
25
|
-
from dataeval.utils.
|
21
|
+
from dataeval.utils.lazy import lazyload
|
26
22
|
from dataeval.utils.tensorflow._internal.trainer import trainer
|
27
23
|
from dataeval.utils.tensorflow._internal.utils import predict_batch
|
28
24
|
|
25
|
+
if TYPE_CHECKING:
|
26
|
+
import tensorflow as tf
|
27
|
+
import tf_keras as keras
|
28
|
+
|
29
|
+
import dataeval.utils.tensorflow._internal.models as tf_models
|
30
|
+
else:
|
31
|
+
tf = lazyload("tensorflow")
|
32
|
+
keras = lazyload("tf_keras")
|
33
|
+
tf_models = lazyload("dataeval.utils.tensorflow._internal.models")
|
34
|
+
|
29
35
|
|
30
36
|
def _build_model(
|
31
|
-
dist: PixelCNN, input_shape: tuple | None = None, filepath: str | None = None
|
32
|
-
) -> tuple[keras.Model, PixelCNN]:
|
37
|
+
dist: tf_models.PixelCNN, input_shape: tuple | None = None, filepath: str | None = None
|
38
|
+
) -> tuple[keras.Model, tf_models.PixelCNN]:
|
33
39
|
"""
|
34
40
|
Create keras.Model from TF distribution.
|
35
41
|
|
@@ -46,9 +52,9 @@ def _build_model(
|
|
46
52
|
-------
|
47
53
|
TensorFlow model.
|
48
54
|
"""
|
49
|
-
x_in = Input(shape=input_shape)
|
55
|
+
x_in = keras.layers.Input(shape=input_shape)
|
50
56
|
log_prob = dist.log_prob(x_in)
|
51
|
-
model = Model(inputs=x_in, outputs=log_prob)
|
57
|
+
model = keras.models.Model(inputs=x_in, outputs=log_prob)
|
52
58
|
model.add_loss(-tf.reduce_mean(log_prob))
|
53
59
|
if isinstance(filepath, str):
|
54
60
|
model.load_weights(filepath)
|
@@ -109,13 +115,13 @@ class OOD_LLR(OODBase):
|
|
109
115
|
|
110
116
|
def __init__(
|
111
117
|
self,
|
112
|
-
model: PixelCNN,
|
113
|
-
model_background: PixelCNN | None = None,
|
118
|
+
model: tf_models.PixelCNN,
|
119
|
+
model_background: tf_models.PixelCNN | None = None,
|
114
120
|
log_prob: Callable | None = None,
|
115
121
|
sequential: bool = False,
|
116
122
|
) -> None:
|
117
|
-
self.dist_s: PixelCNN = model
|
118
|
-
self.dist_b: PixelCNN = (
|
123
|
+
self.dist_s: tf_models.PixelCNN = model
|
124
|
+
self.dist_b: tf_models.PixelCNN = (
|
119
125
|
model.copy()
|
120
126
|
if hasattr(model, "copy")
|
121
127
|
else keras.models.clone_model(model)
|
@@ -135,7 +141,7 @@ class OOD_LLR(OODBase):
|
|
135
141
|
x_ref: ArrayLike,
|
136
142
|
threshold_perc: float = 100.0,
|
137
143
|
loss_fn: Callable | None = None,
|
138
|
-
optimizer: keras.optimizers.Optimizer =
|
144
|
+
optimizer: keras.optimizers.Optimizer | None = None,
|
139
145
|
epochs: int = 20,
|
140
146
|
batch_size: int = 64,
|
141
147
|
verbose: bool = True,
|
@@ -176,7 +182,7 @@ class OOD_LLR(OODBase):
|
|
176
182
|
"""
|
177
183
|
x_ref = to_numpy(x_ref)
|
178
184
|
input_shape = x_ref.shape[1:]
|
179
|
-
optimizer =
|
185
|
+
optimizer = keras.optimizers.Adam() if optimizer is None else optimizer
|
180
186
|
# Separate into two separate optimizers, one for semantic model and one for background model
|
181
187
|
optimizer_s = optimizer
|
182
188
|
optimizer_b = optimizer.__class__.from_config(optimizer.get_config())
|
@@ -10,19 +10,27 @@ from __future__ import annotations
|
|
10
10
|
|
11
11
|
__all__ = ["OOD_VAE"]
|
12
12
|
|
13
|
-
from typing import Callable
|
13
|
+
from typing import TYPE_CHECKING, Callable
|
14
14
|
|
15
15
|
import numpy as np
|
16
|
-
import tensorflow as tf
|
17
|
-
import tf_keras as keras
|
18
16
|
from numpy.typing import ArrayLike
|
19
17
|
|
20
18
|
from dataeval.detectors.ood.base import OODBase, OODScoreOutput
|
21
19
|
from dataeval.interop import to_numpy
|
22
|
-
from dataeval.utils.
|
20
|
+
from dataeval.utils.lazy import lazyload
|
23
21
|
from dataeval.utils.tensorflow._internal.loss import Elbo
|
24
22
|
from dataeval.utils.tensorflow._internal.utils import predict_batch
|
25
23
|
|
24
|
+
if TYPE_CHECKING:
|
25
|
+
import tensorflow as tf
|
26
|
+
import tf_keras as keras
|
27
|
+
|
28
|
+
import dataeval.utils.tensorflow._internal.models as tf_models
|
29
|
+
else:
|
30
|
+
tf = lazyload("tensorflow")
|
31
|
+
keras = lazyload("tf_keras")
|
32
|
+
tf_models = lazyload("dataeval.utils.tensorflow._internal.models")
|
33
|
+
|
26
34
|
|
27
35
|
class OOD_VAE(OODBase):
|
28
36
|
"""
|
@@ -51,7 +59,7 @@ class OOD_VAE(OODBase):
|
|
51
59
|
>>> result = metric.predict(dataset, ood_type="feature")
|
52
60
|
"""
|
53
61
|
|
54
|
-
def __init__(self, model: VAE, samples: int = 10) -> None:
|
62
|
+
def __init__(self, model: tf_models.VAE, samples: int = 10) -> None:
|
55
63
|
super().__init__(model)
|
56
64
|
self.samples = samples
|
57
65
|
|
@@ -60,7 +68,7 @@ class OOD_VAE(OODBase):
|
|
60
68
|
x_ref: ArrayLike,
|
61
69
|
threshold_perc: float = 100.0,
|
62
70
|
loss_fn: Callable[..., tf.Tensor] = Elbo(0.05),
|
63
|
-
optimizer: keras.optimizers.Optimizer =
|
71
|
+
optimizer: keras.optimizers.Optimizer | None = None,
|
64
72
|
epochs: int = 20,
|
65
73
|
batch_size: int = 64,
|
66
74
|
verbose: bool = True,
|
@@ -10,20 +10,28 @@ from __future__ import annotations
|
|
10
10
|
|
11
11
|
__all__ = ["OOD_VAEGMM"]
|
12
12
|
|
13
|
-
from typing import Callable
|
13
|
+
from typing import TYPE_CHECKING, Callable
|
14
14
|
|
15
15
|
import numpy as np
|
16
|
-
import tensorflow as tf
|
17
|
-
import tf_keras as keras
|
18
16
|
from numpy.typing import ArrayLike
|
19
17
|
|
20
18
|
from dataeval.detectors.ood.base import OODGMMBase, OODScoreOutput
|
21
19
|
from dataeval.interop import to_numpy
|
22
|
-
from dataeval.utils.
|
20
|
+
from dataeval.utils.lazy import lazyload
|
23
21
|
from dataeval.utils.tensorflow._internal.gmm import gmm_energy
|
24
22
|
from dataeval.utils.tensorflow._internal.loss import Elbo, LossGMM
|
25
23
|
from dataeval.utils.tensorflow._internal.utils import predict_batch
|
26
24
|
|
25
|
+
if TYPE_CHECKING:
|
26
|
+
import tensorflow as tf
|
27
|
+
import tf_keras as keras
|
28
|
+
|
29
|
+
import dataeval.utils.tensorflow._internal.models as tf_models
|
30
|
+
else:
|
31
|
+
tf = lazyload("tensorflow")
|
32
|
+
keras = lazyload("tf_keras")
|
33
|
+
tf_models = lazyload("dataeval.utils.tensorflow._internal.models")
|
34
|
+
|
27
35
|
|
28
36
|
class OOD_VAEGMM(OODGMMBase):
|
29
37
|
"""
|
@@ -37,7 +45,7 @@ class OOD_VAEGMM(OODGMMBase):
|
|
37
45
|
Number of samples sampled to evaluate each instance.
|
38
46
|
"""
|
39
47
|
|
40
|
-
def __init__(self, model: VAEGMM, samples: int = 10) -> None:
|
48
|
+
def __init__(self, model: tf_models.VAEGMM, samples: int = 10) -> None:
|
41
49
|
super().__init__(model)
|
42
50
|
self.samples = samples
|
43
51
|
|
@@ -46,7 +54,7 @@ class OOD_VAEGMM(OODGMMBase):
|
|
46
54
|
x_ref: ArrayLike,
|
47
55
|
threshold_perc: float = 100.0,
|
48
56
|
loss_fn: Callable[..., tf.Tensor] = LossGMM(elbo=Elbo(0.05)),
|
49
|
-
optimizer: keras.optimizers.Optimizer =
|
57
|
+
optimizer: keras.optimizers.Optimizer | None = None,
|
50
58
|
epochs: int = 20,
|
51
59
|
batch_size: int = 64,
|
52
60
|
verbose: bool = True,
|
@@ -37,13 +37,15 @@ def to_numpy(array: ArrayLike | None, copy: bool = True) -> NDArray[Any]:
|
|
37
37
|
if isinstance(array, np.ndarray):
|
38
38
|
return array.copy() if copy else array
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
if
|
46
|
-
|
40
|
+
if array.__class__.__module__.startswith("tensorflow"):
|
41
|
+
tf = _try_import("tensorflow")
|
42
|
+
if tf and tf.is_tensor(array):
|
43
|
+
return array.numpy().copy() if copy else array.numpy() # type: ignore
|
44
|
+
|
45
|
+
if array.__class__.__module__.startswith("torch"):
|
46
|
+
torch = _try_import("torch")
|
47
|
+
if torch and isinstance(array, torch.Tensor):
|
48
|
+
return array.detach().cpu().numpy().copy() if copy else array.detach().cpu().numpy() # type: ignore
|
47
49
|
|
48
50
|
return np.array(array, copy=copy)
|
49
51
|
|