code: def forward(self, inputs):
      self.retain_inputs(tuple(range(len(inputs))))
  
      e1 = _as_mat(inputs[0])
      e2 = _as_mat(inputs[1])
      W, gy = inputs[2], inputs[-1]
  
      xp = backend.get_array_module(*inputs)
      # optimize: gW = xp.einsum('ij,ik,il->jkl', e1, e2, gy)
      gW = xp.einsum("ij,ik->jki", e1, e2).dot(gy)
  
      gy_W = xp.tensordot(gy, W, axes=(1, 2))  # 'il,jkl->ijk'
      # optimize: ge1 = xp.einsum('ik,jkl,il->ij', e2, W, gy)
      ge1 = xp.einsum("ik,ijk->ij", e2, gy_W)
      # optimize: ge2 = xp.einsum('ij,jkl,il->ik', e1, W, gy)
      ge2 = xp.einsum("ij,ijk->ik", e1, gy_W)
  
      ret = (
          ge1.reshape(inputs[0].shape),
          ge2.reshape(inputs[1].shape),
          gW,
      )
  
      if len(inputs) == 6:
          V1, V2 = inputs[3], inputs[4]
          gV1 = e1.T.dot(gy)
          gV2 = e2.T.dot(gy)
          gb = gy.sum(0)
          ge1 += gy.dot(V1.T)
          ge2 += gy.dot(V2.T)
          ret += gV1, gV2, gb
  
      return ret
  
imports: import numpy
  import chainer
  from chainer import backend
  from chainer import function_node
  from chainer.utils import type_check
label_desc: Use image node_id 1 for calling the BilinearFunctionGrad obj's underlying member method code with example usage: obj.forward(inputs) and returns: ret