class_docstr: This class is implements the complex-valued batch-normalization
  as introduced by "Deep Complex Networks", Trabelsi C. et al.
  
  Arguments
  ---------
  input_shape : tuple
      Expected shape of the input.
  input_size : int
      Expected size of the input.
  dim : int, optional
      It defines the axis that should be normalized. It usually correspond to
      the channel dimension (default -1).
  eps : float, optional
      Term used to stabilize operation (default 1e-4).
  momentum : float, optional
      It defines the momentum as for the real-valued batch-normalization
      (default 0.1).
  scale : bool, optional,
      It defines if scaling should be used or not. It is
      equivalent to the real-valued batchnormalization scaling (default True).
  center : bool, optional
      It defines if centering should be used or not. It is
      equivalent to the real-valued batchnormalization centering
      (default True).
  track_running_stats : bool, optional
      Equivalent to the real-valued batchnormalization parameter.
      When True, stats are tracked. When False, solely statistics computed
      over the batch are used (default True).
  
  Example
  -------
  >>> inp_tensor = torch.rand([10, 16, 30])
  >>> CBN = CBatchNorm(input_shape=inp_tensor.shape)
  >>> out_tensor = CBN(inp_tensor)
  >>> out_tensor.shape
  torch.Size([10, 16, 30])
class_docstr_tok: ["This","class","is","implements","the","complex-valued","batch-normalization","as","introduced","by","``","Deep","Complex","Networks","''",",","Trabelsi","C.","et","al",".","Arguments","--","--","--","--","-","input_shape",":","tuple","Expected","shape","of","the","input",".","input_size",":","int","Expected","size","of","the","input",".","dim",":","int",",","optional","It","defines","the","axis","that","should","be","normalized",".","It","usually","correspond","to","the","channel","dimension","(","default","-1",")",".","eps",":","float",",","optional","Term","used","to","stabilize","operation","(","default","1e-4",")",".","momentum",":","float",",","optional","It","defines","the","momentum","as","for","the","real-valued","batch-normalization","(","default","0.1",")",".","scale",":","bool",",","optional",",","It","defines","if","scaling","should","be","used","or","not",".","It","is","equivalent","to","the","real-valued","batchnormalization","scaling","(","default","True",")",".","center",":","bool",",","optional","It","defines","if","centering","should","be","used","or","not",".","It","is","equivalent","to","the","real-valued","batchnormalization","centering","(","default","True",")",".","track_running_stats",":","bool",",","optional","Equivalent","to","the","real-valued","batchnormalization","parameter",".","When","True",",","stats","are","tracked",".","When","False",",","solely","statistics","computed","over","the","batch","are","used","(","default","True",")",".","Example","--","--","--","-",">",">",">","inp_tensor","=","torch.rand","(","[","10",",","16",",","30","]",")",">",">",">","CBN","=","CBatchNorm","(","input_shape=inp_tensor.shape",")",">",">",">","out_tensor","=","CBN","(","inp_tensor",")",">",">",">","out_tensor.shape","torch.Size","(","[","10",",","16",",","30","]",")"]
docstr: Returns the normalized input tensor.
  
  Arguments
  ---------
  input : torch.Tensor (batch, time, [channels])
      Input to normalize. It can be 2d, 3d, 4d.
docstr_tok: ["Returns","the","normalized","input","tensor",".","Arguments","--","--","--","--","-","input",":","torch.Tensor","(","batch",",","time",",","[","channels","]",")","Input","to","normalize",".","It","can","be","2d",",","3d",",","4d","."]
code: def forward(self, input):
      """Returns the normalized input tensor.
  
      Arguments
      ---------
      input : torch.Tensor (batch, time, [channels])
          Input to normalize. It can be 2d, 3d, 4d.
      """
      exponential_average_factor = 0.0
  
      # Initialize moving parameters
      if self.training and self.track_running_stats:
          if self.center:
              self.moving_mean = self.moving_mean.detach()
          if self.scale:
              self.moving_Vrr = self.moving_Vrr.detach()
              self.moving_Vii = self.moving_Vii.detach()
              self.moving_Vri = self.moving_Vri.detach()
  
          self.num_batches_tracked = self.num_batches_tracked.detach()
          self.num_batches_tracked += 1
  
      if self.momentum is None:  # use cumulative moving average
          exponential_average_factor = (
              1.0 / self.num_batches_tracked.item()
          )
      else:  # use exponential moving average
          exponential_average_factor = self.momentum
  
      input_shape = input.size()
      ndim = input.dim()
      reduction_axes = list(range(ndim))
      del reduction_axes[self.dim]
      input_dim = input_shape[self.dim] // 2
  
      # Get the mean and center the input
      mu = multi_mean(input, reduction_axes, True)
      input_centred = input - mu
  
      if self.scale:
          centred_squared = input_centred**2
  
      # Retrieve the real and image parts of the input tensor w.r.t the
      # dimension
      if self.scale:
          (
              centred_squared_real,
              centred_squared_imag,
          ) = self._retrieve_real_imag(centred_squared, ndim, input_dim)
      if self.center:
          centred_real, centred_imag = self._retrieve_real_imag(
              input_centred, ndim, input_dim
          )
  
      # We compute the mean for each component
      if self.scale:
          Vrr = (
              multi_mean(
                  centred_squared_real,
                  axes=reduction_axes,
                  keepdim=True,
              )
              + self.eps
          )
          Vii = (
              multi_mean(
                  centred_squared_imag,
                  axes=reduction_axes,
                  keepdim=True,
              )
              + self.eps
          )
  
          # Vri contains the real and imaginary covariance
          # for each feature map.
          Vri = multi_mean(
              centred_real * centred_imag,
              axes=reduction_axes,
              keepdim=True,
          )
      else:
          Vrr = None
          Vii = None
          Vri = None
  
      # Pick the normalized form corresponding
      # to the training phase when we use running stats.
      if self.training and self.track_running_stats:
          if self.center:
              self.moving_mean = (
                  1 - exponential_average_factor
              ) * self.moving_mean + exponential_average_factor * mu.view(
                  self.moving_mean.size()
              )
          if self.scale:
              self.moving_Vrr = (
                  1 - exponential_average_factor
              ) * self.moving_Vrr + exponential_average_factor * Vrr.view(
                  self.moving_Vrr.size()
              )
              self.moving_Vii = (
                  1 - exponential_average_factor
              ) * self.moving_Vii + exponential_average_factor * Vii.view(
                  self.moving_Vii.size()
              )
              self.moving_Vri = (
                  1 - exponential_average_factor
              ) * self.moving_Vri + exponential_average_factor * Vri.view(
                  self.moving_Vri.size()
              )
  
      if self.training or (not self.track_running_stats):
          input_inferred = input_centred if self.center else input
          return c_norm(
              input_inferred,
              Vrr,
              Vii,
              Vri,
              self.beta,
              self.gamma_rr,
              self.gamma_ri,
              self.gamma_ii,
              self.scale,
              self.center,
              layernorm=False,
              dim=self.dim,
          )
      else:  # if we are not training or using running_stats
          if self.center:
              input_inferred = input - self.moving_mean.view(mu.size())
          else:
              input_inferred = input
          return c_norm(
              input_inferred,
              self.moving_Vrr,
              self.moving_Vii,
              self.moving_Vri,
              self.beta,
              self.gamma_rr,
              self.gamma_ri,
              self.gamma_ii,
              self.scale,
              self.center,
              layernorm=False,
              dim=self.dim,
          )
  
imports: import torch
  from torch.nn import Parameter
  import numpy
  from speechbrain.nnet.complex_networks.c_ops import multi_mean
label_desc: Use image node_id 4 for calling the CBatchNorm obj's underlying member method code with example usage: obj.forward(input) and returns: c_norm, c_norm