ofxNeuralNetwork.zip
Demo-images
I wrote a backpropagation-based neural network for Java a few years ago, and I just ported it to C++. The biggest difference between this and something like FANN, apart from scope, is that it’s meant to be used online (i.e., continually alternating between training and running, rather than training first and then running).
NeuralNetworkDemo
Demonstrates how to interface with the class directly. First it sets up a network with 2 input nodes, 3 output nodes, and 3 intermediate nodes.
vector<int> dimensions(3);
dimensions[0] = 2;
dimensions[1] = 3;
dimensions[2] = 3;
nn = new NeuralNetwork(dimensions);
Then it runs the network at each point on the screen:
vector<float> input(2);
input[0] = map(x, 0, width, -1, +1);
input[1] = map(y, 0, height, -1, +1);
vector<float>* output = nn->run(input);
(Notice that this neural network operates on -1 to +1 – just because I understand the math for this kind better than the 0 to 1 style). The output is then mapped to colors and drawn to the screen. Random weights create random gradients.
Learning is not demonstrated, but works like this:
vector<float> input, expected;
...
nn->learn(input, expected);
ofxNeuralNetworkDemo
Demonstrates how to interface with the NeuralNetwork indirectly using ofxNeuralNetwork, which uses the VectorMath class as an interface. Also, notice that Connection has two static variables you can set:
Connection::learningRate = 0.001;
Connection::maxInitWeight = .1;
The network is set up to take two ofxPoint2fs as input, and output one ofxPoint2f. The two ofxPoint2fs have different boundaries (one is a position, the other is a velocity), and the ofxNeuralNetwork will take care of that mapping for you.
vector<ofxPoint2f> minInput, maxInput, minOutput, maxOutput;
vector<int> topology;
int maxVelocity = 128;
minInput.push_back(ofxPoint2f(0, 0));
minInput.push_back(ofxPoint2f(-maxVelocity, -maxVelocity));
maxInput.push_back(ofxPoint2f(width, height));
maxInput.push_back(ofxPoint2f(+maxVelocity, +maxVelocity));
minOutput.push_back(ofxPoint2f(-maxVelocity, -maxVelocity));
maxOutput.push_back(ofxPoint2f(+maxVelocity, +maxVelocity));
topology.push_back(6);
resolution = 8;
nn = new ofxNeuralNetwork<ofxPoint2f>(minInput, maxInput, topology, minOutput, maxOutput, resolution);
The size of the input and output is implicitly given by the number of boundaries. The intermediate nodes are given by “topology”. “resolution” determines how much discrimination the inputs have. The more resolution you have, the more intermediate nodes you’ll need. The more resolution or the more intermediate nodes you have, the slower the network will run. Currently, ofxNeuralNetwork is limited to using all the same ofxPoints.
Learning is accomplished like this:
vector<ofxPoint2f> input, expected;
...
nn->learn(input, expected);
And ofxNeuralNetwork will save everything you’ve taught it so you can relearn quickly. For example, relearning a specific instance:
nn->relearn((int) ofRandom(0, nn->memorySize()));
To run the ofxNeuralNetwork, you can say:
vector<ofxPoint2f> input;
...
vector<ofxPoint2f>* output = nn->run(input);
...
delete output;
This specific demo uses this functionality to learn to scribble like you. I have another app where I’m using these scribbles to make some Yasunao Tone-style noise. If you’d like to play with it, the controls are: space to create a new neural network, enter to clear the screen, ‘i’ to toggle illustration mode, ‘f’ to toggle the field lines, and ‘s’ to save a screenshot.
ofxProcessing
This uses one other addon, ofxProcessing, which is just some of the functionality of Processing I find myself wanting in of. Right now it’s got: a bunch of print() and println()s, save() and saveFrame(), radians(), degrees() and rotate(), map() sq() constrain() dist() mag(). There are some Processing-like things I was considering adding here (e.g.: saveUniqueFrame() that uses ofxDirList to saveFrame() without writing over old files) but I think it’d be best to keep it to functions that exactly mirror Processing only. That way if other people want to implement other functions that aren’t already there, there is no ambiguity about whether it should be included or not.
So, obviously: you’ll need to copy these addons to your /addons and add to “addons.h”:
#ifdef OF_ADDON_USING_OFXNEURALNETWORK
#include "ofxNeuralNetwork.h"
#endif
#ifdef OF_ADDON_USING_OFXPROCESSING
#include "ofxProcessing.h"
#endif