code: def backward(dHout_in, cache, dcn=None, dhn=None):
      WLSTM = cache["WLSTM"]
      Hout = cache["Hout"]
      IFOGf = cache["IFOGf"]
      IFOG = cache["IFOG"]
      C = cache["C"]
      Ct = cache["Ct"]
      Hin = cache["Hin"]
      c0 = cache["c0"]
      # h0 = cache['h0']
      n, b, d = Hout.shape
      input_size = WLSTM.shape[0] - d - 1  # -1 due to bias
  
      # backprop the LSTM
      dIFOG = np.zeros(IFOG.shape)
      dIFOGf = np.zeros(IFOGf.shape)
      dWLSTM = np.zeros(WLSTM.shape)
      dHin = np.zeros(Hin.shape)
      dC = np.zeros(C.shape)
      dX = np.zeros((n, b, input_size))
      dh0 = np.zeros((b, d))
      dc0 = np.zeros((b, d))
      dHout = (
          dHout_in.copy()
      )  # make a copy so we don't have any funny side effects
      if dcn is not None:
          dC[n - 1] += dcn.copy()  # carry over gradients from later
      if dhn is not None:
          dHout[n - 1] += dhn.copy()
  
      for t in reversed(range(n)):
          tanhCt = Ct[t]
          dIFOGf[t, :, 2 * d : 3 * d] = tanhCt * dHout[t]
          # backprop tanh non-linearity first then continue backprop
          dC[t] += (1 - tanhCt**2) * (
              IFOGf[t, :, 2 * d : 3 * d] * dHout[t]
          )
  
          if t > 0:
              dIFOGf[t, :, d : 2 * d] = C[t - 1] * dC[t]
              dC[t - 1] += IFOGf[t, :, d : 2 * d] * dC[t]
          else:
              dIFOGf[t, :, d : 2 * d] = c0 * dC[t]
              dc0 = IFOGf[t, :, d : 2 * d] * dC[t]
          dIFOGf[t, :, :d] = IFOGf[t, :, 3 * d :] * dC[t]
          dIFOGf[t, :, 3 * d :] = IFOGf[t, :, :d] * dC[t]
  
          # backprop activation functions
          dIFOG[t, :, 3 * d :] = (
              1 - IFOGf[t, :, 3 * d :] ** 2
          ) * dIFOGf[t, :, 3 * d :]
          y = IFOGf[t, :, : 3 * d]
          dIFOG[t, :, : 3 * d] = (y * (1.0 - y)) * dIFOGf[t, :, : 3 * d]
  
          # backprop matrix multiply
          dWLSTM += np.dot(Hin[t].transpose(), dIFOG[t])
          dHin[t] = dIFOG[t].dot(WLSTM.transpose())
  
          # backprop the identity transforms into Hin
          dX[t] = dHin[t, :, 1 : input_size + 1]
          if t > 0:
              dHout[t - 1, :] += dHin[t, :, input_size + 1 :]
          else:
              dh0 += dHin[t, :, input_size + 1 :]
  
          # for debugging
  
          # hidden_size = WLSTM.shape[0] - input_size - 1
          # dWrecur = dWLSTM[-hidden_size:, :]
          # dWinput = dWLSTM[1:input_size + 1, :]
          # db = dWLSTM[0, :]
      return dX, dWLSTM, dc0, dh0
  
file_path: neon/tests/lstm_ref.py
imports: from builtins import input
  import numpy
  from neon import logger
  from utils import allclose_with_out
label_desc: Use image node_id 3 for calling the LSTM obj's underlying member method code with example usage: obj.backward(dHout_in, cache, dcn, dhn) and returns: dX,  dWLSTM,  dc0,  dh0