def backward(self, grad_act, input_act): """ Backward propagation. This class is mostly wraps around _backward and does some extra asserts. Child classes should overwrite _backward rather than this method. Parameters ---------- grad_act : nump array, gradient of cost function with respect to the activations from this layer (usually calculated in the layer above and passed down during backward propagation), shape is self.output_shape or (NUMBER_OF_EXAMPLES,) + self.output_shape input_act : numpy array, activations from the layer below; shape must either be the same as self.input_shape, or (NUMBER_OF_EXAMPLES,) + self.input_shape Returns ------- grad_input_act : numpy array, gradient of cost function with respect to the input activations this layer received, which is to be passed down to the layer below; shape will be self.input_shape or (NUMBER_OF_EXAMPLES,) + self.input_shape, depending on the input grad_params : 1D numpy array of length self.num_params() (or None if self.num_params()==0), gradient of cost function with respect to the params of this layer """ input_ndim = len(self.input_shape) output_ndim = len(self.output_shape) assert grad_act.shape[-output_ndim:] == tuple( self.output_shape), 'wrong grad input shape' assert input_act.shape[-input_ndim:] == tuple( self.input_shape), 'wrong input shape' assert ((grad_act.ndim == output_ndim and input_act.ndim == input_ndim) or grad_act.shape[0] == input_act.shape[0]), 'wrong number of samples' many = (input_act.ndim > input_ndim) input_act = atleast(input_act, input_ndim + 1) grad_act = atleast(grad_act, output_ndim + 1) grad_input_act, grad_params = self._backward(grad_act, input_act) assert grad_input_act.shape[1:] == tuple(self.input_shape), \ 'wrong input act grad shape' if self.num_params() > 0: grad_params = grad_params.ravel() assert grad_params.size == self.num_params( ), 'wrong param grad shape' return (grad_input_act if many else grad_input_act[0, ...], grad_params)
def forward(self, input_act): """ Forward propagation. This class is mostly wraps around _forward and does some extra asserts. Child classes should overwrite _forward rather than this method. Parameters ---------- input_act : numpy array, activations from the layer below; shape must either be the same as self.input_shape, or (NUMBER_OF_EXAMPLES,) + self.input_shape Returns ------- output_act : numpy array, output activations from this layer; shape will be self.output_shape or (NUMBER_OF_EXAMPLES,) + self.output_shape, depending on the input """ input_ndim = len(self.input_shape) assert input_act.shape[-input_ndim:] == tuple( self.input_shape), 'wrong input shape' many = (input_act.ndim > input_ndim) input_act = atleast(input_act, input_ndim + 1) act = self._forward(input_act) assert act.shape[1:] == tuple(self.output_shape), 'wrong output shape' return act if many else act[0, ...]
def forward(self, input_act): """ Forward propagation. This class is mostly wraps around _forward and does some extra asserts. Child classes should overwrite _forward rather than this method. Parameters ---------- input_act : numpy array, activations from the layer below; shape must either be the same as self.input_shape, or (NUMBER_OF_EXAMPLES,) + self.input_shape Returns ------- output_act : numpy array, output activations from this layer; shape will be self.output_shape or (NUMBER_OF_EXAMPLES,) + self.output_shape, depending on the input """ input_ndim = len(self.input_shape) assert input_act.shape[-input_ndim:] == tuple(self.input_shape), "wrong input shape" many = input_act.ndim > input_ndim input_act = atleast(input_act, input_ndim + 1) act = self._forward(input_act) assert act.shape[1:] == tuple(self.output_shape), "wrong output shape" return act if many else act[0, ...]
def backward(self, grad_act, input_act): """ Backward propagation. This class is mostly wraps around _backward and does some extra asserts. Child classes should overwrite _backward rather than this method. Parameters ---------- grad_act : nump array, gradient of cost function with respect to the activations from this layer (usually calculated in the layer above and passed down during backward propagation), shape is self.output_shape or (NUMBER_OF_EXAMPLES,) + self.output_shape input_act : numpy array, activations from the layer below; shape must either be the same as self.input_shape, or (NUMBER_OF_EXAMPLES,) + self.input_shape Returns ------- grad_input_act : numpy array, gradient of cost function with respect to the input activations this layer received, which is to be passed down to the layer below; shape will be self.input_shape or (NUMBER_OF_EXAMPLES,) + self.input_shape, depending on the input grad_params : 1D numpy array of length self.num_params() (or None if self.num_params()==0), gradient of cost function with respect to the params of this layer """ input_ndim = len(self.input_shape) output_ndim = len(self.output_shape) assert grad_act.shape[-output_ndim:] == tuple(self.output_shape), "wrong grad input shape" assert input_act.shape[-input_ndim:] == tuple(self.input_shape), "wrong input shape" assert (grad_act.ndim == output_ndim and input_act.ndim == input_ndim) or grad_act.shape[0] == input_act.shape[ 0 ], "wrong number of samples" many = input_act.ndim > input_ndim input_act = atleast(input_act, input_ndim + 1) grad_act = atleast(grad_act, output_ndim + 1) grad_input_act, grad_params = self._backward(grad_act, input_act) assert grad_input_act.shape[1:] == tuple(self.input_shape), "wrong input act grad shape" if self.num_params() > 0: grad_params = grad_params.ravel() assert grad_params.size == self.num_params(), "wrong param grad shape" return (grad_input_act if many else grad_input_act[0, ...], grad_params)