based on article published by James Loy
In [1]:
    
# required imports
import numpy as np
    
In [2]:
    
# definition of neural network with input layer, one hidden layer and an output layer
# neuron activation function is sigmoid function defined as:
def sigmoid(x, derivative=False):
    return x*(1-x) if derivative else 1/(1+np.exp(-x))
class NeuralNetwork:
    
    def __init__(self, x, y):
        self.input = x
        # weights from input layer to hidden layer with 4 neurons
        self.weights1 = np.random.rand(self.input.shape[1], 4)
        # weights from hidden layer to output layer with 1 neuron
        self.weights2 = np.random.rand(4,1)
        self.y = y
        self.output = np.zeros(y.shape)
        
    # feed forward to obtain network output
    def feedforward(self):
        self.layer1 = sigmoid(np.dot(self.input, self.weights1))
        self.output = sigmoid(np.dot(self.layer1, self.weights2))
        
    # backpropagation to update the weights
    def backprop(self):
        # application of chain rule to find derivative of loss function
        d_weights2 = np.dot(self.layer1.T, (2*(self.y - self.output)*sigmoid(self.output, derivative=True)))
        d_weights1 = np.dot(self.input.T, np.dot(2*(self.y - self.output)*sigmoid(self.output, derivative=True), 
                                                 self.weights2.T)*sigmoid(self.layer1, derivative=True))
        
        # updating the weights with slope of the loss function
        self.weights1 += d_weights1
        self.weights2 += d_weights2
    
In [3]:
    
# example of weights from input with 3 neurons to hidden layer with 4 neurons
# first row contains the weights from first input neuron to all the neurons in the hidden layer and so on
np.random.rand(3,4)
    
    Out[3]:
In [4]:
    
# example of weigths from hiddne layer with 4 neurons to one output neuron
np.random.rand(4,1)
    
    Out[4]:
In [5]:
    
# definition of inputs
X = np.array([[0, 0, 1],
            [0, 1, 1],
            [1, 0, 1],
            [1, 1, 1]])
X
    
    Out[5]:
In [6]:
    
# definition of outputs
y = np.array([[0], [1], [1], [0]])
y
    
    Out[6]:
In [7]:
    
# creation of the neural network
net1= NeuralNetwork(X, y)
    
In [8]:
    
net1.feedforward()
    
In [9]:
    
net1.output
    
    Out[9]:
In [10]:
    
net1.backprop()
    
In [11]:
    
net1.output
    
    Out[11]:
In [12]:
    
net1.feedforward()
net1.output
    
    Out[12]:
In [13]:
    
np.sum((net1.output - y)**2)
    
    Out[13]:
In [14]:
    
# training the network with 1500 iterations of feed forward and backpropagation
# loss function L is calculated as sum of squared errors
L = []
for i in range(1500):
    net1.feedforward()
    L.append(np.sum((net1.output - y)**2))
    net1.backprop()
    
# network prediction after training
net1.output
    
    Out[14]:
In [15]:
    
# loss function plot
import matplotlib.pyplot as plt
%matplotlib inline
    
In [16]:
    
plt.style.use('ggplot')
plt.figure(figsize=(12,5))
plt.plot(L)
plt.xlabel('Iteration')
plt.ylabel('Loss function value');
    
    
In [17]:
    
# sigmoid function plot
x = np.linspace(0, 10, 100)
plt.plot(x, sigmoid(x))
plt.xlabel('x')
plt.ylabel('sigmoid(x)');
    
    
In [18]:
    
# sigmoid derivative
plt.plot(x, sigmoid(x, derivative=True))
plt.xlabel('x')
plt.ylabel('sigmoid_derivative(x)');
    
    
In [ ]: