(self, error, alpha=1.0, beta=0.0)
return self.out_deltas_buffer
Backpropagation of errors, output delta for previous layer, and
        calculate the update on model params

        Arguments:
            error (list[Tensor]): error tensors for each time step
                                  of unrolling
            alpha (float, optional): scale to apply to input for activation
                                     gradient bprop.  Defaults to 1.0
            beta (float, optional): scale to apply to output activation
                                    gradient bprop.  Defaults to 0.0

        Returns:
            Tensor: Backpropagated errors for each time step of model unrolling
Backpropagation of errors, output delta for previous layer, and
        calculate the update on model params
Backpropagation of errors output delta for previous layer and calculate the update on model params
def bprop(self, error, alpha=1.0, beta=0.0):
        """
        Backpropagation of errors, output delta for previous layer, and
        calculate the update on model params

        Arguments:
            error (list[Tensor]): error tensors for each time step
                                  of unrolling
            alpha (float, optional): scale to apply to input for activation
                                     gradient bprop.  Defaults to 1.0
            beta (float, optional): scale to apply to output activation
                                    gradient bprop.  Defaults to 0.0

        Returns:
            Tensor: Backpropagated errors for each time step of model unrolling
        """
        self.dW[:] = 0

        if self.in_deltas_f is None:
            self.in_deltas_f = get_steps(error[:self.o_shape[0]], self.o_shape)
            self.prev_in_deltas = self.in_deltas_f[-1:] + self.in_deltas_f[:-1]
            self.ifog_delta_last_steps = self.ifog_delta_buffer[:, self.be.bsz:]
            self.h_first_steps = self.h_buffer_f[:, :-self.be.bsz]
            # h_delta[5] * h[4] + h_delta[4] * h[3] + ... + h_delta[1] * h[0]

        if self.in_deltas_b is None:
            self.in_deltas_b = get_steps(error[self.o_shape[0]:], self.o_shape)
            self.next_in_deltas = self.in_deltas_b[1:] + self.in_deltas_b[:1]
            self.ifog_delta_first_steps = self.ifog_delta_buffer[:,
                                                                 :-self.be.bsz]
            self.h_last_steps = self.h_buffer_b[:, self.be.bsz:]
            # h_delta[0] * h[1] + h_delta[1] * h[2] + ... + h_delta[4] * h[5]

        params_f = (self.in_deltas_f, self.prev_in_deltas,
                    self.i_f, self.f_f, self.o_f, self.g_f,
                    self.ifog_delta, self.i_delta, self.f_delta, self.o_delta, self.g_delta,
                    self.c_delta, self.c_delta_prev, self.c_prev_bprop, self.c_act_f)

        params_b = (self.in_deltas_b, self.next_in_deltas,
                    self.i_b, self.f_b, self.o_b, self.g_b,
                    self.ifog_delta, self.i_delta, self.f_delta, self.o_delta, self.g_delta,
                    self.c_delta, self.c_delta_next, self.c_next_bprop, self.c_act_b)

        # bprop for forward direction connections . Error flow from right to left
        self.c_delta_buffer[:] = 0
        self.ifog_delta_buffer[:] = 0
        self.ifog_delta_f = None
        self.ifog_delta_b = None
        for (in_deltas, prev_in_deltas,
             i, f, o, g,
             ifog_delta, i_delta, f_delta, o_delta, g_delta,
             c_delta, c_delta_prev, c_prev, c_act) in reversed(list(zip(*params_f))):

            # current cell delta
            c_delta[:] = c_delta + \
                self.activation.bprop(c_act) * (o * in_deltas)
            i_delta[:] = self.gate_activation.bprop(i) * c_delta * g
            f_delta[:] = self.gate_activation.bprop(f) * c_delta * c_prev
            o_delta[:] = self.gate_activation.bprop(o) * in_deltas * c_act
            g_delta[:] = self.activation.bprop(g) * c_delta * i

            # bprop the errors to prev_in_delta and c_delta_prev
            self.be.compound_dot(
                self.W_recur_f.T, ifog_delta, prev_in_deltas, beta=1.0)
            if c_delta_prev is not None:
                c_delta_prev[:] = c_delta * f

        # Weight deltas and accumulate
        self.be.compound_dot(
            self.ifog_delta_last_steps, self.h_first_steps.T, self.dW_recur_f)
        self.be.compound_dot(
            self.ifog_delta_buffer, self.x_f.T, self.dW_input_f)
        self.db_f[:] = self.be.sum(self.ifog_delta_buffer, axis=1)
        # out deltas to input units
        if self.out_deltas_buffer:
            self.be.compound_dot(
                self.W_input_f.T, self.ifog_delta_buffer,
                self.out_deltas_buffer_f_v,
                alpha=alpha, beta=beta)

        # bprop for backward direction connections. Error flow from left to right
        self.c_delta_buffer[:] = 0
        self.ifog_delta_buffer[:] = 0
        for (in_deltas, next_in_deltas,
             i, f, o, g,
             ifog_delta, i_delta, f_delta, o_delta, g_delta,
             c_delta, c_delta_next, c_next, c_act) in zip(*params_b):

            # current cell delta
            c_delta[:] = c_delta[:] + \
                self.activation.bprop(c_act) * (o * in_deltas)
            i_delta[:] = self.gate_activation.bprop(i) * c_delta * g
            f_delta[:] = self.gate_activation.bprop(f) * c_delta * c_next
            o_delta[:] = self.gate_activation.bprop(o) * in_deltas * c_act
            g_delta[:] = self.activation.bprop(g) * c_delta * i

            # bprop the errors to next_in_delta and c_next_delta
            self.be.compound_dot(
                self.W_recur_b.T, ifog_delta, next_in_deltas, beta=1.0)
            if c_delta_next is not None:
                c_delta_next[:] = c_delta * f

        # Weight deltas and accumulate
        self.be.compound_dot(
            self.ifog_delta_first_steps, self.h_last_steps.T, self.dW_recur_b)
        self.be.compound_dot(
            self.ifog_delta_buffer, self.x_b.T, self.dW_input_b)
        self.db_b[:] = self.be.sum(self.ifog_delta_buffer, axis=1)
        # out deltas to input units. bprop to the same inputs if
        # split_inputs=False
        if self.out_deltas_buffer:
            self.be.compound_dot(self.W_input_b.T, self.ifog_delta_buffer,
                                 self.out_deltas_buffer_b_v,
                                 alpha=alpha,
                                 beta=beta if self.inputs else 1.0)

        return self.out_deltas_buffer
def bprop ( self , error , alpha = 1.0 , beta = 0.0 ) : self . dW [ : ] = 0 if self . in_deltas_f is None : self . in_deltas_f = get_steps ( error [ : self . o_shape [ 0 ] ] , self . o_shape ) self . prev_in_deltas = self . in_deltas_f [ - 1 : ] + self . in_deltas_f [ : - 1 ] self . ifog_delta_last_steps = self . ifog_delta_buffer [ : , self . be . bsz : ] self . h_first_steps = self . h_buffer_f [ : , : - self . be . bsz ] # h_delta[5] * h[4] + h_delta[4] * h[3] + ... + h_delta[1] * h[0] if self . in_deltas_b is None : self . in_deltas_b = get_steps ( error [ self . o_shape [ 0 ] : ] , self . o_shape ) self . next_in_deltas = self . in_deltas_b [ 1 : ] + self . in_deltas_b [ : 1 ] self . ifog_delta_first_steps = self . ifog_delta_buffer [ : , : - self . be . bsz ] self . h_last_steps = self . h_buffer_b [ : , self . be . bsz : ] # h_delta[0] * h[1] + h_delta[1] * h[2] + ... + h_delta[4] * h[5] params_f = ( self . in_deltas_f , self . prev_in_deltas , self . i_f , self . f_f , self . o_f , self . g_f , self . ifog_delta , self . i_delta , self . f_delta , self . o_delta , self . g_delta , self . c_delta , self . c_delta_prev , self . c_prev_bprop , self . c_act_f ) params_b = ( self . in_deltas_b , self . next_in_deltas , self . i_b , self . f_b , self . o_b , self . g_b , self . ifog_delta , self . i_delta , self . f_delta , self . o_delta , self . g_delta , self . c_delta , self . c_delta_next , self . c_next_bprop , self . c_act_b ) # bprop for forward direction connections . Error flow from right to left self . c_delta_buffer [ : ] = 0 self . ifog_delta_buffer [ : ] = 0 self . ifog_delta_f = None self . ifog_delta_b = None for ( in_deltas , prev_in_deltas , i , f , o , g , ifog_delta , i_delta , f_delta , o_delta , g_delta , c_delta , c_delta_prev , c_prev , c_act ) in reversed ( list ( zip ( * params_f ) ) ) : # current cell delta c_delta [ : ] = c_delta + self . activation . bprop ( c_act ) * ( o * in_deltas ) i_delta [ : ] = self . gate_activation . bprop ( i ) * c_delta * g f_delta [ : ] = self . gate_activation . bprop ( f ) * c_delta * c_prev o_delta [ : ] = self . gate_activation . bprop ( o ) * in_deltas * c_act g_delta [ : ] = self . activation . bprop ( g ) * c_delta * i # bprop the errors to prev_in_delta and c_delta_prev self . be . compound_dot ( self . W_recur_f . T , ifog_delta , prev_in_deltas , beta = 1.0 ) if c_delta_prev is not None : c_delta_prev [ : ] = c_delta * f # Weight deltas and accumulate self . be . compound_dot ( self . ifog_delta_last_steps , self . h_first_steps . T , self . dW_recur_f ) self . be . compound_dot ( self . ifog_delta_buffer , self . x_f . T , self . dW_input_f ) self . db_f [ : ] = self . be . sum ( self . ifog_delta_buffer , axis = 1 ) # out deltas to input units if self . out_deltas_buffer : self . be . compound_dot ( self . W_input_f . T , self . ifog_delta_buffer , self . out_deltas_buffer_f_v , alpha = alpha , beta = beta ) # bprop for backward direction connections. Error flow from left to right self . c_delta_buffer [ : ] = 0 self . ifog_delta_buffer [ : ] = 0 for ( in_deltas , next_in_deltas , i , f , o , g , ifog_delta , i_delta , f_delta , o_delta , g_delta , c_delta , c_delta_next , c_next , c_act ) in zip ( * params_b ) : # current cell delta c_delta [ : ] = c_delta [ : ] + self . activation . bprop ( c_act ) * ( o * in_deltas ) i_delta [ : ] = self . gate_activation . bprop ( i ) * c_delta * g f_delta [ : ] = self . gate_activation . bprop ( f ) * c_delta * c_next o_delta [ : ] = self . gate_activation . bprop ( o ) * in_deltas * c_act g_delta [ : ] = self . activation . bprop ( g ) * c_delta * i # bprop the errors to next_in_delta and c_next_delta self . be . compound_dot ( self . W_recur_b . T , ifog_delta , next_in_deltas , beta = 1.0 ) if c_delta_next is not None : c_delta_next [ : ] = c_delta * f # Weight deltas and accumulate self . be . compound_dot ( self . ifog_delta_first_steps , self . h_last_steps . T , self . dW_recur_b ) self . be . compound_dot ( self . ifog_delta_buffer , self . x_b . T , self . dW_input_b ) self . db_b [ : ] = self . be . sum ( self . ifog_delta_buffer , axis = 1 ) # out deltas to input units. bprop to the same inputs if # split_inputs=False if self . out_deltas_buffer : self . be . compound_dot ( self . W_input_b . T , self . ifog_delta_buffer , self . out_deltas_buffer_b_v , alpha = alpha , beta = beta if self . inputs else 1.0 ) return self . out_deltas_buffer