class_docstr: This class implements the simplest form of a quaternion batchnorm as
  described in : "Quaternion Convolutional Neural Network for
  Color Image Classification and Forensics", Qilin Y. et al.
  
  Arguments
  ---------
  input_size : int
      Expected size of the dimension to be normalized.
  dim : int, optional
      It defines the axis that should be normalized. It usually correspond to
      the channel dimension (default -1).
  gamma_init : float, optional
      First value of gamma to be used (mean) (default 1.0).
  beta_param : bool, optional
      When set to True the beta parameter of the BN is applied (default True).
  momentum : float, optional
      It defines the momentum as for the real-valued batch-normalization (default 0.1).
  eps : float, optional
      Term used to stabilize operation (default 1e-4).
  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, 40])
  >>> QBN = QBatchNorm(input_size=40)
  >>> out_tensor = QBN(inp_tensor)
  >>> out_tensor.shape
  torch.Size([10, 40])
class_docstr_tok: ["This","class","implements","the","simplest","form","of","a","quaternion","batchnorm","as","described","in",":","``","Quaternion","Convolutional","Neural","Network","for","Color","Image","Classification","and","Forensics","''",",","Qilin","Y.","et","al",".","Arguments","--","--","--","--","-","input_size",":","int","Expected","size","of","the","dimension","to","be","normalized",".","dim",":","int",",","optional","It","defines","the","axis","that","should","be","normalized",".","It","usually","correspond","to","the","channel","dimension","(","default","-1",")",".","gamma_init",":","float",",","optional","First","value","of","gamma","to","be","used","(","mean",")","(","default","1.0",")",".","beta_param",":","bool",",","optional","When","set","to","True","the","beta","parameter","of","the","BN","is","applied","(","default","True",")",".","momentum",":","float",",","optional","It","defines","the","momentum","as","for","the","real-valued","batch-normalization","(","default","0.1",")",".","eps",":","float",",","optional","Term","used","to","stabilize","operation","(","default","1e-4",")",".","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",",","40","]",")",">",">",">","QBN","=","QBatchNorm","(","input_size=40",")",">",">",">","out_tensor","=","QBN","(","inp_tensor",")",">",">",">","out_tensor.shape","torch.Size","(","[","10",",","40","]",")"]
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
  
      # Entering training mode
      if self.training:
          if self.num_batches_tracked is not None:
              self.num_batches_tracked = 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
  
          # Get mean along batch axis
          mu = torch.mean(input, dim=0)
          mu_r, mu_i, mu_j, mu_k = torch.chunk(mu, 4, dim=self.dim)
  
          # Get variance along batch axis
          delta = input - mu
          delta_r, delta_i, delta_j, delta_k = torch.chunk(
              delta, 4, dim=self.dim
          )
          quat_variance = torch.mean(
              (
                  delta_r**2
                  + delta_i**2
                  + delta_j**2
                  + delta_k**2
              ),
              dim=0,
          )
  
          denominator = torch.sqrt(quat_variance + self.eps)
  
          # x - mu / sqrt(var + e)
          out = input / torch.cat(
              [denominator, denominator, denominator, denominator],
              dim=self.dim,
          )
  
          # Update the running stats
          if self.track_running_stats:
              self.running_mean = (
                  1 - exponential_average_factor
              ) * self.running_mean + exponential_average_factor * mu.view(
                  self.running_mean.size()
              )
  
              self.running_var = (
                  1 - exponential_average_factor
              ) * self.running_var + exponential_average_factor * quat_variance.view(
                  self.running_var.size()
              )
      else:
          q_var = torch.cat(
              [
                  self.running_var,
                  self.running_var,
                  self.running_var,
                  self.running_var,
              ],
              dim=self.dim,
          )
          out = (input - self.running_mean) / q_var
  
      # lambda * (x - mu / sqrt(var + e)) + beta
  
      q_gamma = torch.cat(
          [self.gamma, self.gamma, self.gamma, self.gamma], dim=self.dim
      )
      out = (q_gamma * out) + self.beta
  
      return out
  
imports: import torch
  from torch.nn import Parameter
label_desc: Use image node_id 2 for calling the QBatchNorm obj's underlying member method code with example usage: obj.forward(input) and returns: out