code: def _np_bn_training(x, scale, bias, rm, rv, momentum=0.1, e=1e-5):
      channel = x.shape[1]
      np.testing.assert_array_almost_equal(
          scale.shape, (1, channel, 1, 1)
      )
      np.testing.assert_array_almost_equal(
          bias.shape, (1, channel, 1, 1)
      )
      np.testing.assert_array_almost_equal(rm.shape, (1, channel, 1, 1))
      np.testing.assert_array_almost_equal(rv.shape, (1, channel, 1, 1))
  
      batch_m = x.mean(axis=(0, 2, 3), keepdims=True)
      batch_v = x.var(axis=(0, 2, 3), keepdims=True)
  
      x_norm = (x - batch_m) / np.sqrt(batch_v + e)
      y_norm = x_norm * scale + bias
  
      # https://arxiv.org/pdf/1502.03167.pdf
      s = list(x.shape)
      s[1] = 1
      batch_v_unbiased = np.prod(s) * batch_v / (np.prod(s) - 1)
  
      rm = momentum * batch_m + (1 - momentum) * rm
      rv = momentum * batch_v_unbiased + (1 - momentum) * rv
  
      # https://docs.nvidia.com/deeplearning/sdk/cudnn-developer-guide/index.html#cudnnBatchNormalizationForwardTraining
      resultSaveInvVariance = 1 / np.sqrt(batch_v)
      return y_norm, rm, rv, batch_m, resultSaveInvVariance
  
imports: from __future__ import division
  import unittest
  import math
  import numpy
  from singa import singa_wrap
  from singa import tensor
  from cuda_helper import gpu_dev, cpu_dev
label_desc: Use image node_id 1 for calling a global function with example usage: _np_bn_training(x, scale, bias, rm, rv, momentum, e) and returns: y_norm,  rm,  rv,  batch_m,  resultSaveInvVariance