def bprop(self, error, alpha=1.0, beta=1.0):
        self.dW[:] = 0

        if self.in_deltas_f is None:
            self.in_deltas_f = get_steps(error[:self.nout], self.o_shape)
            self.prev_in_deltas = self.in_deltas_f[-1:] + self.in_deltas_f[:-1]

        if self.in_deltas_b is None:
            self.in_deltas_b = get_steps(error[self.nout:], self.o_shape)
            self.next_in_deltas = self.in_deltas_b[1:] + self.in_deltas_b[:1]

        params_f = (self.xs_f, self.h_f, self.h_prev_bprop, self.in_deltas_f,
                    self.prev_in_deltas, self.out_delta_f)

        params_b = (self.xs_b, self.h_b, self.h_next_bprop, self.in_deltas_b,
                    self.next_in_deltas, self.out_delta_b)

        self.out_deltas_buffer[:] = 0
        # errors propagate from right to left
        for (xs, hs, h_prev, in_deltas,
             prev_in_deltas, out_delta) in reversed(zip(*params_f)):

            in_deltas[:] = self.activation.bprop(hs) * in_deltas
            self.be.compound_dot(
                self.W_recur_f.T, in_deltas, prev_in_deltas, beta=1.0)
            if h_prev is not None:
                self.be.compound_dot(
                    in_deltas, h_prev.T, self.dW_recur_f, beta=1.0)
            self.be.compound_dot(in_deltas, xs.T, self.dW_input_f, beta=1.0)
            self.db_f[:] = self.db_f + self.be.sum(in_deltas, axis=1)
            if out_delta:
                self.be.compound_dot(self.W_input_f.T, in_deltas, out_delta,
                                     alpha=alpha, beta=beta)

        # errors propagate left to right
        for (xs, hs, h_next, in_deltas,
             next_in_deltas, out_delta) in zip(*params_b):

            in_deltas[:] = self.activation.bprop(hs) * in_deltas
            self.be.compound_dot(
                self.W_recur_b.T, in_deltas, next_in_deltas, beta=1.0)
            if h_next is not None:
                self.be.compound_dot(
                    in_deltas, h_next.T, self.dW_recur_b, beta=1.0)
            self.be.compound_dot(in_deltas, xs.T, self.dW_input_b, beta=1.0)
            self.db_b[:] = self.db_b + self.be.sum(in_deltas, axis=1)
            if out_delta:
                # propagate the errors to same input if split_inputs is False
                self.be.compound_dot(self.W_input_b.T, in_deltas, out_delta,
                                     alpha=alpha, beta=beta if self.split_inputs else 1.0)

        return self.out_deltas_buffer
Backward propagation of errors through bi-directional recurrent layer.
dataset/ETHPy150Open NervanaSystems/neon/neon/layers/recurrent.py/BiRNN.bprop