def grads(self, x, y):

       # Run forward and store activations for each layer 
       activations   = self.forward(x, allOuts=True) 

       # For each layer in reverse store the gradients for each parameter 
       nabla_params = [None]*(2*self.n_layers)

       for n in np.arange(self.n_layers-1, -1, -1):

           # Get weigths and bias (always in even and odd positions)
           # Note that sometimes we need the weight from the next layer  
           W = self.params[2*n]
           b = self.params[2*n+1]
           if n != self.n_layers-1:
               W_next = self.params[2*(n+1)]

           ###########################
           # Solution to Exercise 6.2 
            
           # If it is the last layer, compute the average cost gradient
           # Otherwise, propagate the error backwards from the next layer
           if n == self.n_layers-1:
               # NOTE: This assumes cross entropy cost
               if self.actvfunc[n] == 'sigmoid':
                   e = (activations[n] - y)/y.shape[0]
               elif self.actvfunc[n] == 'softmax':
                   I  = index2onehot(y, W.shape[0])
                   e  = (activations[n] - I)/y.shape[0]      

           else:
               e  = np.dot(W_next.T, e)
               # This is correct but confusing n+1 is n in the guide
               e *= activations[n]*(1-activations[n])

           # Weight gradient 
           nabla_W = np.zeros(W.shape)
           for l in np.arange(e.shape[1]):
              if n == 0:
                  # For the first layer, the activation is the input 
                  nabla_W += np.outer(e[:, l], x[:, l])
              else:    
                  nabla_W += np.outer(e[:, l], activations[n-1][:, l])
           # Bias gradient
           nabla_b = np.sum(e, 1, keepdims=True)

           # End of solution to Exercise 6.2 
           ###########################

           # Store the gradients 
           nabla_params[2*n]   = nabla_W
           nabla_params[2*n+1] = nabla_b

       return nabla_params
Computes the gradients of the network with respect to cross entropy 
dataset/ETHPy150Open LxMLS/lxmls-toolkit/lxmls/deep_learning/mlp.py/NumpyMLP.grads