

def backward(self, inputs, grad_outputs):
    e1 = array.as_mat(inputs[0])
    e2 = array.as_mat(inputs[1])
    W = inputs[2]
    gy = grad_outputs[0]
    xp = cuda.get_array_module(*inputs)
    if (xp is numpy):
        gW = numpy.einsum('ij,ik,il->jkl', e1, e2, gy)
        ge1 = numpy.einsum('ik,jkl,il->ij', e2, W, gy)
        ge2 = numpy.einsum('ij,jkl,il->ik', e1, W, gy)
    else:
        kern = cuda.reduce('T in0, T in1, T in2', 'T out', 'in0 * in1 * in2', 'a + b', 'out = a', 0, 'bilinear_product')
        e1_b = e1[:, :, None, None]
        e2_b = e2[:, None, :, None]
        gy_b = gy[:, None, None, :]
        W_b = W[None, :, :, :]
        gW = kern(e1_b, e2_b, gy_b, axis=0)
        ge1 = kern(e2_b, W_b, ge1, axis=(2, 3))
        ge2 = kern(e1_b, W_b, gy_b, axis=(1, 3))
    ret = (ge1.reshape(inputs[0].shape), ge2.reshape(inputs[1].shape), gW)
    if (len(inputs) == 6):
        (V1, V2, b) = inputs[3:]
        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

dataset/ETHPy150Open pfnet/chainer/chainer/functions/connection/bilinear.py BilinearFunction.backward/VarMisuse@217/332 `gy_b`->`ge1`