##ConvolutionalNeuralNetwork
A general purpose convolutional neural network.
Under construction. This network it currently under development and expected to be finished soon. When finished I will write a blog post on how to write the thing from scratch yourself.
###About
This project is a simple to use general purpose convolutional neural network framework. It features several types of layers which can be linked together as they are needed. Written in C++ which allows it to run blazingly fast (not just yet) and stay extremely portable (it has no dependencies).
###Usage
The network has a layered design which allows different configurations of how many layers and what layer types should be stacked together.
There are four types of layers:
- Convolution. The convolution layer will perform the main feature extraction for the provided sample.
- Pooling. The pooling layer performs a downsampling of the input by the factor of
filterSize
(defaults to 2) and with a stride provided instride
(defaults to 2). So the default downsampling is equal to 2x2. - Hidden. The hidden layer is a layer of a regular multi layer perceptron. It's only difference from the output layer is the way it computes its backpropagation gradients.
- Output layer. The final layer. There are no hyperparameters to specify, just make sure you end the network with an output layer.
A fancy ASCII art of the network structure:
+-------------------+---------------+-----+--------------+-----+--------------+
| Convolution layer | Pooling layer | ... | Hidden layer | ... | Output layer |
+-------------------+---------------+-----+--------------+-----+--------------+
The convolution & pooling layer combinations are optional and there are no restrictions on how many there can be. If no conv & pooling layers are present the netowrk behaves line a regular multilayer perceptron. While the pooling layer itself is also optional it is recommended since the network yields better results when used (spatial invariance).
#####Code
Here's what an example might look like (so far only the MLP part is working):
using namespace sf;
//Size of our input data
const unsigned long inputWidth = 3;
const unsigned long inputHeight = 1;
//A bunch of samples. The 1 & 2 are similar so are 3 & 4 and 5 & 6.
double sample1[] = {1.0, 0.2, 0.1}; //Cow
double sample2[] = {0.8, 0.1, 0.25}; //Cow
double sample3[] = {0.2, 0.95, 0.1}; //Chicken
double sample4[] = {0.11, 0.9, 0.13}; //Chicken
double sample5[] = {0.0, 0.2, 0.91}; //Car
double sample6[] = {0.21, 0.12, 1.0}; //Car
//A new network with the given data width and height
Net *net = new Net(inputWidth, inputHeight);
sf::LayerDescriptor descriptor;
descriptor.type = kLayerTypeHiddenNeuron;
descriptor.neuronCount = 4;
net->addLayer(descriptor); //A hidden neural layer with 4 neurons
net->addLayer(descriptor); //A hidden neural layer with 4 neurons
descriptor.type = kLayerTypeOutputNeuron;
net->addLayer(descriptor); //Finish it off by adding an output layer
//Add all the samples with their corresponding labels
net->addTrainingSample(sample1, "cow");
net->addTrainingSample(sample2, "cow");
net->addTrainingSample(sample3, "chicken");
net->addTrainingSample(sample4, "chicken");
net->addTrainingSample(sample5, "car");
net->addTrainingSample(sample6, "car");
//And now we play the waiting game
net->train();
//This example is similar to "chicken" so we expect the chicken probability to be close to 1 and car and cow to be close to 0
double example[] = {0.1, 0.98, 0.01};
auto output = net->classifySample(example);
//Let's see what we get
for (auto &tuple : output)
std::cout << std::get<1>(tuple) << ": " << std::get<0>(tuple) << std::endl;
std::cout << std::endl;
return 0;
####Building it
You can open it using Xcode or just make build
. To toggle debug mode (exposes all private properties, ...) just update the #define DEBUG
flag in the helpers.h
.
###TODO
Things to come (in order):
- Finish
PoolingLayer
backpropagation - Finish
ConvolutionLayer
backpropagation - A few tweaks here and there
- Release alpha version
- Merge
OutputNeuronLayer
andHiddenNeuronLayer
- Refactor to C++14 (no raw pointers, ...)
- Finish various TODOs (code comments)
- Release beta version After this point I don't have a concrete plan of what to do next. Here are some things I'm considering:
- Speed it up
- CUDA support
- Add tests :>
- ???