Skip to content

Instantly share code, notes, and snippets.

@miloharper
Last active May 30, 2022 23:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save miloharper/46ed114b9118888233f7 to your computer and use it in GitHub Desktop.
Save miloharper/46ed114b9118888233f7 to your computer and use it in GitHub Desktop.
A two layer neural network written in Python, which trains itself to solve a variation of the XOR problem.
from numpy import exp, array, random, dot
class NeuronLayer():
def __init__(self, number_of_neurons, number_of_inputs_per_neuron):
self.synaptic_weights = 2 * random.random((number_of_inputs_per_neuron, number_of_neurons)) - 1
class NeuralNetwork():
def __init__(self, layer1, layer2):
self.layer1 = layer1
self.layer2 = layer2
# The Sigmoid function, which describes an S shaped curve.
# We pass the weighted sum of the inputs through this function to
# normalise them between 0 and 1.
def __sigmoid(self, x):
return 1 / (1 + exp(-x))
# The derivative of the Sigmoid function.
# This is the gradient of the Sigmoid curve.
# It indicates how confident we are about the existing weight.
def __sigmoid_derivative(self, x):
return x * (1 - x)
# We train the neural network through a process of trial and error.
# Adjusting the synaptic weights each time.
def train(self, training_set_inputs, training_set_outputs, number_of_training_iterations):
for iteration in xrange(number_of_training_iterations):
# Pass the training set through our neural network
output_from_layer_1, output_from_layer_2 = self.think(training_set_inputs)
# Calculate the error for layer 2 (The difference between the desired output
# and the predicted output).
layer2_error = training_set_outputs - output_from_layer_2
layer2_delta = layer2_error * self.__sigmoid_derivative(output_from_layer_2)
# Calculate the error for layer 1 (By looking at the weights in layer 1,
# we can determine by how much layer 1 contributed to the error in layer 2).
layer1_error = layer2_delta.dot(self.layer2.synaptic_weights.T)
layer1_delta = layer1_error * self.__sigmoid_derivative(output_from_layer_1)
# Calculate how much to adjust the weights by
layer1_adjustment = training_set_inputs.T.dot(layer1_delta)
layer2_adjustment = output_from_layer_1.T.dot(layer2_delta)
# Adjust the weights.
self.layer1.synaptic_weights += layer1_adjustment
self.layer2.synaptic_weights += layer2_adjustment
# The neural network thinks.
def think(self, inputs):
output_from_layer1 = self.__sigmoid(dot(inputs, self.layer1.synaptic_weights))
output_from_layer2 = self.__sigmoid(dot(output_from_layer1, self.layer2.synaptic_weights))
return output_from_layer1, output_from_layer2
# The neural network prints its weights
def print_weights(self):
print " Layer 1 (4 neurons, each with 3 inputs): "
print self.layer1.synaptic_weights
print " Layer 2 (1 neuron, with 4 inputs):"
print self.layer2.synaptic_weights
if __name__ == "__main__":
#Seed the random number generator
random.seed(1)
# Create layer 1 (4 neurons, each with 3 inputs)
layer1 = NeuronLayer(4, 3)
# Create layer 2 (a single neuron with 4 inputs)
layer2 = NeuronLayer(1, 4)
# Combine the layers to create a neural network
neural_network = NeuralNetwork(layer1, layer2)
print "Stage 1) Random starting synaptic weights: "
neural_network.print_weights()
# The training set. We have 7 examples, each consisting of 3 input values
# and 1 output value.
training_set_inputs = array([[0, 0, 1], [0, 1, 1], [1, 0, 1], [0, 1, 0], [1, 0, 0], [1, 1, 1], [0, 0, 0]])
training_set_outputs = array([[0, 1, 1, 1, 1, 0, 0]]).T
# Train the neural network using the training set.
# Do it 60,000 times and make small adjustments each time.
neural_network.train(training_set_inputs, training_set_outputs, 60000)
print "Stage 2) New synaptic weights after training: "
neural_network.print_weights()
# Test the neural network with a new situation.
print "Stage 3) Considering a new situation [1, 1, 0] -> ?: "
hidden_state, output = neural_network.think(array([1, 1, 0]))
print output
@robodhruv
Copy link

Hey!
I was referring to your blog on Medium and it was very helpful indeed.

But looks like you committed a small error in declaration of the sigmoid derivative function:

def __sigmoid_derivative(self, x):
    y = self.__sigmoid(x)
    return y * (1 - y)

I am sure that was overlooked.
Performance improvement: over 5-fold!

@AzureIP
Copy link

AzureIP commented Apr 27, 2018

__sigmoid_derivative(output_from_layer_2)

Well it might also be correct because the output went already through the sigmoid function.

@utzyvi
Copy link

utzyvi commented Jan 27, 2019

Hey!
I was referring to your blog on Medium and it was very helpful indeed.

But looks like you committed a small error in declaration of the sigmoid derivative function:

def __sigmoid_derivative(self, x):
    y = self.__sigmoid(x)
    return y * (1 - y)

I am sure that was overlooked.
Performance improvement: over 5-fold!

Thanks for that! I am making a two million neuron 7-layer neural network and I was having trouble with “overflow experienced in exp”.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment