code: def local_abstract_batch_norm_train(node):
      if not isinstance(node.op, AbstractBatchNormTrain):
          return None
  
      x, scale, bias, epsilon, running_average_factor = node.inputs[:5]
      axes = node.op.axes
      if min(axes) < 0 or max(axes) > x.ndim:
          return None
      if (
          not isinstance(x.type, TensorType)
          or not isinstance(scale.type, TensorType)
          or not isinstance(bias.type, TensorType)
          or not isinstance(epsilon.type, TensorType)
          or not isinstance(running_average_factor.type, TensorType)
      ):
          return None
      # optional running_mean and running_var
      if len(node.inputs) > 5 and not isinstance(
          node.inputs[5].type, TensorType
      ):
          return None
      if len(node.inputs) > 6 and not isinstance(
          node.inputs[6].type, TensorType
      ):
          return None
  
      mean = x.mean(axes, keepdims=True)
      var = x.var(axes, keepdims=True)
      # The epsilon should not upcast the dtype.
      if var.dtype == "float32" and epsilon.dtype == "float64":
          epsilon = epsilon.astype("float32")
      invstd = T.inv(T.sqrt(var + epsilon))
      out = (x - mean) * (scale * invstd) + bias
      results = [out, mean, invstd]
  
      if len(node.inputs) > 5:
          running_mean = node.inputs[5]
          running_mean = (
              running_mean * (1.0 - running_average_factor)
              + mean * running_average_factor
          )
          results.append(running_mean)
      if len(node.inputs) > 6:
          m = T.cast(
              T.prod(x.shape) / T.prod(scale.shape),
              theano.config.floatX,
          )
          running_var = node.inputs[6]
          running_var = (
              running_var * (1.0 - running_average_factor)
              + (m / (m - 1)) * var * running_average_factor
          )
          results.append(running_var)
  
      results = [
          T.patternbroadcast(r, r_orig.broadcastable)
          for (r, r_orig) in zip(results, node.outputs)
      ]
  
      for var in theano.gof.graph.variables(node.inputs, results):
          if var not in node.inputs:
              copy_stack_trace(node.outputs[0], var)
      return results
  
imports: from __future__ import absolute_import, print_function, division
  import numpy
  import theano
  from theano import Apply, Op
  from theano.gof import local_optimizer
  from theano.gof.opt import copy_stack_trace
  from theano.tensor import as_tensor_variable, TensorType
  from theano.tensor import basic
  from theano.tensor.opt import register_specialize_device
  from theano.scalar import Composite, as_common_dtype
  from theano.scalar import add, sub, true_div, mul
label_desc: Use image node_id 5 for calling a global function with example usage: local_abstract_batch_norm_train(node) and returns: results, None, None, None, None, None