Last active
March 19, 2024 00:47
-
-
Save rjlutz/5fb448c6f6b9d2663a745c833bbf162f to your computer and use it in GitHub Desktop.
Starter code and data files for neural net / python practice assignment
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## modified from: | |
## https://github.com/miloharper/simple-neural-network and | |
## https://medium.com/technology-invention-and-more/how-to-build-a-simple-neural-network-in-9-lines-of-python-code-cc8f23647ca1 | |
## thanks! | |
import csv | |
from numpy import exp, array, random, dot | |
class NeuralNetwork(): | |
def __init__(self): | |
# Seed the random number generator, so it generates the same numbers | |
# every time the program runs. | |
random.seed(1) | |
# 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) | |
def randomize_weights(self, num_inputs, num_outputs): | |
# We model a single neuron, with inputs*outputs input connections and 1 output connection. | |
# We assign random weights to an i*o x 1 matrix, with values in the range -1 to 1 | |
# and mean 0. | |
self.synaptic_weights = 2 * random.random((num_inputs*num_outputs, 1)) - 1 | |
# We train the neural network through a process of trial and error. | |
# Adjusting the synaptic weights each time. if __name__ == "__main__": | |
def train(self, training_set_inputs, training_set_outputs, number_of_training_iterations): | |
for iteration in range(number_of_training_iterations): | |
# Pass the training set through our neural network (a single neuron). | |
output = self.think(training_set_inputs) | |
# Calculate the error (The difference between the desired output | |
# and the predicted output). | |
error = training_set_outputs - output | |
# Multiply the error by the input and again by the gradient of the Sigmoid curve. | |
# This means less confident weights are adjusted more. | |
# This means inputs, which are zero, do not cause changes to the weights. | |
adjustment = dot(training_set_inputs.T, error * self.__sigmoid_derivative(output)) | |
# Adjust the weights. | |
self.synaptic_weights += adjustment | |
# The neural network thinks. | |
def think(self, inputs): | |
# Pass inputs through our neural network (our single neuron). | |
return self.__sigmoid(dot(inputs, self.synaptic_weights)) | |
def read_data(self, input_file): | |
''' | |
:param self: | |
:param input_file: read inputs from data file | |
here is an example data file | |
1, 3 | |
0, 1, 1, 0 | |
0, 0, 1 | |
1, 1, 1 | |
1, 0, 1 | |
0, 1, 1 | |
where the first line contains every image's 2d dimensions, | |
the second line contains the dataset's labels, | |
and the remaining lines contain a 2d map of images | |
:return: a 2d array of unrolled image values and a column vector of labels, such as: | |
images = array([[0, 0, 1], [1, 1, 1], [1, 0, 1], [0, 1, 1]]) | |
labels = array([[0, 1, 1, 0]]).T | |
''' | |
with open(input_file, 'r') as csvfile: | |
reader = csv.reader(csvfile, delimiter=',', quotechar='|') | |
image_height, image_width = (0,0) | |
## TODO | |
## Read in the first line of the file from the reader object | |
## you will need to convert each comma separated value to an int and | |
## place these in a two-item list. assign these list items as: | |
## | |
## image_height, image_width = | |
## | |
labels = () | |
## TODO | |
## Read in the second line of the file from the reader object | |
## you will need to convert each csv element to an int and place | |
## them into a variable length list named 'labels.' | |
## labels = | |
## | |
images = [] | |
for i in range(len(labels)): | |
input = [] | |
pixels = 0; | |
while pixels < image_height * image_width: | |
## TODO | |
## Read in the next line in the file | |
## Assign the results to 'line'. No further processing is necessary | |
## line = | |
## | |
if len(line) == 0 or line[0].startswith("#"): continue | |
for px in map(int, line): | |
input.append(px) | |
pixels += 1; | |
images.append(input) | |
# reset synaptic weights, based on new dims, input equals # of pixels, output = 1 | |
self.randomize_weights(image_width * image_height, 1) | |
return array(images), array([labels]).T | |
if __name__ == "__main__": | |
# Intialise a single neuron neural network. | |
neural_network = NeuralNetwork() | |
training_set_inputs, training_set_outputs = neural_network.read_data('images4x1x3.csv') | |
# Train the neural network using a training set. | |
# Do it 10,000 times and make small adjustments each time. | |
neural_network.train(training_set_inputs, training_set_outputs, 10000) | |
# Test the neural network with a new situation. | |
print("Considering new situation [1, 0, 0] -> ?: (expecting ~0.99993704)") | |
challenge = array([1, 0, 0]) | |
print(neural_network.think(challenge), "expecting value close to 1") | |
print() | |
neural_network = NeuralNetwork() | |
training_set_inputs, training_set_outputs = neural_network.read_data('images4x2x2.csv') | |
neural_network.train(training_set_inputs, training_set_outputs, 10000) | |
print("Considering new situation [1, 0, 0, 0] -> ?: (expecting ~0.99993703)") | |
challenge = array([1, 0, 0, 0]) | |
print(neural_network.think(challenge), "expecting value close to 1") | |
print() | |
## TODO use the following code to test your 5x5 image detection data file | |
''' | |
neural_network = NeuralNetwork() | |
training_set_inputs, training_set_outputs = neural_network.read_data('images25x5x5.csv') | |
neural_network.train(training_set_inputs, training_set_outputs, 10000) | |
print("Considering new situation [] -> ?: ") | |
challenge = array( | |
[[1, 0, 0, 0, 1], | |
[0, 1, 0, 1, 0], | |
[0, 0, 0, 0, 0], | |
[0, 1, 0, 1, 0], | |
[1, 0, 0, 0, 1]]).ravel() ## | |
print(neural_network.think(challenge), "expecting probability close to 1") | |
print() | |
challenge = array( | |
[[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[1, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0]]).ravel() | |
print(neural_network.think(challenge), "expecting probability close to 0") | |
print() | |
challenge = array( | |
[[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0]]).ravel() | |
print(neural_network.think(challenge), "expecting probability close to 0") | |
print() | |
''' | |
We can make this file beautiful and searchable if this error is corrected: It looks like row 2 should actually have 2 columns, instead of 4. in line 1.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1, 3 | |
0, 1, 1, 0 | |
0, 0, 1 | |
1, 1, 1 | |
1, 0, 1 | |
0, 1, 1 |
We can make this file beautiful and searchable if this error is corrected: It looks like row 2 should actually have 2 columns, instead of 4. in line 1.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2, 2 | |
0, 1, 1, 0 | |
0, 0, 1, 0 | |
1, 1, 1, 0 | |
1, 0, 1, 0 | |
0, 1, 1, 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment