code: def compute_nnabla_and_numerical_grad(
      inputs,
      variable_inputs,
      variable_outputs,
      rng=None,
      epsilon=1e-8,
      have_scalar=False,
  ):
      """
      Compute both nnabla grad and numerical grad using given functions
  
      Args:
          inputs: ndarray inputs
          variable_inputs: function input variables
          variable_outputs: function output variables
          rng: random number generator
          epsilon: small value to calculate numerical grad
      Returns:
  
      """
  
      if rng is None:
          rng = np.random.RandomState(np.random.randint(1000))
  
      for i in variable_inputs:
          i.g = _randn(rng, *i.shape)
  
      def func(vector):
          bind = 0
          backups = []
  
          for vi, i in zip(variable_inputs, inputs):
              if not have_scalar:
                  vi.d[...] = np.reshape(
                      vector[bind : bind + vi.size], vi.shape
                  )
                  bind += vi.size
              else:
                  if not isinstance(i, np.ndarray):
                      vi.d[...] = np.reshape(
                          vector[bind : bind + 1], vi.shape
                      )
                      bind += 1
                  else:
                      vi.d[...] = np.reshape(
                          vector[bind : bind + vi.size], vi.shape
                      )
                      bind += vi.size
  
              backups.append(vi.d.copy())
  
          variable_outputs.forward()
          for index, vi in enumerate(variable_inputs):
              vi.d[...] = backups[index]
  
          return np.sum(1.0 * variable_outputs.d)
  
      def _nbla_grad(vector):
          bind = 0
          backups = []
  
          for vi, i in zip(variable_inputs, inputs):
              if not have_scalar:
                  vi.d[...] = np.reshape(
                      vector[bind : bind + vi.size], vi.shape
                  )
                  bind += vi.size
              else:
                  if not isinstance(i, np.ndarray):
                      vi.d[...] = np.reshape(
                          vector[bind : bind + 1], vi.shape
                      )
                      bind += 1
                  else:
                      vi.d[...] = np.reshape(
                          vector[bind : bind + vi.size], vi.shape
                      )
                      bind += vi.size
  
              backups.append(vi.g.copy())
  
          variable_outputs.forward()
          variable_outputs.backward()
  
          bind = 0
          g = np.zeros_like(vector)
          index = 0
          for vi, i in zip(variable_inputs, inputs):
              g[bind : bind + vi.size] = (
                  vi.g.flatten() - backups[index].flatten()
              )
              vi.g[...] = backups[index]
              bind += vi.size
              index += 1
  
          return g
  
      vector = []
      if have_scalar:
          for i in inputs:
              if not isinstance(i, np.ndarray):
                  vector += [i]
              else:
                  vector += i.flatten().tolist()
      else:
          for i in inputs:
              vector += i.flatten().tolist()
  
      nbla_grad = _nbla_grad(vector)
      numerical_grad = optimize.approx_fprime(vector, func, epsilon)
  
      return nbla_grad, numerical_grad
  
file_path: nnabla/python/test/nbla_test_function_network.py
imports: import nnabla
  import numpy
  from scipy import optimize
  from nnabla.testing import assert_allclose
label_desc: Use image node_id 3 for calling a global function with example usage: compute_nnabla_and_numerical_grad(inputs, variable_inputs, variable_outputs, rng, epsilon, have_scalar) and returns: nbla_grad,  numerical_grad, np, g