import os
from typing import Tuple
import numpy as np
import tensorflow as tf
import tensorflow.keras.backend as K
from deprecated import deprecated
from packaging.version import parse as version
MAX_STEPS = 'TF_KERAS_VIS_MAX_STEPS'
@deprecated(version='0.7.0')
def check_steps(steps):
return get_num_of_steps_allowed(steps)
def get_num_of_steps_allowed(steps) -> int:
return min(steps, int(os.environ[MAX_STEPS])) if MAX_STEPS in os.environ else steps
[docs]
def num_of_gpus() -> Tuple[int, int]:
"""Return the number of physical and logical gpus.
Returns:
Tuple[int, int]: A tuple of the number of physical and logical gpus.
"""
if version(tf.version.VERSION) < version("2.1.0"):
list_physical_devices = tf.config.experimental.list_physical_devices
list_logical_devices = tf.config.experimental.list_logical_devices
else:
list_physical_devices = tf.config.list_physical_devices
list_logical_devices = tf.config.list_logical_devices
physical_gpus = list_physical_devices('GPU')
if physical_gpus:
logical_gpus = list_logical_devices('GPU')
return len(physical_gpus), len(logical_gpus)
else:
return 0, 0
[docs]
def listify(value, return_empty_list_if_none=True, convert_tuple_to_list=True) -> list:
"""Ensures that the value is a list.
If it is not a list, it creates a new list with `value` as an item.
Args:
value (object): A list or something else.
return_empty_list_if_none (bool, optional): When True (default), None you passed as `value`
will be converted to a empty list (i.e., `[]`). When False, None will be converted to
a list that has an None (i.e., `[None]`). Defaults to True.
convert_tuple_to_list (bool, optional): When True (default), a tuple you passed as `value`
will be converted to a list. When False, a tuple will be unconverted
(i.e., returning a tuple object that was passed as `value`). Defaults to True.
Returns:
list: A list. When `value` is a tuple and `convert_tuple_to_list` is False, a tuple.
"""
if not isinstance(value, list):
if value is None and return_empty_list_if_none:
value = []
elif isinstance(value, tuple) and convert_tuple_to_list:
value = list(value)
else:
value = [value]
return value
@deprecated(version='0.8.0', reason="Use `normalize()` instead.")
def standardize(array, value_range=(1., 0.)):
return normalize(array, value_range=(1., 0.))
[docs]
def normalize(array, value_range=(1., 0.)) -> np.ndarray:
"""Normalization.
Args:
array (np.ndarray): A tensor.
value_range (tuple, optional): `array` will be scaled in this range. Defaults to (1., 0.).
Returns:
np.ndarray: Normalize array.
"""
max_value = np.max(array, axis=tuple(range(array.ndim)[1:]), keepdims=True)
min_value = np.min(array, axis=tuple(range(array.ndim)[1:]), keepdims=True)
normalized_array = (array - min_value) / (max_value - min_value + K.epsilon())
return normalized_array
def find_layer(model, condition, offset=None, reverse=True) -> tf.keras.layers.Layer:
found_offset = offset is None
for layer in reversed(model.layers):
if not found_offset:
found_offset = (layer == offset)
if condition(layer) and found_offset:
return layer
if isinstance(layer, tf.keras.Model):
if found_offset:
result = find_layer(layer, condition, offset=None, reverse=reverse)
else:
result = find_layer(layer, condition, offset=offset, reverse=reverse)
if result is not None:
return result
return None
def zoom_factor(from_shape, to_shape) -> Tuple[float, float]:
return tuple(float(t) / float(f) for f, t in zip(from_shape, to_shape))
[docs]
def is_mixed_precision(model) -> bool:
"""Check whether the model has any lower precision variable or not.
Args:
model (tf.keras.Model): A model instance.
Returns:
bool: When the model has any lower precision variable, True.
"""
if version(tf.version.VERSION) >= version("2.4.0"):
for layer in model.layers:
if (layer.compute_dtype == tf.float16) or \
(isinstance(layer, tf.keras.Model) and is_mixed_precision(layer)):
return True
return False
@deprecated(version='0.7.0', reason="Unnecessary function.")
def lower_precision_dtype(model):
if version(tf.version.VERSION) >= version("2.4.0"):
for layer in model.layers:
if (layer.compute_dtype in [tf.float16, tf.bfloat16]) or \
(isinstance(layer, tf.keras.Model) and is_mixed_precision(layer)):
return layer.compute_dtype
return model.dtype # pragma: no cover
def get_input_names(model):
if version(tf.version.VERSION) >= version("2.4.0"):
names = [input.name for input in model.inputs]
else:
names = model.input_names
return names