class_docstr: Generalized divisive normalization layer.
  
  Based on the papers:
  
  > "Density modeling of images using a generalized normalization
  > transformation"<br />
  > J. Ballé, V. Laparra, E.P. Simoncelli<br />
  > https://arxiv.org/abs/1511.06281
  
  > "End-to-end optimized image compression"<br />
  > J. Ballé, V. Laparra, E.P. Simoncelli<br />
  > https://arxiv.org/abs/1611.01704
  
  Implements an activation function that is a multivariate generalization of a
  particular sigmoid-type function:
  
  ```
  y[i] = x[i] / (beta[i] + sum_j(gamma[j, i] * |x[j]|^alpha))^epsilon
  ```
  
  where `i` and `j` run over channels. This implementation never sums across
  spatial dimensions. It is similar to local response normalization, but much
  more flexible, as `alpha`, `beta`, `gamma`, and `epsilon` are trainable
  parameters.
  
  Attributes:
    inverse: Boolean. If `False`, compute GDN response. If `True`, compute IGDN
      response (one step of fixed point iteration to invert GDN; the division is
      replaced by multiplication).
    rectify: Boolean. If `True`, apply a `relu` nonlinearity to the inputs
      before calculating GDN response.
    data_format: String. Format of input tensor. Currently supports
      `'channels_first'` and `'channels_last'`.
    alpha_parameter: Scalar, callable, or `None`. A number or scalar `tf.Tensor`
      means that the value of alpha is fixed. A callable can be used to
      determine the value of alpha as a function of some other variable or
      tensor. This can be a `Parameter` object. `None` means that when the layer
      is built, a `GDNParameter` object is created to train alpha (with a
      minimum value of 1). The default is a fixed value of 1. Note that certain
      choices here such as `tf.Tensor`s or lambda functions may prevent
      JSON-style serialization (`Parameter` objects and Python constants work).
    beta_parameter: Tensor, callable, or `None`. A `tf.Tensor` means that the
      value of beta is fixed. A callable can be used to determine the value of
      beta as a function of some other variable or tensor. This can be a
      `Parameter` object. `None` means that when the layer is built, a
      `GDNParameter` object is created to train beta (with a minimum value of
      1e-6). Note that certain choices here such as `tf.Tensor`s or lambda
      functions may prevent JSON-style serialization (`Parameter` objects work).
    gamma_parameter: Tensor, callable, or `None`. A `tf.Tensor` means that the
      value of gamma is fixed. A callable can be used to determine the value of
      gamma as a function of some other variable or tensor. This can be a
      `Parameter` object. `None` means that when the layer is built, a
      `GDNParameter` object is created to train gamma. Note that certain choices
      here such as `tf.Tensor`s or lambda functions may prevent JSON-style
      serialization (`Parameter` objects work).
    epsilon_parameter: Scalar, callable, or `None`. A number or scalar
      `tf.Tensor` means that the value of epsilon is fixed. A callable can be
      used to determine the value of epsilon as a function of some other
      variable or tensor. This can be a `Parameter` object. `None` means that
      when the layer is built, a `GDNParameter` object is created to train
      epsilon (with a minimum value of 1e-6). The default is a fixed value of 1.
      Note that certain choices here such as `tf.Tensor`s or lambda functions
      may prevent JSON-style serialization (`Parameter` objects and Python
      constants work).
    alpha_initializer: `Initializer` object for alpha parameter. Only used if
      alpha is trained. Defaults to 1.
    beta_initializer: `Initializer` object for beta parameter. Only used if beta
      is created on building the layer. Defaults to 1.
    gamma_initializer: `Initializer` object for gamma parameter. Only used if
      gamma is created on building the layer. Defaults to identity matrix
      multiplied by 0.1. A good default value for the diagonal is somewhere
      between 0 and 0.5. If set to 0 and beta initialized as 1, the layer is
      effectively initialized to the identity operation.
    epsilon_initializer: `Initializer` object for epsilon parameter. Only used
      if epsilon is trained. Defaults to 1.
    alpha: `tf.Tensor`. Read-only property always returning the current value of
      alpha.
    beta: `tf.Tensor`. Read-only property always returning the current value of
      beta.
    gamma: `tf.Tensor`. Read-only property always returning the current value of
      gamma.
    epsilon: `tf.Tensor`. Read-only property always returning the current value
      of epsilon.
code: def call(self, inputs) -> tf.Tensor:
      rank = inputs.shape.rank
      if rank is None or rank < 2:
          raise ValueError(
              f"Input tensor must have at least rank 2, received "
              f"shape {inputs.shape}."
          )
  
      if self.rectify:
          inputs = tf.nn.relu(inputs)
  
      # Optimize for fixed alphas.
      if (
          not callable(self.alpha_parameter)
          and self.alpha == 1
          and self.rectify
      ):
          norm_pool = inputs
      elif not callable(self.alpha_parameter) and self.alpha == 1:
          norm_pool = abs(inputs)
      elif not callable(self.alpha_parameter) and self.alpha == 2:
          norm_pool = tf.math.square(inputs)
      else:
          norm_pool = inputs**self.alpha
  
      # Compute normalization pool.
      if rank == 2:
          norm_pool = tf.linalg.matmul(norm_pool, self.gamma)
          norm_pool = tf.nn.bias_add(norm_pool, self.beta)
      elif self.data_format == "channels_last" and rank <= 5:
          shape = self.gamma.shape
          gamma = tf.reshape(self.gamma, (rank - 2) * [1] + shape)
          norm_pool = tf.nn.convolution(
              norm_pool, gamma, padding="VALID"
          )
          norm_pool = tf.nn.bias_add(norm_pool, self.beta)
      else:  # generic implementation
          # This puts channels in the last dimension regardless of input.
          norm_pool = tf.linalg.tensordot(
              norm_pool, self.gamma, [[self._channel_axis], [0]]
          )
          norm_pool += self.beta
          if self.data_format == "channels_first":
              # Return to channels_first format if necessary.
              axes = list(range(rank - 1))
              axes.insert(1, rank - 1)
              norm_pool = tf.transpose(norm_pool, axes)
  
      # Optimize for fixed epsilons.
      if not callable(self.epsilon_parameter) and self.epsilon == 1:
          pass
      elif not callable(self.epsilon_parameter) and self.epsilon == 0.5:
          norm_pool = tf.math.sqrt(norm_pool)
      else:
          norm_pool = norm_pool**self.epsilon
  
      if self.inverse:
          return inputs * norm_pool
      else:
          return inputs / norm_pool
  
imports: from typing import Any, Callable, Dict, Union
  import tensorflow
  from tensorflow_compression.python.layers import parameters
label_desc: Use image node_id 31 for calling the GDN obj's underlying member method code with example usage: obj.call(inputs) and returns: unknown, unknown