code: def batch_normalization(
      x,
      beta,
      gamma,
      mean,
      variance,
      axes=[1],
      decay_rate=0.9,
      eps=1e-05,
      batch_stat=True,
      output_stat=False,
      n_outputs=None,
  ):
      r"""
      Batch normalization.
  
      .. math::
          \begin{eqnarray}
            \mu &=& \frac{1}{M} \sum x_i \\
            \sigma^2 &=& \frac{1}{M} \sum \left(x_i - \mu\right)^2 \\
            \hat{x}_i &=& \frac{x_i - \mu}{\sqrt{\sigma^2 + \epsilon}} \\
            y_i &=& \hat{x}_i \gamma + \beta.
          \end{eqnarray}
  
  
      At testing time, the mean and variance values used are those that were computed during training by moving average.
  
      References:
  
          * `Ioffe and Szegedy, Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift.
            <https://arxiv.org/abs/1502.03167>`_
  
      Args:
          x(~nnabla.Variable): N-D array of input.
          beta(~nnabla.Variable or None): N-D array of beta which is learned. If None, the bias term is omitted.
          gamma(~nnabla.Variable or None): N-D array of gamma which is learned. If None, the scale term is omitted.
          mean(~nnabla.Variable or None):
              N-D array of running mean (modified during forward execution).
              If None, dummy variable is created and running mean is not updated.
              mean=None with batch_stat=False is prohibited.
          variance(~nnabla.Variable or None):
              N-D array of running variance (modified during forward execution).
              If None, dummy variable is created and running variance is not updated.
              variance=None with batch_stat=False is prohibited.
          axes(list of int or int): Mean and variance are calculated along these axes.
          decay_rate(float): Decay rate of running mean and variance.
          eps(float): Tiny value to avoid zero division by std.
          batch_stat(bool):
              Use mini-batch statistics rather than running ones.
              If False, mean and variance must be `~nnabla.Variable`. (None is prohibited.)
          output_stat(bool): It true, the batch statistics of mean and variance,
              will be returned as Variables. They are also differentiable.
  
      Returns:
          Returns batch normalization output as :obj:`~nnabla.Variable`.
          If ``output_stat=True``, it also returns the mean and variance
          of the mini-batch
  
          * :obj:`~nnabla.Variable`: Output of the batch normalization
          * :obj:`~nnabla.Variable`: Mean (if `output_stat=True`)
          * :obj:`~nnabla.Variable`: Variance (if `output_stat=True`)
  
      See Also:
          ``nnabla.function_bases.batch_normalization``.
  
      """
      from .function_bases import (
          batch_normalization as batch_normalization_base,
      )
  
      n_outputs = 3 if output_stat else 1
      axes = _force_list(axes)
      axes = [a + len(x.shape) * (a < 0) for a in axes]
  
      assert batch_stat or (not output_stat)
  
      if not batch_stat and (mean is None or variance is None):
          raise ValueError(
              "If batch_stat is False, mean and variable must not be None."
          )
  
      _, _, mean, variance = _create_bn_dummy_vars(
          x, axes, beta, gamma, mean, variance
      )
  
      if batch_stat and (mean.parent or variance.parent) is not None:
          raise ValueError(
              "if batch_stat is True, mean and variable must not have a parent function."
          )
  
      no_scale = gamma is None
      no_bias = beta is None
  
      if len(axes) == 1:
          return batch_normalization_base(
              x,
              beta,
              gamma,
              mean,
              variance,
              axes=axes,
              decay_rate=decay_rate,
              eps=eps,
              batch_stat=batch_stat,
              no_scale=no_scale,
              no_bias=no_bias,
              n_outputs=n_outputs,
          )
  
      in_adapter = BatchNormalizationInOutAdapter(x.ndim, axes)
      param_adapter = BatchNormalizationInOutAdapter(x.ndim, axes)
      inp = in_adapter(x)
      if beta is not None:
          beta = param_adapter(beta)
      if gamma is not None:
          gamma = param_adapter(gamma)
      mean = param_adapter(mean)
      variance = param_adapter(variance)
      axis = x.ndim - len(axes)
  
      if n_outputs == 1:
          out = batch_normalization_base(
              inp,
              beta,
              gamma,
              mean,
              variance,
              axes=[axis],
              decay_rate=decay_rate,
              eps=eps,
              batch_stat=batch_stat,
              no_scale=no_scale,
              no_bias=no_bias,
              n_outputs=n_outputs,
          )
          return in_adapter.inv(out)
      out, mean, variance = batch_normalization_base(
          inp,
          beta,
          gamma,
          mean,
          variance,
          axes=[axis],
          decay_rate=decay_rate,
          eps=eps,
          batch_stat=batch_stat,
          no_scale=no_scale,
          no_bias=no_bias,
          n_outputs=n_outputs,
      )
      out = in_adapter.inv(out)
      mean = param_adapter.inv(mean)
      variance = param_adapter.inv(variance)
      return out, mean, variance
  
imports: from __future__ import absolute_import
  from .function_bases import *
  from six.moves import reduce
  import numpy
  import nnabla
label_desc: Use image node_id 8 for calling a global function with example usage: batch_normalization(x, beta, gamma, mean, variance, axes, decay_rate, eps, batch_stat, output_stat, n_outputs) and returns: out,  mean,  variance, batch_normalization_base, in_adapter