Setting up the code, feed forward part

# Note that we use the  numpy wrapper for Autograd (see the gradient descent  slides)
import autograd.numpy as np
from autograd import grad, elementwise_grad
import autograd.numpy.random as npr
from matplotlib import pyplot as plt

def sigmoid(z):
    return 1/(1 + np.exp(-z))

def neural_network(params, x):
    
    # Find the weights (including and biases) for the hidden and output layer.
    # Assume that params is a list of parameters for each layer. 
    # The biases are the first element for each array in params, 
    # and the weights are the remaning elements in each array in params.   
    
    w_hidden = params[0]
    w_output = params[1]

    # Assumes input x being an one-dimensional array
    num_values = np.size(x)
    x = x.reshape(-1, num_values)
    
    # Assume that the input layer does nothing to the input x
    x_input = x

    ## Hidden layer:
    
    # Add a row of ones to include bias
    x_input = np.concatenate((np.ones((1,num_values)), x_input ), axis = 0)
    
    z_hidden = np.matmul(w_hidden, x_input)
    x_hidden = sigmoid(z_hidden)

    ## Output layer:
    
    # Include bias:
    x_hidden = np.concatenate((np.ones((1,num_values)), x_hidden ), axis = 0)

    z_output = np.matmul(w_output, x_hidden)
    x_output = z_output

    return x_output