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.
Files changed (75) hide show
  1. {dataeval-0.72.2 → dataeval-0.73.1}/PKG-INFO +3 -3
  2. {dataeval-0.72.2 → dataeval-0.73.1}/pyproject.toml +13 -8
  3. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/__init__.py +3 -3
  4. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/__init__.py +1 -1
  5. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/drift/__init__.py +1 -1
  6. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/drift/base.py +2 -2
  7. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/linters/clusterer.py +1 -1
  8. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/__init__.py +1 -1
  9. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/ae.py +14 -6
  10. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/aegmm.py +14 -6
  11. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/base.py +9 -3
  12. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/llr.py +22 -16
  13. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/vae.py +14 -6
  14. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/vaegmm.py +14 -6
  15. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/interop.py +9 -7
  16. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/bias/balance.py +50 -44
  17. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/bias/coverage.py +38 -6
  18. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/bias/diversity.py +117 -65
  19. dataeval-0.73.1/src/dataeval/metrics/bias/metadata.py +440 -0
  20. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/bias/parity.py +68 -54
  21. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/__init__.py +4 -3
  22. dataeval-0.73.1/src/dataeval/utils/lazy.py +26 -0
  23. dataeval-0.73.1/src/dataeval/utils/metadata.py +258 -0
  24. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/shared.py +1 -1
  25. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/split_dataset.py +12 -6
  26. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/tensorflow/_internal/gmm.py +8 -2
  27. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/tensorflow/_internal/loss.py +20 -11
  28. dataeval-0.72.2/src/dataeval/utils/tensorflow/_internal/pixelcnn.py → dataeval-0.73.1/src/dataeval/utils/tensorflow/_internal/models.py +371 -77
  29. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/tensorflow/_internal/trainer.py +12 -5
  30. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/tensorflow/_internal/utils.py +70 -71
  31. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/torch/datasets.py +2 -2
  32. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/workflows/__init__.py +1 -1
  33. dataeval-0.72.2/src/dataeval/metrics/bias/metadata.py +0 -275
  34. dataeval-0.72.2/src/dataeval/utils/tensorflow/_internal/autoencoder.py +0 -316
  35. {dataeval-0.72.2 → dataeval-0.73.1}/LICENSE.txt +0 -0
  36. {dataeval-0.72.2 → dataeval-0.73.1}/README.md +0 -0
  37. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/drift/cvm.py +0 -0
  38. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/drift/ks.py +0 -0
  39. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/drift/mmd.py +0 -0
  40. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/drift/torch.py +0 -0
  41. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/drift/uncertainty.py +0 -0
  42. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/drift/updates.py +0 -0
  43. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/linters/__init__.py +0 -0
  44. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/linters/duplicates.py +0 -0
  45. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/linters/merged_stats.py +0 -0
  46. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/linters/outliers.py +0 -0
  47. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/metadata_ks_compare.py +0 -0
  48. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/metadata_least_likely.py +0 -0
  49. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/detectors/ood/metadata_ood_mi.py +0 -0
  50. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/__init__.py +0 -0
  51. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/bias/__init__.py +0 -0
  52. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/estimators/__init__.py +0 -0
  53. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/estimators/ber.py +0 -0
  54. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/estimators/divergence.py +0 -0
  55. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/estimators/uap.py +0 -0
  56. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/__init__.py +0 -0
  57. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/base.py +0 -0
  58. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/boxratiostats.py +0 -0
  59. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/datasetstats.py +0 -0
  60. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/dimensionstats.py +0 -0
  61. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/hashstats.py +0 -0
  62. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/labelstats.py +0 -0
  63. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/pixelstats.py +0 -0
  64. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/metrics/stats/visualstats.py +0 -0
  65. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/output.py +0 -0
  66. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/py.typed +0 -0
  67. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/image.py +0 -0
  68. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/tensorflow/__init__.py +0 -0
  69. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/tensorflow/loss/__init__.py +0 -0
  70. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/torch/__init__.py +0 -0
  71. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/torch/blocks.py +0 -0
  72. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/torch/models.py +0 -0
  73. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/torch/trainer.py +0 -0
  74. {dataeval-0.72.2 → dataeval-0.73.1}/src/dataeval/utils/torch/utils.py +0 -0
  75. {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.72.2
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.72.2" # dynamic
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
- tox = {version = "*"}
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 = ["raise NotImplementedError"]
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/pixelcnn.py",
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.72.2"
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: # pragma: no cover
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: # pragma: no cover
20
+ if _IS_TENSORFLOW_AVAILABLE or _IS_TORCH_AVAILABLE:
21
21
  from dataeval import utils
22
22
 
23
23
  __all__ += ["utils"]
@@ -7,7 +7,7 @@ from dataeval.detectors import drift, linters
7
7
 
8
8
  __all__ = ["drift", "linters"]
9
9
 
10
- if _IS_TENSORFLOW_AVAILABLE: # pragma: no cover
10
+ if _IS_TENSORFLOW_AVAILABLE:
11
11
  from dataeval.detectors import ood
12
12
 
13
13
  __all__ += ["ood"]
@@ -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: # pragma: no cover
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, to_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 = to_numpy(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=bool)
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: # pragma: no cover
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.tensorflow._internal.autoencoder import AE
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 = keras.optimizers.Adam,
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.tensorflow._internal.autoencoder import AEGMM
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 = keras.optimizers.Adam,
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.tensorflow._internal.pixelcnn import PixelCNN
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 = keras.optimizers.Adam,
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 = optimizer() if isinstance(optimizer, type) else 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.tensorflow._internal.autoencoder import VAE
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 = keras.optimizers.Adam,
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.tensorflow._internal.autoencoder import VAEGMM
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 = keras.optimizers.Adam,
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
- tf = _try_import("tensorflow")
41
- if tf and tf.is_tensor(array):
42
- return array.numpy().copy() if copy else array.numpy() # type: ignore
43
-
44
- torch = _try_import("torch")
45
- if torch and isinstance(array, torch.Tensor):
46
- return array.detach().cpu().numpy().copy() if copy else array.detach().cpu().numpy() # type: ignore
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