dataeval 0.72.2__py3-none-any.whl → 0.73.1__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.
- dataeval/__init__.py +3 -3
- dataeval/detectors/__init__.py +1 -1
- dataeval/detectors/drift/__init__.py +1 -1
- dataeval/detectors/drift/base.py +2 -2
- dataeval/detectors/linters/clusterer.py +1 -1
- dataeval/detectors/ood/__init__.py +1 -1
- dataeval/detectors/ood/ae.py +14 -6
- dataeval/detectors/ood/aegmm.py +14 -6
- dataeval/detectors/ood/base.py +9 -3
- dataeval/detectors/ood/llr.py +22 -16
- dataeval/detectors/ood/vae.py +14 -6
- dataeval/detectors/ood/vaegmm.py +14 -6
- dataeval/interop.py +9 -7
- dataeval/metrics/bias/balance.py +50 -44
- dataeval/metrics/bias/coverage.py +38 -6
- dataeval/metrics/bias/diversity.py +117 -65
- dataeval/metrics/bias/metadata.py +225 -60
- dataeval/metrics/bias/parity.py +68 -54
- dataeval/utils/__init__.py +4 -3
- dataeval/utils/lazy.py +26 -0
- dataeval/utils/metadata.py +258 -0
- dataeval/utils/shared.py +1 -1
- dataeval/utils/split_dataset.py +12 -6
- dataeval/utils/tensorflow/_internal/gmm.py +8 -2
- dataeval/utils/tensorflow/_internal/loss.py +20 -11
- dataeval/utils/tensorflow/_internal/{pixelcnn.py → models.py} +371 -77
- dataeval/utils/tensorflow/_internal/trainer.py +12 -5
- dataeval/utils/tensorflow/_internal/utils.py +70 -71
- dataeval/utils/torch/datasets.py +2 -2
- dataeval/workflows/__init__.py +1 -1
- {dataeval-0.72.2.dist-info → dataeval-0.73.1.dist-info}/METADATA +3 -3
- {dataeval-0.72.2.dist-info → dataeval-0.73.1.dist-info}/RECORD +34 -33
- dataeval/utils/tensorflow/_internal/autoencoder.py +0 -316
- {dataeval-0.72.2.dist-info → dataeval-0.73.1.dist-info}/LICENSE.txt +0 -0
- {dataeval-0.72.2.dist-info → dataeval-0.73.1.dist-info}/WHEEL +0 -0
@@ -12,27 +12,321 @@ from __future__ import annotations
|
|
12
12
|
|
13
13
|
import functools
|
14
14
|
import warnings
|
15
|
+
from typing import TYPE_CHECKING, cast
|
15
16
|
|
16
17
|
import numpy as np
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
)
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
18
|
+
|
19
|
+
from dataeval.utils.lazy import lazyload
|
20
|
+
|
21
|
+
if TYPE_CHECKING:
|
22
|
+
import tensorflow as tf
|
23
|
+
import tensorflow_probability.python.bijectors as bijectors
|
24
|
+
import tensorflow_probability.python.distributions as distributions
|
25
|
+
import tensorflow_probability.python.internal as tfp_internal
|
26
|
+
import tf_keras as keras
|
27
|
+
else:
|
28
|
+
tf = lazyload("tensorflow")
|
29
|
+
bijectors = lazyload("tensorflow_probability.python.bijectors")
|
30
|
+
distributions = lazyload("tensorflow_probability.python.distributions")
|
31
|
+
tfp_internal = lazyload("tensorflow_probability.python.internal")
|
32
|
+
keras = lazyload("tf_keras")
|
33
|
+
|
34
|
+
|
35
|
+
def relative_euclidean_distance(x: tf.Tensor, y: tf.Tensor, eps: float = 1e-12, axis: int = -1) -> tf.Tensor:
|
36
|
+
"""
|
37
|
+
Relative Euclidean distance.
|
38
|
+
|
39
|
+
Parameters
|
40
|
+
----------
|
41
|
+
x
|
42
|
+
Tensor used in distance computation.
|
43
|
+
y
|
44
|
+
Tensor used in distance computation.
|
45
|
+
eps
|
46
|
+
Epsilon added to denominator for numerical stability.
|
47
|
+
axis
|
48
|
+
Axis used to compute distance.
|
49
|
+
|
50
|
+
Returns
|
51
|
+
-------
|
52
|
+
Tensor with relative Euclidean distance across specified axis.
|
53
|
+
"""
|
54
|
+
denom = tf.concat(
|
55
|
+
[
|
56
|
+
tf.reshape(tf.norm(x, ord=2, axis=axis), (-1, 1)), # type: ignore
|
57
|
+
tf.reshape(tf.norm(y, ord=2, axis=axis), (-1, 1)), # type: ignore
|
58
|
+
],
|
59
|
+
axis=1,
|
60
|
+
)
|
61
|
+
dist = tf.norm(tf.math.subtract(x, y), ord=2, axis=axis) / (tf.reduce_min(denom, axis=axis) + eps) # type: ignore
|
62
|
+
return dist
|
63
|
+
|
64
|
+
|
65
|
+
def eucl_cosim_features(x: tf.Tensor, y: tf.Tensor, max_eucl: float = 1e2) -> tf.Tensor:
|
66
|
+
"""
|
67
|
+
Compute features extracted from the reconstructed instance using the
|
68
|
+
relative Euclidean distance and cosine similarity between 2 tensors.
|
69
|
+
|
70
|
+
Parameters
|
71
|
+
----------
|
72
|
+
x : tf.Tensor
|
73
|
+
Tensor used in feature computation.
|
74
|
+
y : tf.Tensor
|
75
|
+
Tensor used in feature computation.
|
76
|
+
max_eucl : float, default 1e2
|
77
|
+
Maximum value to clip relative Euclidean distance by.
|
78
|
+
|
79
|
+
Returns
|
80
|
+
-------
|
81
|
+
tf.Tensor
|
82
|
+
Tensor concatenating the relative Euclidean distance and cosine similarity features.
|
83
|
+
"""
|
84
|
+
if len(x.shape) > 2 or len(y.shape) > 2:
|
85
|
+
x = cast(tf.Tensor, keras.layers.Flatten()(x))
|
86
|
+
y = cast(tf.Tensor, keras.layers.Flatten()(y))
|
87
|
+
rec_cos = tf.reshape(keras.losses.cosine_similarity(y, x, -1), (-1, 1))
|
88
|
+
rec_euc = tf.reshape(relative_euclidean_distance(y, x, -1), (-1, 1))
|
89
|
+
# rec_euc could become very large so should be clipped
|
90
|
+
rec_euc = tf.clip_by_value(rec_euc, 0, max_eucl)
|
91
|
+
return cast(tf.Tensor, tf.concat([rec_cos, rec_euc], -1))
|
92
|
+
|
93
|
+
|
94
|
+
class Sampling(keras.layers.Layer):
|
95
|
+
"""Reparametrization trick - Uses (z_mean, z_log_var) to sample the latent vector z."""
|
96
|
+
|
97
|
+
def call(self, inputs: tuple[tf.Tensor, tf.Tensor]) -> tf.Tensor:
|
98
|
+
"""
|
99
|
+
Sample z.
|
100
|
+
|
101
|
+
Parameters
|
102
|
+
----------
|
103
|
+
inputs
|
104
|
+
Tuple with mean and log :term:`variance<Variance>`.
|
105
|
+
|
106
|
+
Returns
|
107
|
+
-------
|
108
|
+
Sampled vector z.
|
109
|
+
"""
|
110
|
+
z_mean, z_log_var = inputs
|
111
|
+
batch, dim = tuple(tf.shape(z_mean).numpy().ravel()[:2]) # type: ignore
|
112
|
+
epsilon = cast(tf.Tensor, keras.backend.random_normal(shape=(batch, dim)))
|
113
|
+
return z_mean + tf.exp(tf.math.multiply(0.5, z_log_var)) * epsilon
|
114
|
+
|
115
|
+
|
116
|
+
class EncoderAE(keras.layers.Layer):
|
117
|
+
def __init__(self, encoder_net: keras.Sequential) -> None:
|
118
|
+
"""
|
119
|
+
Encoder of AE.
|
120
|
+
|
121
|
+
Parameters
|
122
|
+
----------
|
123
|
+
encoder_net
|
124
|
+
Layers for the encoder wrapped in a keras.keras.Sequential class.
|
125
|
+
name
|
126
|
+
Name of encoder.
|
127
|
+
"""
|
128
|
+
super().__init__(name="encoder_ae")
|
129
|
+
self.encoder_net: keras.Sequential = encoder_net
|
130
|
+
|
131
|
+
def call(self, x: tf.Tensor) -> tf.Tensor:
|
132
|
+
return cast(tf.Tensor, self.encoder_net(x))
|
133
|
+
|
134
|
+
|
135
|
+
class EncoderVAE(keras.layers.Layer):
|
136
|
+
def __init__(self, encoder_net: keras.Sequential, latent_dim: int) -> None:
|
137
|
+
"""
|
138
|
+
Encoder of VAE.
|
139
|
+
|
140
|
+
Parameters
|
141
|
+
----------
|
142
|
+
encoder_net
|
143
|
+
Layers for the encoder wrapped in a keras.keras.Sequential class.
|
144
|
+
latent_dim
|
145
|
+
Dimensionality of the :term:`latent space<Latent Space>`.
|
146
|
+
name
|
147
|
+
Name of encoder.
|
148
|
+
"""
|
149
|
+
super().__init__(name="encoder_vae")
|
150
|
+
self.encoder_net: keras.Sequential = encoder_net
|
151
|
+
self._fc_mean = keras.layers.Dense(latent_dim, activation=None)
|
152
|
+
self._fc_log_var = keras.layers.Dense(latent_dim, activation=None)
|
153
|
+
self._sampling = Sampling()
|
154
|
+
|
155
|
+
def call(self, x: tf.Tensor) -> tuple[tf.Tensor, tf.Tensor, tf.Tensor]:
|
156
|
+
x = cast(tf.Tensor, self.encoder_net(x))
|
157
|
+
if len(x.shape) > 2:
|
158
|
+
x = cast(tf.Tensor, keras.layers.Flatten()(x))
|
159
|
+
z_mean = cast(tf.Tensor, self._fc_mean(x))
|
160
|
+
z_log_var = cast(tf.Tensor, self._fc_log_var(x))
|
161
|
+
z = cast(tf.Tensor, self._sampling((z_mean, z_log_var)))
|
162
|
+
return z_mean, z_log_var, z
|
163
|
+
|
164
|
+
|
165
|
+
class Decoder(keras.layers.Layer):
|
166
|
+
def __init__(self, decoder_net: keras.Sequential) -> None:
|
167
|
+
"""
|
168
|
+
Decoder of AE and VAE.
|
169
|
+
|
170
|
+
Parameters
|
171
|
+
----------
|
172
|
+
decoder_net
|
173
|
+
Layers for the decoder wrapped in a keras.keras.Sequential class.
|
174
|
+
name
|
175
|
+
Name of decoder.
|
176
|
+
"""
|
177
|
+
super().__init__(name="decoder")
|
178
|
+
self.decoder_net: keras.Sequential = decoder_net
|
179
|
+
|
180
|
+
def call(self, inputs: tf.Tensor) -> tf.Tensor:
|
181
|
+
return cast(tf.Tensor, self.decoder_net(inputs))
|
182
|
+
|
183
|
+
|
184
|
+
class AE(keras.Model):
|
185
|
+
"""
|
186
|
+
Combine encoder and decoder in AE.
|
187
|
+
|
188
|
+
Parameters
|
189
|
+
----------
|
190
|
+
encoder_net : keras.Sequential
|
191
|
+
Layers for the encoder wrapped in a keras.keras.Sequential class.
|
192
|
+
decoder_net : keras.Sequential
|
193
|
+
Layers for the decoder wrapped in a keras.keras.Sequential class.
|
194
|
+
"""
|
195
|
+
|
196
|
+
def __init__(self, encoder_net: keras.Sequential, decoder_net: keras.Sequential) -> None:
|
197
|
+
super().__init__(name="ae")
|
198
|
+
self.encoder: keras.layers.Layer = EncoderAE(encoder_net)
|
199
|
+
self.decoder: keras.layers.Layer = Decoder(decoder_net)
|
200
|
+
|
201
|
+
def call(self, inputs: tf.Tensor, training: bool | None = None, mask: tf.Tensor | None = None) -> tf.Tensor:
|
202
|
+
z = cast(tf.Tensor, self.encoder(inputs))
|
203
|
+
x_recon = cast(tf.Tensor, self.decoder(z))
|
204
|
+
return x_recon
|
205
|
+
|
206
|
+
|
207
|
+
class VAE(keras.Model):
|
208
|
+
"""
|
209
|
+
Combine encoder and decoder in VAE.
|
210
|
+
|
211
|
+
Parameters
|
212
|
+
----------
|
213
|
+
encoder_net : keras.Sequential
|
214
|
+
Layers for the encoder wrapped in a keras.keras.Sequential class.
|
215
|
+
decoder_net : keras.Sequential
|
216
|
+
Layers for the decoder wrapped in a keras.keras.Sequential class.
|
217
|
+
latent_dim : int
|
218
|
+
Dimensionality of the :term:`latent space<Latent Space>`.
|
219
|
+
beta : float, default 1.0
|
220
|
+
Beta parameter for KL-divergence loss term.
|
221
|
+
"""
|
222
|
+
|
223
|
+
def __init__(
|
224
|
+
self, encoder_net: keras.Sequential, decoder_net: keras.Sequential, latent_dim: int, beta: float = 1.0
|
225
|
+
) -> None:
|
226
|
+
super().__init__(name="vae_model")
|
227
|
+
self.encoder: keras.layers.Layer = EncoderVAE(encoder_net, latent_dim)
|
228
|
+
self.decoder: keras.layers.Layer = Decoder(decoder_net)
|
229
|
+
self.beta: float = beta
|
230
|
+
self.latent_dim: int = latent_dim
|
231
|
+
|
232
|
+
def call(self, inputs: tf.Tensor, training: bool | None = None, mask: tf.Tensor | None = None) -> tf.Tensor:
|
233
|
+
z_mean, z_log_var, z = cast(tuple[tf.Tensor, tf.Tensor, tf.Tensor], self.encoder(inputs))
|
234
|
+
x_recon = self.decoder(z)
|
235
|
+
# add KL divergence loss term
|
236
|
+
kl_loss = -0.5 * tf.reduce_mean(z_log_var - tf.square(z_mean) - tf.exp(z_log_var) + 1)
|
237
|
+
self.add_loss(self.beta * kl_loss)
|
238
|
+
return cast(tf.Tensor, x_recon)
|
239
|
+
|
240
|
+
|
241
|
+
class AEGMM(keras.Model):
|
242
|
+
"""
|
243
|
+
Deep Autoencoding Gaussian Mixture Model.
|
244
|
+
|
245
|
+
Parameters
|
246
|
+
----------
|
247
|
+
encoder_net : keras.Sequential
|
248
|
+
Layers for the encoder wrapped in a keras.keras.Sequential class.
|
249
|
+
decoder_net : keras.Sequential
|
250
|
+
Layers for the decoder wrapped in a keras.keras.Sequential class.
|
251
|
+
gmm_density_net : keras.Sequential
|
252
|
+
Layers for the GMM network wrapped in a keras.keras.Sequential class.
|
253
|
+
n_gmm : int
|
254
|
+
Number of components in GMM.
|
255
|
+
"""
|
256
|
+
|
257
|
+
def __init__(
|
258
|
+
self,
|
259
|
+
encoder_net: keras.Sequential,
|
260
|
+
decoder_net: keras.Sequential,
|
261
|
+
gmm_density_net: keras.Sequential,
|
262
|
+
n_gmm: int,
|
263
|
+
) -> None:
|
264
|
+
super().__init__("aegmm")
|
265
|
+
self.encoder = encoder_net
|
266
|
+
self.decoder = decoder_net
|
267
|
+
self.gmm_density = gmm_density_net
|
268
|
+
self.n_gmm = n_gmm
|
269
|
+
|
270
|
+
def call(
|
271
|
+
self, inputs: tf.Tensor, training: bool | None = None, mask: tf.Tensor | None = None
|
272
|
+
) -> tuple[tf.Tensor, tf.Tensor, tf.Tensor]:
|
273
|
+
enc = self.encoder(inputs)
|
274
|
+
x_recon = cast(tf.Tensor, self.decoder(enc))
|
275
|
+
recon_features = eucl_cosim_features(inputs, x_recon)
|
276
|
+
z = cast(tf.Tensor, tf.concat([enc, recon_features], -1))
|
277
|
+
gamma = cast(tf.Tensor, self.gmm_density(z))
|
278
|
+
return x_recon, z, gamma
|
279
|
+
|
280
|
+
|
281
|
+
class VAEGMM(keras.Model):
|
282
|
+
"""
|
283
|
+
Variational Autoencoding Gaussian Mixture Model.
|
284
|
+
|
285
|
+
Parameters
|
286
|
+
----------
|
287
|
+
encoder_net : keras.Sequential
|
288
|
+
Layers for the encoder wrapped in a keras.keras.Sequential class.
|
289
|
+
decoder_net : keras.Sequential
|
290
|
+
Layers for the decoder wrapped in a keras.keras.Sequential class.
|
291
|
+
gmm_density_net : keras.Sequential
|
292
|
+
Layers for the GMM network wrapped in a keras.keras.Sequential class.
|
293
|
+
n_gmm : int
|
294
|
+
Number of components in GMM.
|
295
|
+
latent_dim : int
|
296
|
+
Dimensionality of the :term:`latent space<Latent Space>`.
|
297
|
+
beta : float, default 1.0
|
298
|
+
Beta parameter for KL-divergence loss term.
|
299
|
+
"""
|
300
|
+
|
301
|
+
def __init__(
|
302
|
+
self,
|
303
|
+
encoder_net: keras.Sequential,
|
304
|
+
decoder_net: keras.Sequential,
|
305
|
+
gmm_density_net: keras.Sequential,
|
306
|
+
n_gmm: int,
|
307
|
+
latent_dim: int,
|
308
|
+
beta: float = 1.0,
|
309
|
+
) -> None:
|
310
|
+
super().__init__(name="vaegmm")
|
311
|
+
self.encoder: keras.Sequential = EncoderVAE(encoder_net, latent_dim)
|
312
|
+
self.decoder: keras.Sequential = decoder_net
|
313
|
+
self.gmm_density: keras.Sequential = gmm_density_net
|
314
|
+
self.n_gmm: int = n_gmm
|
315
|
+
self.latent_dim: int = latent_dim
|
316
|
+
self.beta = beta
|
317
|
+
|
318
|
+
def call(
|
319
|
+
self, inputs: tf.Tensor, training: bool | None = None, mask: tf.Tensor | None = None
|
320
|
+
) -> tuple[tf.Tensor, tf.Tensor, tf.Tensor]:
|
321
|
+
enc_mean, enc_log_var, enc = cast(tuple[tf.Tensor, tf.Tensor, tf.Tensor], self.encoder(inputs))
|
322
|
+
x_recon = cast(tf.Tensor, self.decoder(enc))
|
323
|
+
recon_features = eucl_cosim_features(inputs, x_recon)
|
324
|
+
z = cast(tf.Tensor, tf.concat([enc, recon_features], -1))
|
325
|
+
gamma = cast(tf.Tensor, self.gmm_density(z))
|
326
|
+
# add KL divergence loss term
|
327
|
+
kl_loss = -0.5 * tf.reduce_mean(enc_log_var - tf.square(enc_mean) - tf.exp(enc_log_var) + 1)
|
328
|
+
self.add_loss(self.beta * kl_loss)
|
329
|
+
return x_recon, z, gamma
|
36
330
|
|
37
331
|
|
38
332
|
class WeightNorm(keras.layers.Wrapper):
|
@@ -182,7 +476,7 @@ class WeightNorm(keras.layers.Wrapper):
|
|
182
476
|
return tf.TensorShape(self.layer.compute_output_shape(input_shape).as_list())
|
183
477
|
|
184
478
|
|
185
|
-
class Shift(
|
479
|
+
class Shift(bijectors.Bijector):
|
186
480
|
def __init__(self, shift, validate_args=False, name="shift") -> None:
|
187
481
|
"""Instantiates the `Shift` bijector which computes `Y = g(X; shift) = X + shift`
|
188
482
|
where `shift` is a numeric `Tensor`.
|
@@ -197,8 +491,8 @@ class Shift(bijector.Bijector):
|
|
197
491
|
Python `str` name given to ops managed by this object.
|
198
492
|
"""
|
199
493
|
with tf.name_scope(name) as name:
|
200
|
-
dtype = dtype_util.common_dtype([shift], dtype_hint=tf.float32)
|
201
|
-
self._shift = tensor_util.convert_nonref_to_tensor(shift, dtype=dtype, name="shift")
|
494
|
+
dtype = tfp_internal.dtype_util.common_dtype([shift], dtype_hint=tf.float32)
|
495
|
+
self._shift = tfp_internal.tensor_util.convert_nonref_to_tensor(shift, dtype=dtype, name="shift")
|
202
496
|
super().__init__(
|
203
497
|
forward_min_event_ndims=0,
|
204
498
|
is_constant_jacobian=True,
|
@@ -226,12 +520,12 @@ class Shift(bijector.Bijector):
|
|
226
520
|
# is_constant_jacobian = True for this bijector, hence the
|
227
521
|
# `log_det_jacobian` need only be specified for a single input, as this will
|
228
522
|
# be tiled to match `event_ndims`.
|
229
|
-
return tf.zeros([], dtype=dtype_util.base_dtype(x.dtype))
|
523
|
+
return tf.zeros([], dtype=tfp_internal.dtype_util.base_dtype(x.dtype))
|
230
524
|
|
231
525
|
|
232
|
-
class PixelCNN(distribution.Distribution):
|
526
|
+
class PixelCNN(distributions.distribution.Distribution):
|
233
527
|
"""
|
234
|
-
Construct Pixel CNN++ distribution.
|
528
|
+
Construct Pixel CNN++ distributions.distribution.
|
235
529
|
|
236
530
|
Parameters
|
237
531
|
----------
|
@@ -246,7 +540,7 @@ class PixelCNN(distribution.Distribution):
|
|
246
540
|
num_filters : int, default 160
|
247
541
|
The number of convolutional filters.
|
248
542
|
num_logistic_mix : int, default 10
|
249
|
-
Number of components in the logistic mixture distribution.
|
543
|
+
Number of components in the distributions.logistic mixture distributions.distribution.
|
250
544
|
receptive_field_dims tuple, default (3, 3)
|
251
545
|
Height and width in pixels of the receptive field of the convolutional layers above and to the left
|
252
546
|
of a given pixel. The width (second element of the tuple) should be odd. Figure 1 (middle) of [2]
|
@@ -292,20 +586,20 @@ class PixelCNN(distribution.Distribution):
|
|
292
586
|
with tf.name_scope("PixelCNN") as name:
|
293
587
|
super().__init__(
|
294
588
|
dtype=dtype,
|
295
|
-
reparameterization_type=reparameterization.NOT_REPARAMETERIZED,
|
589
|
+
reparameterization_type=tfp_internal.reparameterization.NOT_REPARAMETERIZED,
|
296
590
|
validate_args=False,
|
297
591
|
allow_nan_stats=True,
|
298
592
|
parameters=parameters,
|
299
593
|
name=name,
|
300
594
|
)
|
301
595
|
|
302
|
-
if not tensorshape_util.is_fully_defined(image_shape):
|
596
|
+
if not tfp_internal.tensorshape_util.is_fully_defined(image_shape):
|
303
597
|
raise ValueError("`image_shape` must be fully defined.")
|
304
598
|
|
305
|
-
if conditional_shape is not None and not tensorshape_util.is_fully_defined(conditional_shape):
|
599
|
+
if conditional_shape is not None and not tfp_internal.tensorshape_util.is_fully_defined(conditional_shape):
|
306
600
|
raise ValueError("`conditional_shape` must be fully defined.")
|
307
601
|
|
308
|
-
if tensorshape_util.rank(image_shape) != 3:
|
602
|
+
if tfp_internal.tensorshape_util.rank(image_shape) != 3:
|
309
603
|
raise ValueError("`image_shape` must have length 3, representing [height, width, channels] dimensions.")
|
310
604
|
|
311
605
|
self._high = tf.cast(high, self.dtype)
|
@@ -325,11 +619,11 @@ class PixelCNN(distribution.Distribution):
|
|
325
619
|
dtype=dtype,
|
326
620
|
)
|
327
621
|
|
328
|
-
image_input_shape = tensorshape_util.concatenate([None], image_shape)
|
622
|
+
image_input_shape = tfp_internal.tensorshape_util.concatenate([None], image_shape)
|
329
623
|
if conditional_shape is None:
|
330
624
|
input_shape = image_input_shape
|
331
625
|
else:
|
332
|
-
conditional_input_shape = tensorshape_util.concatenate([None], conditional_shape)
|
626
|
+
conditional_input_shape = tfp_internal.tensorshape_util.concatenate([None], conditional_shape)
|
333
627
|
input_shape = [image_input_shape, conditional_input_shape]
|
334
628
|
|
335
629
|
self.image_shape = image_shape
|
@@ -337,12 +631,12 @@ class PixelCNN(distribution.Distribution):
|
|
337
631
|
self._network.build(input_shape)
|
338
632
|
|
339
633
|
def _make_mixture_dist(self, component_logits, locs, scales, return_per_feature: bool = False):
|
340
|
-
"""Builds a mixture of quantized logistic distributions.
|
634
|
+
"""Builds a mixture of quantized distributions.logistic distributions.
|
341
635
|
|
342
636
|
Parameters
|
343
637
|
----------
|
344
638
|
component_logits
|
345
|
-
4D `Tensor` of logits for the Categorical distribution
|
639
|
+
4D `Tensor` of logits for the Categorical distributions.distribution
|
346
640
|
over Quantized Logistic mixture components. Dimensions are `[batch_size,
|
347
641
|
height, width, num_logistic_mix]`.
|
348
642
|
locs
|
@@ -359,17 +653,17 @@ class PixelCNN(distribution.Distribution):
|
|
359
653
|
Returns
|
360
654
|
-------
|
361
655
|
dist
|
362
|
-
A quantized logistic mixture `tfp.distribution` over the input data.
|
656
|
+
A quantized distributions.logistic mixture `tfp.distributions.distribution` over the input data.
|
363
657
|
"""
|
364
|
-
mixture_distribution = categorical.Categorical(logits=component_logits)
|
658
|
+
mixture_distribution = distributions.categorical.Categorical(logits=component_logits)
|
365
659
|
|
366
|
-
# Convert distribution parameters for pixel values in
|
660
|
+
# Convert distributions.distribution parameters for pixel values in
|
367
661
|
# `[self._low, self._high]` for use with `QuantizedDistribution`
|
368
662
|
locs = self._low + 0.5 * (self._high - self._low) * (locs + 1.0)
|
369
663
|
scales *= 0.5 * (self._high - self._low)
|
370
|
-
logistic_dist = quantized_distribution.QuantizedDistribution(
|
371
|
-
distribution=transformed_distribution.TransformedDistribution(
|
372
|
-
distribution=logistic.Logistic(loc=locs, scale=scales),
|
664
|
+
logistic_dist = distributions.quantized_distribution.QuantizedDistribution(
|
665
|
+
distribution=distributions.transformed_distribution.TransformedDistribution(
|
666
|
+
distribution=distributions.logistic.Logistic(loc=locs, scale=scales),
|
373
667
|
bijector=Shift(shift=tf.cast(-0.5, self.dtype)),
|
374
668
|
),
|
375
669
|
low=self._low,
|
@@ -377,20 +671,20 @@ class PixelCNN(distribution.Distribution):
|
|
377
671
|
)
|
378
672
|
|
379
673
|
# mixture with logistics for the loc and scale on each pixel for each component
|
380
|
-
dist = mixture_same_family.MixtureSameFamily(
|
674
|
+
dist = distributions.mixture_same_family.MixtureSameFamily(
|
381
675
|
mixture_distribution=mixture_distribution,
|
382
|
-
components_distribution=independent.Independent(logistic_dist, reinterpreted_batch_ndims=1),
|
676
|
+
components_distribution=distributions.independent.Independent(logistic_dist, reinterpreted_batch_ndims=1),
|
383
677
|
)
|
384
678
|
if return_per_feature:
|
385
679
|
return dist
|
386
680
|
else:
|
387
|
-
return independent.Independent(dist, reinterpreted_batch_ndims=2)
|
681
|
+
return distributions.independent.Independent(dist, reinterpreted_batch_ndims=2)
|
388
682
|
|
389
683
|
def _log_prob(self, value, conditional_input=None, training=None, return_per_feature=False):
|
390
684
|
"""Log probability function with optional conditional input.
|
391
685
|
|
392
686
|
Calculates the log probability of a batch of data under the modeled
|
393
|
-
distribution (or conditional distribution, if conditional input is
|
687
|
+
distributions.distribution (or conditional distributions.distribution, if conditional input is
|
394
688
|
provided).
|
395
689
|
|
396
690
|
Parameters
|
@@ -400,7 +694,7 @@ class PixelCNN(distribution.Distribution):
|
|
400
694
|
dimension(s), which must broadcast to the leading batch dimensions of
|
401
695
|
`conditional_input`.
|
402
696
|
conditional_input
|
403
|
-
`Tensor` on which to condition the distribution (e.g.
|
697
|
+
`Tensor` on which to condition the distributions.distribution (e.g.
|
404
698
|
class labels), or `None`. May have leading batch dimension(s), which
|
405
699
|
must broadcast to the leading batch dimensions of `value`.
|
406
700
|
training
|
@@ -415,38 +709,38 @@ class PixelCNN(distribution.Distribution):
|
|
415
709
|
log_prob_values: `Tensor`.
|
416
710
|
"""
|
417
711
|
# Determine the batch shape of the input images
|
418
|
-
image_batch_shape = prefer_static.shape(value)[:-3]
|
712
|
+
image_batch_shape = tfp_internal.prefer_static.shape(value)[:-3]
|
419
713
|
|
420
714
|
# Broadcast `value` and `conditional_input` to the same batch_shape
|
421
715
|
if conditional_input is None:
|
422
716
|
image_batch_and_conditional_shape = image_batch_shape
|
423
717
|
else:
|
424
718
|
conditional_input = tf.convert_to_tensor(conditional_input)
|
425
|
-
conditional_input_shape = prefer_static.shape(conditional_input)
|
426
|
-
conditional_batch_rank = prefer_static.rank(
|
427
|
-
|
428
|
-
)
|
719
|
+
conditional_input_shape = tfp_internal.prefer_static.shape(conditional_input)
|
720
|
+
conditional_batch_rank = tfp_internal.prefer_static.rank(
|
721
|
+
conditional_input
|
722
|
+
) - tfp_internal.tensorshape_util.rank(self.conditional_shape)
|
429
723
|
conditional_batch_shape = conditional_input_shape[:conditional_batch_rank]
|
430
724
|
|
431
|
-
image_batch_and_conditional_shape = prefer_static.broadcast_shape(
|
725
|
+
image_batch_and_conditional_shape = tfp_internal.prefer_static.broadcast_shape(
|
432
726
|
image_batch_shape, conditional_batch_shape
|
433
727
|
)
|
434
728
|
conditional_input = tf.broadcast_to(
|
435
729
|
conditional_input,
|
436
|
-
prefer_static.concat([image_batch_and_conditional_shape, self.conditional_shape], axis=0),
|
730
|
+
tfp_internal.prefer_static.concat([image_batch_and_conditional_shape, self.conditional_shape], axis=0),
|
437
731
|
)
|
438
732
|
value = tf.broadcast_to(
|
439
733
|
value,
|
440
|
-
prefer_static.concat([image_batch_and_conditional_shape, self.event_shape], axis=0),
|
734
|
+
tfp_internal.prefer_static.concat([image_batch_and_conditional_shape, self.event_shape], axis=0),
|
441
735
|
)
|
442
736
|
|
443
737
|
# Flatten batch dimension for input to Keras model
|
444
738
|
conditional_input = tf.reshape(
|
445
739
|
conditional_input,
|
446
|
-
prefer_static.concat([(-1,), self.conditional_shape], axis=0),
|
740
|
+
tfp_internal.prefer_static.concat([(-1,), self.conditional_shape], axis=0),
|
447
741
|
)
|
448
742
|
|
449
|
-
value = tf.reshape(value, prefer_static.concat([(-1,), self.event_shape], axis=0))
|
743
|
+
value = tf.reshape(value, tfp_internal.prefer_static.concat([(-1,), self.event_shape], axis=0))
|
450
744
|
|
451
745
|
transformed_value = (2.0 * (value - self._low) / (self._high - self._low)) - 1.0
|
452
746
|
inputs = transformed_value if conditional_input is None else [transformed_value, conditional_input]
|
@@ -459,7 +753,7 @@ class PixelCNN(distribution.Distribution):
|
|
459
753
|
else:
|
460
754
|
# If there is more than one channel, we create a linear autoregressive
|
461
755
|
# dependency among the location parameters of the channels of a single
|
462
|
-
# pixel (the scale parameters within a pixel are independent). For a pixel
|
756
|
+
# pixel (the scale parameters within a pixel are distributions.independent). For a pixel
|
463
757
|
# with R/G/B channels, the `r`, `g`, and `b` saturation values are
|
464
758
|
# distributed as:
|
465
759
|
#
|
@@ -489,7 +783,7 @@ class PixelCNN(distribution.Distribution):
|
|
489
783
|
return tf.reshape(log_px, image_batch_and_conditional_shape)
|
490
784
|
|
491
785
|
def _sample_n(self, n, seed=None, conditional_input=None, training=False):
|
492
|
-
"""Samples from the distribution, with optional conditional input.
|
786
|
+
"""Samples from the distributions.distribution, with optional conditional input.
|
493
787
|
|
494
788
|
Parameters
|
495
789
|
----------
|
@@ -499,7 +793,7 @@ class PixelCNN(distribution.Distribution):
|
|
499
793
|
`int`, seed for RNG. Setting a random seed enforces reproducibility
|
500
794
|
of the samples between sessions (not within a single session).
|
501
795
|
conditional_input
|
502
|
-
`Tensor` on which to condition the distribution (e.g.
|
796
|
+
`Tensor` on which to condition the distributions.distribution (e.g.
|
503
797
|
class labels), or `None`.
|
504
798
|
training
|
505
799
|
`bool` or `None`. If `bool`, it controls the dropout layer,
|
@@ -513,9 +807,9 @@ class PixelCNN(distribution.Distribution):
|
|
513
807
|
"""
|
514
808
|
if conditional_input is not None:
|
515
809
|
conditional_input = tf.convert_to_tensor(conditional_input, dtype=self.dtype)
|
516
|
-
conditional_event_rank = tensorshape_util.rank(self.conditional_shape)
|
517
|
-
conditional_input_shape = prefer_static.shape(conditional_input)
|
518
|
-
conditional_sample_rank = prefer_static.rank(conditional_input) - conditional_event_rank
|
810
|
+
conditional_event_rank = tfp_internal.tensorshape_util.rank(self.conditional_shape)
|
811
|
+
conditional_input_shape = tfp_internal.prefer_static.shape(conditional_input)
|
812
|
+
conditional_sample_rank = tfp_internal.prefer_static.rank(conditional_input) - conditional_event_rank
|
519
813
|
|
520
814
|
# If `conditional_input` has no sample dimensions, prepend a sample
|
521
815
|
# dimension
|
@@ -528,14 +822,14 @@ class PixelCNN(distribution.Distribution):
|
|
528
822
|
conditional_event_shape = conditional_input_shape[conditional_sample_rank:]
|
529
823
|
with tf.control_dependencies([tf.assert_equal(self.conditional_shape, conditional_event_shape)]):
|
530
824
|
conditional_sample_shape = conditional_input_shape[:conditional_sample_rank]
|
531
|
-
repeat = n // prefer_static.reduce_prod(conditional_sample_shape)
|
825
|
+
repeat = n // tfp_internal.prefer_static.reduce_prod(conditional_sample_shape)
|
532
826
|
h = tf.reshape(
|
533
827
|
conditional_input,
|
534
|
-
prefer_static.concat([(-1,), self.conditional_shape], axis=0),
|
828
|
+
tfp_internal.prefer_static.concat([(-1,), self.conditional_shape], axis=0),
|
535
829
|
)
|
536
830
|
h = tf.tile(
|
537
831
|
h,
|
538
|
-
prefer_static.pad(
|
832
|
+
tfp_internal.prefer_static.pad(
|
539
833
|
[repeat],
|
540
834
|
paddings=[[0, conditional_event_rank]],
|
541
835
|
constant_values=1,
|
@@ -543,7 +837,7 @@ class PixelCNN(distribution.Distribution):
|
|
543
837
|
)
|
544
838
|
|
545
839
|
samples_0 = tf.random.uniform(
|
546
|
-
prefer_static.concat([(n,), self.event_shape], axis=0),
|
840
|
+
tfp_internal.prefer_static.concat([(n,), self.event_shape], axis=0),
|
547
841
|
minval=-1.0,
|
548
842
|
maxval=1.0,
|
549
843
|
dtype=self.dtype,
|
@@ -553,7 +847,7 @@ class PixelCNN(distribution.Distribution):
|
|
553
847
|
params_0 = self._network(inputs, training=training)
|
554
848
|
samples_0 = self._sample_channels(*params_0, seed=seed)
|
555
849
|
|
556
|
-
image_height, image_width, _ = tensorshape_util.as_list(self.event_shape)
|
850
|
+
image_height, image_width, _ = tfp_internal.tensorshape_util.as_list(self.event_shape)
|
557
851
|
|
558
852
|
def loop_body(index, samples):
|
559
853
|
"""Loop for iterative pixel sampling.
|
@@ -605,7 +899,7 @@ class PixelCNN(distribution.Distribution):
|
|
605
899
|
Parameters
|
606
900
|
----------
|
607
901
|
component_logits
|
608
|
-
4D `Tensor` of logits for the Categorical distribution
|
902
|
+
4D `Tensor` of logits for the Categorical distributions.distribution
|
609
903
|
over Quantized Logistic mixture components. Dimensions are `[batch_size,
|
610
904
|
height, width, num_logistic_mix]`.
|
611
905
|
locs
|
@@ -633,7 +927,7 @@ class PixelCNN(distribution.Distribution):
|
|
633
927
|
num_channels = self.event_shape[-1]
|
634
928
|
|
635
929
|
# sample mixture components once for the entire pixel
|
636
|
-
component_dist = categorical.Categorical(logits=component_logits)
|
930
|
+
component_dist = distributions.categorical.Categorical(logits=component_logits)
|
637
931
|
mask = tf.one_hot(indices=component_dist.sample(seed=seed), depth=self._num_logistic_mix)
|
638
932
|
mask = tf.cast(mask[..., tf.newaxis], self.dtype)
|
639
933
|
|
@@ -656,7 +950,7 @@ class PixelCNN(distribution.Distribution):
|
|
656
950
|
loc += c * coef_tensors[coef_count]
|
657
951
|
coef_count += 1
|
658
952
|
|
659
|
-
logistic_samp = logistic.Logistic(loc=loc, scale=scale_tensors[i]).sample(seed=seed)
|
953
|
+
logistic_samp = distributions.logistic.Logistic(loc=loc, scale=scale_tensors[i]).sample(seed=seed)
|
660
954
|
logistic_samp = tf.clip_by_value(logistic_samp, -1.0, 1.0)
|
661
955
|
channel_samples.append(logistic_samp)
|
662
956
|
|
@@ -670,7 +964,7 @@ class PixelCNN(distribution.Distribution):
|
|
670
964
|
|
671
965
|
|
672
966
|
class PixelCNNNetwork(keras.layers.Layer):
|
673
|
-
"""Keras `Layer` to parameterize a Pixel CNN++ distribution.
|
967
|
+
"""Keras `Layer` to parameterize a Pixel CNN++ distributions.distribution.
|
674
968
|
This is a Keras implementation of the Pixel CNN++ network, as described in
|
675
969
|
Salimans et al. (2017)[1] and van den Oord et al. (2016)[2].
|
676
970
|
(https://github.com/openai/pixel-cnn).
|
@@ -702,7 +996,7 @@ class PixelCNNNetwork(keras.layers.Layer):
|
|
702
996
|
use_data_init: bool = True,
|
703
997
|
dtype: tf.DType = tf.float32,
|
704
998
|
) -> None:
|
705
|
-
"""Initialize the :term:`neural network<Neural Network>` for the Pixel CNN++ distribution.
|
999
|
+
"""Initialize the :term:`neural network<Neural Network>` for the Pixel CNN++ distributions.distribution.
|
706
1000
|
|
707
1001
|
Parameters
|
708
1002
|
----------
|
@@ -717,8 +1011,8 @@ class PixelCNNNetwork(keras.layers.Layer):
|
|
717
1011
|
num_filters
|
718
1012
|
`int`, the number of convolutional filters.
|
719
1013
|
num_logistic_mix
|
720
|
-
`int`, number of components in the logistic mixture
|
721
|
-
distribution.
|
1014
|
+
`int`, number of components in the distributions.logistic mixture
|
1015
|
+
distributions.distribution.
|
722
1016
|
receptive_field_dims
|
723
1017
|
`tuple`, height and width in pixels of the receptive
|
724
1018
|
field of the convolutional layers above and to the left of a given
|
@@ -1004,21 +1298,21 @@ class PixelCNNNetwork(keras.layers.Layer):
|
|
1004
1298
|
|
1005
1299
|
# Build final Dense/Reshape layers to output the correct number of
|
1006
1300
|
# parameters per pixel.
|
1007
|
-
num_channels = tensorshape_util.as_list(image_shape)[-1]
|
1301
|
+
num_channels = tfp_internal.tensorshape_util.as_list(image_shape)[-1]
|
1008
1302
|
num_coeffs = num_channels * (num_channels - 1) // 2 # alpha, beta, gamma in eq.3 of paper
|
1009
1303
|
num_out = num_channels * 2 + num_coeffs + 1 # mu, s + alpha, beta, gamma + 1 (mixture weight)
|
1010
1304
|
num_out_total = num_out * self._num_logistic_mix
|
1011
1305
|
params = Dense(num_out_total)(x_out)
|
1012
1306
|
params = tf.reshape(
|
1013
1307
|
params,
|
1014
|
-
prefer_static.concat( # [-1,H,W,nb mixtures, params per mixture]
|
1308
|
+
tfp_internal.prefer_static.concat( # [-1,H,W,nb mixtures, params per mixture]
|
1015
1309
|
[[-1], image_shape[:-1], [self._num_logistic_mix, num_out]], axis=0
|
1016
1310
|
),
|
1017
1311
|
)
|
1018
1312
|
|
1019
1313
|
# If there is one color channel, split the parameters into a list of three
|
1020
1314
|
# output `Tensor`s: (1) component logits for the Quantized Logistic mixture
|
1021
|
-
# distribution, (2) location parameters for each component, and (3) scale
|
1315
|
+
# distributions.distribution, (2) location parameters for each component, and (3) scale
|
1022
1316
|
# parameters for each component. If there is more than one color channel,
|
1023
1317
|
# return a fourth `Tensor` for the coefficients for the linear dependence
|
1024
1318
|
# among color channels (e.g. alpha, beta, gamma).
|
@@ -1056,7 +1350,7 @@ class PixelCNNNetwork(keras.layers.Layer):
|
|
1056
1350
|
-------
|
1057
1351
|
outputs
|
1058
1352
|
a 3- or 4-element `list` of `Tensor`s in the following order: \
|
1059
|
-
component_logits: 4D `Tensor` of logits for the Categorical distribution \
|
1353
|
+
component_logits: 4D `Tensor` of logits for the Categorical distributions.distribution \
|
1060
1354
|
over Quantized Logistic mixture components. Dimensions are \
|
1061
1355
|
`[batch_size, height, width, num_logistic_mix]`.
|
1062
1356
|
locs
|