def back_prob(self, E: np.ndarray) -> tuple:
    if (self.dropout_rate > 0):
        E *= self.dropout_mask
    (n_in, c_in, h_in, w_in) = self.a_in.shape
    (n_f, c_f, h_f, w_f) = self.W.shape
    if (self.activation is None):
        E *= self.a_out
    else:
        E *= self.activation.gradient(self.a_out)
    delta_reshaped = E.transpose((1, 2, 3, 0)).reshape(n_f, (- 1))
    dX_cols = self.W.reshape(n_f, (- 1)).T.dot(delta_reshaped)
    dX = col2im_cython(dX_cols, n_in, c_in, h_in, w_in, h_f, w_f, self.padding, self.stride)
    dW = delta_reshaped.dot(self.x_cols.T).reshape(self.W.shape)
    db = np.sum(E, axis=(0, 2, 3))
    return (dX, dW, db)
def back_prob(self, E: np.ndarray) -> tuple:
    if (self.dropout_rate > 0):
        E *= self.dropout_mask
    (n_in, c_in, h_in, w_in) = self.a_in.shape
    (n_f, c_f, h_f, w_f) = self.W.shape
    if (self.activation is None):
        E *= self.a_out
    else:
        E *= self.activation.gradient(self.a_out)
    delta_reshaped = E.transpose((1, 2, 3, 0)).reshape(n_f, (- 1))
    dX_cols = self.W.reshape(n_f, (- 1)).T.dot(delta_reshaped)
    dX = col2im_cython(dX_cols, n_in, c_in, h_in, w_in, h_f, w_f, self.padding, self.stride)
    dW = delta_reshaped.dot(self.x_cols.T).reshape(self.W.shape)
    db = np.sum(E, axis=(0, 2, 3))
    return (dX, dW, db)