Source code for zea.backend.tensorflow.layers.utils
"""
Tensorflow utilities
"""
import keras
import numpy as np
import tensorflow as tf
from keras.layers import Lambda, LeakyReLU, ReLU
PI = tf.experimental.numpy.pi
[docs]
def antirect(x):
"""Function that implements the antirectifier activation"""
mean, _ = tf.nn.moments(x, axes=-1, keepdims=True)
x = tf.math.l2_normalize(x - mean, axis=-1)
return tf.nn.crelu(x)
[docs]
def get_activation(activation: str = None):
"""Get activation function given string.
Args:
activation (str, optional): name of activation
function. Defaults to None.
Raises:
ValueError: Cannot find activation function
Returns:
Tensorflow activation function
"""
if activation.lower() == "relu":
return ReLU()
elif activation.lower() == "leakyrelu":
return LeakyReLU()
elif activation.lower() == "swish":
return Lambda(lambda x: keras.activations.swish(x))
elif activation.lower() == "sigmoid":
return Lambda(lambda x: keras.activations.sigmoid(x))
elif activation is None:
return Lambda(lambda x: x)
else:
raise ValueError("Unknown activation function.")
[docs]
def tf_cropping_and_padding(input_shape, target_shape):
"""Crop or pad a tensor to the specified shape.
Args:
input_shape: A list or tuple of integers representing the input shape.
target_shape: A list or tuple of integers representing the desired shape.
Returns:
A tensorflow cropping layer (2D) for 4D tensors.
"""
assert len(input_shape) == len(target_shape) == 2, "can only do 2D cropping"
# Calculate the amount of cropping needed for each dimension
diff = np.array(input_shape) - np.array(target_shape)
cropping = ((0, diff[0]), (0, diff[1]))
# replace negative values with zero and make padding tuple of tuples
padding = tuple(tuple(0 if x > 0 else -x for x in row) for row in cropping)
cropping = tuple(tuple(0 if x < 0 else x for x in row) for row in cropping)
# Create a Cropping2D layer with the calculated crop amounts
cropping_layer = keras.layers.Cropping2D(cropping=cropping)
# Create a ZeroPadding2D layer with the calculated padding amounts
padding_layer = keras.layers.ZeroPadding2D(padding=padding)
return cropping_layer, padding_layer
[docs]
def tf_complex_resize(tensor, image_size):
"""Resize / interpolate complex tensor"""
magnitude = tf.math.abs(tensor)
phase = tf.math.angle(tensor)
# unwrap phase
phase = tf_unwrap(phase)
magnitude = tf.image.resize(magnitude, image_size)
phase = tf.image.resize(phase, image_size)
phase = tf.complex(tf.cast(0.0, dtype=phase.dtype), phase)
magnitude = tf.cast(magnitude, dtype=tf.complex64)
# complex = magnitude * exp(1j * phase)
return tf.math.multiply(magnitude, tf.math.exp(phase))
[docs]
def tf_unwrap(tensor, axis=0):
"""Tensorflow phase unwrapping function"""
pi_tf = tf.cast(PI, dtype=tensor.dtype)
dphi = tf.experimental.numpy.diff(tensor, axis=axis)
dphi_pad = tf.gather(dphi, 0, axis=axis)
dphi_pad = tf.expand_dims(dphi_pad, axis=axis)
dphi = tf.concat([dphi_pad, dphi], axis=axis)
dphi_m = ((dphi + pi_tf) % (2.0 * pi_tf)) - pi_tf
dphi_m = tf.where((dphi_m == -PI) & (dphi > 0.0), pi_tf, dphi_m)
phi_adj = dphi_m - dphi
phi_adj = tf.where(tf.abs(dphi) < pi_tf, 0.0, phi_adj)
return tensor + tf.math.cumsum(phi_adj, axis=axis)