Documentation for Capstone-Finnegan

Contents:

Finnegan - An Exploration in Neural Nets

Overview

Finnegan is a basic multi-class neural net classifier. It is designed to be trained with any labled dataset, and then make predictions (classifications) on unseen, similar examples.

A front end user experience, in the form of a web app is provided around the task of classifying handwritten digits (0-9). To try: navigate here in a browser.

The webapp uses django and boostrap to serve a javascript page to collect the handwriting sample. On the backend the server parses the drawing to a greyscale image and then uses the pixel values as the input vector to the neural net.

The neural net in the webapp is pre-trained (as real time training would be impractical from the perspective of a user’s time).

The pre-training was done on the MNIST dataset, a set of 60,000 handwritten digit examples. Each a 28px by 28px greyscale image. The architecture of the net was chosen by running the helper function “ext_mini_net.py” to iterate over many possible combinations of layer sizes (number of neurons) and number of layers. The most successful of those runs against a validation set were chosen and the state of that trained network was “pickled” using Python Pickle.

The webapp reinstantiates that trained network and runs the user’s sample resized (see this post on my blog for deatails on that). It then makes a guess as to which digit it is. It also provides a confidence and requests feedback from the user on the validity of the guess. The data surrounding each submission is stored in a PostgreSQL database: image, resized image, guess, confidence, correct/incorrect, actual digit (if guess was incorrect).

Lastly, a statistic page is provided for the overall performance of the classifier.

Requirements

Basic Neural Network Needs

  • Scipy
  • Numpy
  • Scikit-learn (for randomize dataset, or using their handwritten, smaller digits)

Webapp Needs (in addition to above)

  • Django
  • Bootstrap
  • PosgreSQL

Usage

To run the webapp locally, clone the repo.

You will need to setup a PostgreSQL database and point the app to it in: capstone/net/settings.py

Then from the capstone directory:

python manage.py makemigrations
python manage.py migrate
python manage.py runserver

This will serve the page on localhost:8000. Navigate your browser there and enjoy.

To use the Finnegan network separately, from capstone/finnegan:

from network import Network

Create an instance from the class:

net = Network(layers, neuron_count, vector)

Where: - layers is number of layers including the output layer - neuron_count is a list of integers representing the number of neurons per layer, with the output layer being the last in the list (and therefor should be the total number of possible classifications). - vector is a sample input vector (for determining size and shape)

Then:

net.train(dataset, answers, epcohs)
guesses = net.run_unseen(test_dataset)
net.report_results(guesses, test_answers)

Will train the net, and provide a report on the success of guessing against the test set.

Acknowledgements

sketch.js is a javascript/jquery tool for capturing user input on an html canvas. Borrowed and modified from here.

The blog I Am Trask provided me with the key insight to vectorize each layer as a single unit and thereby get rid of the for loops as that took FOREVER to run.

Network Class for Neural Network

Author: Cole Howard

An extinsible neural net designed to explore Neural Network Architecture via extensive visualizations.

class finnegan.network.Network(layers, neuron_count, vector)

A multi layer neural net with backpropogation.

Parameters:
  • layers (int) – Number of layers to use in the network.
  • neuron_count (list) – A list of integers that represent the number of neurons present in each hidden layer. (Size of input/output layers are dictated by dataset)
  • vector (list) – Example vector to get size of initial input
possible

list

A list of possible output values

_backprop(guess_vector, target_vector)

Takes the output of the net and initiates the backpropogation

In output layer:
generate error matrix [(out * (1-out) * (Target-out)) for each neuron] update weights matrix [[+= l_rate * error_entry * input TO that amount] for each neuron ]
In hidden layer
generate error matrix [out * (1-out) * dotproduct(entry in n+1 error matrix, n+1 weight of that entry)] update weights matrix [[+= l_rate for each weight] for each neuron]
Parameters:
  • guess_vector (numpy array) – The output from the last layer during a training pass
  • target_vector (list) – List of expected values
Returns:

As evidence of execution

Return type:

True

_pass_through_net(vector, dropout=True)

Sends a vector into the net

Parameters:
  • vector (numpy array) – A numpy array representing a training input (without the target)
  • dropout (bool) – Whether or not you should perform random dropout in the pass through the net. (Set False for the tesing set vectors)
Returns:

Output of the last layer in the chain

Return type:

numpy array

_softmax(w, t=1.0)

Author: Jeremy M. Stober, edits by Martin Thoma Program: softmax.py Date: Wednesday, February 29 2012 and July 31 2014 Description: Simple softmax function. Calculate the softmax of a list of numbers w.

Parameters:
  • w (list of numbers) –
  • t (float) –
Returns:

Return type:

a list of the same length as w of non-negative numbers

Examples

>>> softmax([0.1, 0.2])
array([ 0.47502081,  0.52497919])
>>> softmax([-0.1, 0.2])
array([ 0.42555748,  0.57444252])
>>> softmax([0.9, -10])
array([  9.99981542e-01,   1.84578933e-05])
>>> softmax([0, 10])
array([  4.53978687e-05,   9.99954602e-01])
report_results(guess_list, answers)

Reports results of guesses on unseen set

Parameters:
  • guess_list (list) –
  • answers (list) –
run_unseen(test_set)

Makes guesses on the unseen data, and switches over the test answers to validation set if the bool is True

For each vector in the collection, each neuron in turn will either fire or not. If a vector fires, it is collected as a possible correct guess. Not firing is collected as well, in case there an no good guesses at all. The method will choose the vector with the highest dot product, from either the fired list or the dud list.

Parameters:test_set (list) – List of numpy arrays representing the unseen vectors
Returns:a list of ints (the guesses for each vector)
Return type:list
train(dataset, answers, epochs)

Runs the training dataset through the network a given number of times.

Parameters:
  • dataset (Numpy nested array) – The collection of training data (vectors and the associated target value)
  • answers (numpy array) – The array of correct answers to associate with each training vector
  • epochs (int) – Number of times to run the training set through the net

Layer Class for Neural Network

Author: Cole Howard

class finnegan.layer.Layer(num_neurons, vector_size)

A matrix representation of the neurons in a layer Inspired by: I Am Trask http://iamtrask.github.io/2015/07/12/basic-python-network/

Parameters:
  • num_neurons (int) – The number of instances of the class Neuron in each layer.
  • vector_size (int) – The number of inputs from the previous layer/original input. Also, equivalent to the length of incoming input vector.
weights

numpy array

A matrix reprsentation of the weight space. Each column represents a neurnon in the layer. Each entry in those columns is the value of a weight in that neuron.

mr_output

numpy array

Output of the layer

mr_input

numpy array

Input vector from the layer below (or original input)

deltas

numpy array

Calculated change in the weightspace for the backprop

l_rate

float

The learning rate for the update weight method

reg_rate

float

The factor by which the weights are adjusted for regularization to prevent overfitting.

_act_derivative(vector)

Calculate the derivative of the activation function

Parameters:vector (numpy array) – A vector representing the most recent output of a given layer
Returns:
Return type:numpy array
_layer_level_backprop(output, layer_ahead, target_vector, hidden=True)

Calculates the error at this level

Parameters:
  • layer_ahead (object) – The instance of Layer that this layer’s output is connected to
  • target_vector (numpy array) – A representation of the expected output of the net for the original vector input on this particular pass
  • hidden (bool) – Whether or not the current layer is hidden (default: True)
Returns:

For acknoledgment of execution

Return type:

True

_update_weights()

Update the weights of each neuron based on the backprop calculation

_vector_pass(vector, do_dropout=True)

Takes the vector through the neurons of the layer

Parameters:
  • vector (numpy array) – The input array to the layer
  • do_dropout (bool) – Whether or not weight dropout should happen as the vector passes through the layer
Returns:

The ouput of the layer

Return type:

numpy array

Mini Net Helper Module

Author: Cole Howard

Helper module to create or reinstantiate a neural network. Commented out code is for training the network via Scikit dataset or original MNIST dataset. The resulting network is then pickled and saved to a file. The current uncommented code is for reading that file and reinstantiating it for testing new input against.

mini_net.run_mnist(vector, epochs=0, layers=0, neuron_count=0)

Builds network (or reinstantiates it) based on the MNIST Digits dataset.

Parameters:
  • epochs (int) – Number of iterations of the the traininng loop for the whole dataset
  • layers (int) – Number of layers (not counting the input layer, but does count output layer)
  • neuron_count (list) – The number of neurons in each of the layers (in order), does not count the bias term
mini_net.target_values

list

The possible values for each training vector

mini_net.run_scikit_digits(vector, epochs=0, layers=0, neuron_count=[])

Builds network (or reinstantiates it) based on the Scikit Digits dataset.

Parameters:
  • epochs (int) – Number of iterations of the the traininng loop for the whole dataset
  • layers (int) – Number of layers (not counting the input layer, but does count output layer)
  • neuron_count (list) – The number of neurons in each of the layers (in order), does not count the bias term
mini_net.target_values

list

The possible values for each training vector

Django View for Finnegan Web App

guess.views.parse_data(request, *args, **kwargs)

As a request comes from the home page via POST, parse the canvas image, downsize it to match the dims of the training data, and then pass it to the pre-trained neural network for it make a prediction.

The results of the prediction (value and confidence), as well as the array representations of the images themselves are stored in the model, and hence the PostgresQL database.

guess.views.show_data(request)

Sends a render of image as drawn and the network’s guess and confidence via the report template.

guess.views.drawing_obj

Drawing model instance

The last line from the database (specifically the most recent entry).

guess.views.stats_work(request)

Work out statistics for results

guess.views.valid_info(request, *args, **kwargs)

Stores the users validation (or dis-validation) of the network’s guess in the database along with what the user intended it to be, in the case of an incorrect guess.

Helper Method for Parsing Web App Input

Accept an array representing a test sample, parse it and pass through a pre-trained neural net then store results in a pre-existing database

guess.predict.parse_to_test_sample(info)

Takes the info retrieved from the script.js implementation on main page and parses it. Data is run against existing neural net and then stores net’s output and original data in PostgreSQL database.

guess.predict.orig_size

int

The length of a side of the square html input canvas.

guess.predict.train_data_size

int

The length of a side of the square 2d array representing the training data.

Indices and tables