GithubHelp home page GithubHelp logo

neural2d's Introduction

This repository and the associated neural2d.net website are no longer supported and will be going away soon. Neural2d started as a fun weekend project, then gained some momentum from excellent code contributions from a number of programmers. But I’m at a place in my life where I need to turn my attention elsewhere. I would refer users and educators to the many excellent neural net resources that are more pedagogically effective and more technologically current than this project.

The most recent neural2d user manual is shown below for historical reference.

A sincere thank-you to everyone who particpiated in neural2d, and best wishes in your neural-netting.

— Dave

Neural2d - Neural Net Simulator User Manual

Features

  • Optimized for 2D input data
  • Neuron layers can be abstracted as 1D or 2D arrangements of neurons
  • Input data can binary or text
  • Network topology is defined in a text file
  • Neurons in layers can be fully or sparsely connected
  • Selectable transfer function per layer
  • Adjustable or automatic training rate (eta)
  • Optional momentum (alpha) and regularization (lambda)
  • Convolution filtering and convolution networking
  • Standalone console program
  • Simple, heavily-commented code, suitable for prototyping, learning, and experimentation
  • Optional web-browser-based GUI controller
  • Graphic visualizations of hidden-layer data
  • No dependencies! Just C++11 (and POSIX networking for the optional webserver interface)

Document Contents

Overview
Requirements
Compiling the source
How to run the digits demo
How to run the XOR example
GUI interface
How to use your own data
The 2D in neural2d
Convolution filtering
Convolution networking and pooling
Layer depth
Topology config file format
Topology config file examples
How-do-I X?

Overview

Neural2d is a standalone console program with optional HTTP web interface written in C++. It's a backpropagation neural net simulator, with features that make it easy to think of your input data as either one-dimensional or two-dimensional. You specify a network topology in a text file (topology.txt). The input data to the neural is specified in a text file (inputData.txt). The inputData.txt file can contain the actual input values for all the input samples, or it can contain a list of .bmp or .dat files that contain the input data in binary form.

Neural2d is for educational purposes. It's not production-quality code, and it's not burdened with a lot of bling. It's just heavily-commented neural net code that you can take apart and see how it works. Or modify it and experiment with new ideas. Or extract the functions you need and embed them into your own project.

If you're not using the optional GUI interface, then neural2d has no dependencies other than a conforming C++11 compiler. If using the GUI interface, you'll need to link with a standard POSIX sockets networking library.

Requirements

  • C++-11 compiler
    • e.g., g++ 4.7 on Linux or Cygwin, Visual Studio 2013 on Windows
  • POSIX sockets (only needed if compiling the optional GUI)
    • e.g., Cygwin on Windows
  • CMake 2.8.12 or later
  • Compiles and runs on Linux, Windows, and probably Mac

Compiling the source

We use CMake to configure the build system. First get the source code from the Gitub repository. If using the command line, the command is:

 git clone https://github.com/davidrmiller/neural2d

That will put the source code tree into a directory named neural2d.

Compiling with CMake graphical interface

If you are using the CMake graphical interface, run it and set the "source" directory to the neural2d top directory, and set the binary output directory to a build directory under that (you must create the build directory), then click Configure and Generate. Uncheck WEBSERVER if you don't want to compile the optional GUI. Here is what it looks like:

CMake GUI example

Compiling with CMake command line interface

If you are using CMake from the command line, cd to the neural2d top level directory, make a build directory, then run cmake from there:

git clone https://github.com/davidrmiller/neural2d
cd neural2d
mkdir build
cd build
cmake ..
make

There is no "install" step. After the neural2d program is compiled, you can execute it or open the project file from the build directory.

On Windows, by default CMake generates a Microsoft Visual Studio project file in the build directory. On Linux and Cygwin, CMake generates a Makefile that you can use to compile neural2d. You can specify a different CMake generator with the -G option, for example:

 cmake -G "Visual Studio 14 2015" ..

To get a list of available CMake generators:

 cmake --help

If you get errors when compiling the integrated webserver, you can build neural2d without webserver support by running CMake with the -DWEBSERVER=OFF option, like this:

 cmake -DWEBSERVER=OFF ..

How to run the digits demo

On systems using Makefiles, in the build directory, execute:

make test

This will do several things: it will compile the neural2d program if necessary; it will expand the archive named image/digits/digits.zip into 5000 individual images; and it will then train the neural net to classify those digit images.

The input data, or "training set," consists of images of numeric digits. The first 50 look like these:

training samples

The images are 32x32 pixels each, stored in .bmp format. In this demo, the neural net is configured to have 32x32 input neurons, and 10 output neurons. The net is trained to classify the digits in the images and to indicate the answer by driving the corresponding output neuron to a high level.

Once the net is sufficiently trained, all the connection weights are saved in a file named "weights.txt".

If you are not using Makefiles, you will need to expand the archive in images/digits, then invoke the neural2d program like this:

 neural2d ../images/digits/topology.txt ../images/digits/inputData.txt weights.txt

How to run the XOR example

On systems using Makefiles, in the build directory, execute:

 make test-xor

For more information about the XOR example, see this wiki page.

GUI interface (optional)

First, launch the neural2d console program in a command window with the -p option:

 ./neural2d topology.txt inputData.txt weights.txt -p

The -p option causes the neural2d program to wait for a command before starting the training. The screen will look something like this:

console-window

At this point, the neural2d console program is paused and waiting for a command to continue. Using any web browser, open:

 http://localhost:24080

A GUI interface will appear that looks like:

HTTP interface

Press Resume to start the neural net training. It will automatically pause when the average error rate falls below a certain threshold (or when you press Pause). You now have a trained net. You can press Save Weights to save the weights for later use.

See the neural2d wiki for design notes on the web interface.

Visualizations

At the bottom of the GUI window, a drop-down box shows the visualization options that are available for your network topology, as shown below. There will be options to display the activation (the outputs) of any 2D layer of neurons 3x3 or larger, and convolution kernels of size 3x3 or larger. Visualization images appear at the bottom of the GUI. You can mouse-over the images to zoom in.

visualizerExample

How to use your own data

Input data to the neural net can be specified in text or binary format. If you want to specify input values in text format, just list the input values in the inputData.txt file. If you're inputting from .bmp or .dat binary files, then list those filenames in inputData.txt. Details are explained below.

Text input format

To specify input data as text, prepare a text file, typically called inputData.txt, with one input sample per line. The input values go inside curly braces. If the data is for training, the target output values must be specified on the same line after the input values. In each sample, the input values are given in a linear list, regardless whether the neural net input layer is one-dimensional or two-dimensional. For example, if your neural net has 9 input neurons of any arrangement and two output neurons, then the inputData.txt file for training will look like this format:

{ 0.32 0.98 0.12 0.44 0.98 0.22 0.34 0.72 0.84 } -1  1   
{ 1.00 0.43 0.19 0.83 0.97 0.87 0.75 0.47 0.92 }  1  1   
{ 0.87 0.75 0.47 0.92 1.00 0.43 0.19 0.83 0.97 } -1 -1   
{ 0.34 0.83 0.97 0.87 0.75 0.43 0.19 0.47 0.92 } -1  1   
etc.. . .  

Binary input formats

There are two binary options -- .bmp image files, and .dat data files. First, prepare your .bmp or .dat files, one sample per file. If using .bmp files, the number of pixels in each image should equal the number of input neurons in your neural net. If using .dat files, each file must contain a linear list of input values, with the same number of values as the number of input neurons in your neural net.

Next, prepare an input data configuration file, called inputData.txt containing a list of the .bmp or .dat filenames, one per line. If the data is for training, then also list the target output values for each input sample after the filename, like this:

images/thumbnails/test-918.bmp -1 1 -1 -1 -1 -1 -1 -1 -1 -1
images/thumbnails/test-919.bmp -1 -1 -1 -1 -1 -1 -1 -1 1 -1
images/thumbnails/test-920.bmp -1 -1 -1 -1 -1 -1 1 -1 -1 -1
images/thumbnails/test-921.bmp -1 -1 -1 -1 -1 1 -1 -1 -1 -1
etc. . .

The path and filename cannot contain any spaces.

The path_prefix directive can be used to specify a string to be attached to the front of all subsequent filenames, or until the next path_prefix directive. For example, the previous example could be written:

 path_prefix = images/thumbnails/
 test-918.bmp
 test-919.bmp
 test-920.bmp
 test-921.bmp
 etc. . .

For more information on the .bmp file format, see this Wikipedia article..

For more information on the neural2d .dat binary format, see this wiki page. and the design notes.

Topology file

In addition to the input data config file (inputData.txt), you'll also need a topology config file (typically named topology.txt by default) to define your neural net topology (the number and arrangement of neurons and connections). Its format is described in a later section. A typical one looks like this example:

input size 32x32  
layer1 size 32x32 from input radius 8x8  
layer2 size 16x16 from layer1  
output size 1x10 from layer2  

Then run neuron2d (optionally with the web browser interface) and experiment with the parameters until the net is adequately trained, then save the weights in a file for later use.

If you run the web interface, you can change the global parameters from the GUI while the neural2d program is running. If you run the neural2d console program without the GUI interface, there is no way to interact with it while running. Instead, you'll need to examine and modify the parameters in the code at the top of the files neural2d.cpp and neural2d-core.cpp.

The 2D in neural2d

In a simple traditional neural net model, the neurons are arranged in a column in each layer:

In neural2d, you can specify a rectangular arrangement of neurons in each layer, such as:

The neurons can be sparsely connected to mimic how retinal neurons are connected in biological brains. For example, if a radius of "1x1" is specified in the topology config file, each neuron on the right (destination) layer will connect to a circular patch of neurons in the left (source) layer as shown here (only a single neuron on the right side is shown connected in this picture so you can see what's going on, but imagine all of them connected in the same pattern):

radius-1x1

The pattern that is projected onto the source layer is elliptical. (Layers configured as convolution filters work slightly differently; see the later section about convolution filtering.)

Here are some projected connection patterns for various radii:

radius 0x0

radius 1x1

radius 2x2

radius 3x1

Convolution filtering

Any layer other than the input layer can be configured as a convolution filter layer by specifying a convolve-matrix specification for the layer in the topology config file. The neurons are still called neurons, but their operation differs in the following ways:

  • The connection pattern to the source layer is defined by the convolution matrix (kernel) dimensions (not by a radius parameter)

  • The connection weights are initialized from the convolution matrix, and are constant throughout the life of the net.

  • The transfer function is automatically set to the identity function (not by a tf parameter).

For example, the following line in the topology config file defines a 3x3 convolution matrix for shrarpening the source layer:

 layerConv1 size 64x64 from input convolve {{0,-1,0},{-1,5,-1},{0,-1,0}}

When a convolution matrix is specified for a layer, you cannot also specify a radius parameter for that layer, as the convolution matrix size determines the size and shape of the rectangle of neurons in the source layer. You also cannot also specify a tf parameter, because the transfer function on a convolution layer is automatically set to be the identity function.

The elements of the convolution matrix are stored as connection weights to the source neurons. Connection weights on convolution layers are not updated by the back propagation algorithm, so they remain constant for the life of the net.

For illustrations of various convolution kernels, see this Wikipedia article

In the following illustration, the topology config file defines a convolution filter with a 2x2 kernel that is applied to the input layer, then the results are combined with a reduced-resolution fully-connected pathway. The blue connections in the picture are the convolution connections; the green connections are regular neural connections:

input size 8x8
layerConvolve size 8x8 from input convolve {{-1,2},{-1,2}}
layerReducedRes size 4x4 from input
output size 2 from layerConvolve
output size 2 from layerReducedRes

Convolution networking and pooling

A convolution network layer is like a convolution filter layer, except that the kernel participates in backprop training, and everything inside the layer is replicated N times to train N separate kernels. A convolution network layer is said to have depth N. A convolution network layer has depth * X * Y neurons.

Any layer other than the input or output layer can be configured as a convolution networking layer by specifying a layer depth > 1, and specifying the kernel size with a convolve parameter. For example, to train 40 kernels of size 7x7 on an input image of 64x64 pixels:

  input size 64x64
  layerConv size 40*64x64 from input convolve 7x7
  . . .

A pooling layer down-samples the previous layer by finding the average or maximum in patches of source neurons. A pooling layer is defined in the topology config file by specifying a pool parameter on a layer.

In the topology config syntax, the pool parameter requires the argument "avg" or "max" followed by the operator size, For example, in a convolution network pipeline of depth 20, you might have these layers:

  input size 64x64
  layerConv size 20*64x64 from input convolve 5x5
  layerPool size 20*16x16 from layerConv pool max 4x4
  . . .

Layer depth

All layers have a depth, whether explicit or implicit. Layer depth is specified in the topology config file in the layer size parameter by an integer and asterisk before the layer size. If the depth is not specified, it defaults to one. For example:

  • size 10*64x64 means 64x64 neurons, depth 10

  • size 64x64 means 64x64 neurons, depth 1

  • size 1*64x64 also means 64x64 neurons, depth 1

  • size 10*64 means 64x1 neurons, depth 10 (the Y dimension defaults to 1)

The primary purpose of layer depth is to allow convolution network layers to train multiple kernels. However, the concept of layer depth is generalized in neural2d, allowing any layer to have any depth and connect to any other layer of any kind with any depth.

The way two layers are connected depends on the relationship of the source and destination layer depths as shown below:

Relationship How connected
src depth == dst depth connect only to the corresponding depth in source
src depth != dst depth fully connect across all depths

Topology config file format

Here is the grammar of the topology config file:

layer-name parameters := parameter [ parameters ]

parameters := parameter [ parameters ]

parameter :=

          input | output | layername

          size dxy-spec

          from layer-name

          channel channel-spec

          radius xy-spec

          tf transfer-function-spec

          convolve filter-spec

          convolve xy-spec

          pool { max | avg } xy-spec

dxy-spec := [ integer * ] integer [ x integer ]

xy-spec := integer [ x integer ]

channel-spec := R | G | B | BW

transfer-function-spec := tanh | logistic | linear | ramp | gaussian | relu

filter-spec := same {{,},{,}} syntax used for array initialization in C, C#, VB, Java, etc.

Rules:

  1. Comment lines that begin with "#" and blank lines are ignored.

  2. The first layer defined must be named "input".

  3. The last layer defined must be named "output".

  4. The hidden layers can be named anything beginning with "layer".

  5. The argument for "from" must be a layer already defined.

  6. The color channel parameter can be specified only on the input layer.

  7. If a size parameter is omitted, the size is copied from the layer specified in the from parameter.

  8. A radius parameter cannot be used on the same line with a convolve or pool parameter.

  9. The same layer name can be defined multiple times with different "from" parameters. This allows source neurons from more than one layer to be combined in one destination layer. The source layers can be any size, but the repeated (the destination) layer must have the same size in each specification. For example, in the following, layerCombined is size 16x16 and takes inputs from two source layers of different sizes:

     input size 128x128  
     layerVertical size 32x32 from input radius 1x8  
     layerHorizontal size 16x16 from input radius 8x1  
     layerCombined from layerHorizontal          <= assumes size 16x16 from the source layer  
     layerCombined size 16x16 from layerVertical <= repeated destination, must match 16x16  
     output size 1 from layerCombined  
  1. In the xy-spec and in the X,Y part of the dxy-spec, you may specify one or two dimensions. Spaces are not allowed in the size spec. If only one dimension is given, the other is assumed to be 1. For example:
  • "8x8" means 64 neurons in an 8 x 8 arrangement.
  • "8x1" means a row of 8 neurons
  • "1x8" means a column of 8 neurons.
  • "8" means the same as "8x1"

Topology config file examples

Here are a few complete topology config files and the nets they specify.

input size 4x4
layer1 size 3x3 from input
layer2 size 2x2 from layer1
output size 1 from layer2

input size 4x4
layer1 size 1x4 from input
layer2 size 3x1 from layer1
output size 1 from layer2

input size 4x4
output size 4x1 from input radius 0x2

input size 16x16
layer1 size 4x4 from input radius 1x1
output size 7x1 from layer1

# In the picture that follows, layerVertical is the set of 4 neurons
# in the upper part of the picture, and layerHorizontal is the lower
# set of 4 neurons.

input size 6x6
layerHorizontal size 2x2 from input radius 2x0
layerVertical size 2x2 from input radius 0x2
output size 1 from layerHorizontal
output size 1 from layerVertical

# This example shows how vertical and horizontal image features can be
# extracted through separate paths and combined in a subsequent layer.

input size 4x4

layerH1 size 1x4 from input radius 4x0
layerH2 size 1x4 from layerH1
layerH3 size 1x4 from layerH2

layerV1 size 4x1 from input radius 0x4
layerV2 size 4x1 from layerV1
layerV3 size 4x1 from layerV2

output size 2 from layerV3
output size 2 from layerH3

How-do-I X?

How do I run the command-line program?

Run neural2d with three arguments specifying the topology configuration, input data configuration, and where to store the weights if training succeeds:

 ./neural2d topology.txt inputData.txt weights.txt

How do I run the GUI interface?

First launch the neural2d program with the -p option:

 ./neural2d topology.txt inputData.txt weights.txt -p

Then open a web browser and point it at http://localhost:24080 .

If your firewall complains, you may need to allow access to TCP port 24080.

How do I disable the GUI interface?

Run CMake with the -DWEBSERVER=OFF option. Or if you are using your own home-grown Makefiles, you can define the preprocessor macro DISABLE_WEBSERVER. For example, with gnu compilers, add -DDISABLE_WEBSERVER to the g++ command line. Alternatively, you can undefine the macro ENABLE_WEBSERVER in neural2d.h.

When the web server is disabled, there is no remaining dependency on POSIX sockets.

Also see the illustrations above.

How do I use my own data instead of the digits images?

For binary input data, create your own directory of BMP image files or .dat binary files, and an input data config file (inputData.txt) that follows the same format as shown in the examples elsewhere. Then define a topology config file with the appropriate number of network inputs and outputs, then run the neural2d program.

Or if you don't want to use .bmp image files or .dat binary files for input, make an input config file containing all the literal input values and the target output values.

See above for more information on the input formats.

How do I use a trained net on new data?

It's all about the weights file. After the net has been successfully trained, save the internal connection weights in a weights file. That's typically done in neural2d.cpp by calling the member function saveWeights(filename).

The weights you saved can be loaded back into a neural net of the same topology using the member function loadWeights(filename). Once the net has been loaded with weights, it can be used applied to new data by calling feedForward(). Prior to calling feedForward(), you'll want to set a couple of parameters:

 myNet.repeatInputSamples = false;
 myNet.reportEveryNth = 1;

This is normally done in neural2d.cpp.

You'll need to prepare a new input data config file (default name inputData.txt) that contains a list of only those new input data images that you want the net to process.

How do I train on the MNIST handwritten digits data set?

See the instructions in the wiki.

How do I change the learning rate parameter?

In the command-line program, you can set the eta parameter or change it by directly setting the eta member of the Net object, like this:

 myNet.eta = 0.1;

When using the web interface, you can change the eta parameter (and other parameters) in the GUI at any time, even while the network is busy processing input data.

Also see the Parameter List in the wiki.

Are the output neurons binary or floating point?

They are interpreted in whatever manner you train them to be, but you can only train the outputs to take values in the range that the transfer function is capable of producing.

If you're training a net to output binary values, it's best if you use the maxima of the transfer function to represent the two binary values. For example, when using the default tanh() transfer function, train the outputs to be -1 and +1 for false and true. When using the logistic transfer function, train the outputs to be 0 and 1.

How do I use a different transfer function?

You can add a "tf" parameter to any layer definition line in the topology config file. The argument to tf can be "tanh", "logistic", "linear", "ramp", "gaussian", or "relu". The transfer function you specify will be used by all the neurons in that layer. Here are the graphs of the built-in transfer functions.

In the topology config file, the tf parameter is specified as in this example:

 layerHidden1 size 64x64 from input radius 3x3 tf linear

You can add new transfer functions by following the examples in neural2d-core.cpp. There are two places to change: first find where transferFunctionTanh() is defined and add your new transfer function and its derivative there. Next, locate the constructor for class Neuron and add a new else-if clause there, following the examples.

How do I define a convolution filter?

In the topology config file, any layer defined with a convolve parameter and a list of constant weights will operate as a convolution filter applied to the source layer. The syntax is of the form:

 layer2 size 64x64 from input convolve {{1,0,-1},{0,0,0},{-1,0,1}}

Also see above for more information.

See this article for the difference between convolution filter and convolution networking.

How do I define convolution networking and pooling?

In the topology config file, define a layer with an X,Y size and a depth (number of kernels to train), and add a convolve parameter to specify the kernel size. For example, to train 40 kernels of size 7x7 on an input image of 64x64 pixels:

 input size 64x64  
 layerConv size 40*64x64 from input convolve 7x7
 . . .

To define a pooling layer, add a pool parameter, followed by the argument "avg" or "max," followed by the operator size, e.g.:

 layerConv size 10*32x32 ...
 layerPool size 10*8x8 from layerConv pool max 4x4
 . . .

Also see above for more information.

How do the color image pixels get converted to floating point for the input layer?

That's in the ImageReaderBMP class in neural2d-core.cpp. The default version provided converts each RGB pixel to a single floating point value in the range -1.0 to 1.0.

By default, the three color channels are converted to monochrome and normalized to the range -1.0 to 1.0. That can be changed at runtime by setting the colorChannel member of the Net object to R, G, B, or BW prior to calling feedForward(). E.g., to use only the green color channel of the images, use:

myNet.colorChannel = NNet::G;

The color conversion can also be specified in the topology config file on the line that defines the input layer by setting the "channel" parameter to R, G, B, or BW, e.g.:

input size 64x64 channel G

There is no conversion when inputting floating point data directly from a .dat file, or from literal values embedded in the input data config file.

How can I use .jpg and .png images as inputs to the net?

Currently only .bmp images files are supported. This is because the uncompressed BMP format is so simple that we can use simple, standard C/C++ to read the image data without any dependencies on third-party image libraries.

To support a new input file format, derive a new subclass from class ImageReader and implement its getData() member following the examples of the existing image readers. For more information on the input data readers, see the design notes.

How can I find my way through the source code?

Here is a little map of the important files:

Also see the class relationship diagram in the project root directory.

Why does the net error rate stay high? Why doesn't my net learn?

Neural nets are finicky. Try different network topologies. Try starting with a larger eta values and reduce it incrementally. It could also be due to redundancy in the input data, or mislabeled target output values. Or you may need more training samples.

What other parameters do I need to know about?

Check out the list of parameters in the wiki.

Licenses

The neural2d program and its documentation are copyrighted and licensed under the terms of the MIT license. See the LICENSE file for more information.

The set of digits images in the images/digits/ subdirectory is released to the public domain.

neural2d's People

Contributors

davidrmiller avatar jeandudey avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

neural2d's Issues

classification ..but also regression

Hi,
is it able to do regression? I couldn't find any example of this in the docs but i saw examples of networks with one neuron on the output, that i can assume it is regression, but within what range can i give the input values then? I tried several things and couldn't figure it out, is there an example of using this network to do regression (to estimate numerically the similarity between two images for example)

Thank you

can not build

I get this error when trying to build in Visual Studio
parseTopologyConfig.cpp(548): error C3861: 'back_inserter': identifier not found

what can i do to fix it?
Thank you

Proposal: path_prefix directive in input data config file

This is a proposal to modify the input data configuration file parser to look for lines that begin with:

 path_prefix =

Everything after the equals sign, except leading and trailing whitespace, will be prepended to the front of all subsequent image filenames, or until the next path_prefix directive.

This would allow us to simplify an input data config file from this:

../images/digits/test-1.bmp -1 -1 -1 -1 -1 1 -1 -1 -1 -1
../images/digits/test-2.bmp -1 -1 -1 -1 1 -1 -1 -1 -1 -1
../images/digits/test-3.bmp -1 -1 -1 -1 1 -1 -1 -1 -1 -1
. . .

to this:

path_prefix = ../images/digits/
test-1.bmp -1 -1 -1 -1 -1 1 -1 -1 -1 -1
test-2.bmp -1 -1 -1 -1 1 -1 -1 -1 -1 -1 
test-3.bmp -1 -1 -1 -1 1 -1 -1 -1 -1 -1 
. . .

Details

Initially the path prefix is a null string. Each time the path_prefix directive is encountered, the new prefix replaces the old one. If there is nothing after the equals sign or nothing besides whitepace, the prefix string is reset to null. To keep this modification as simple as possible, the prefix string cannot contain embedded spaces. Whitespace is optional between path_prefix and the equals sign.

Optimization issue

Hello,

I am not 100% sure but I think there is a big optimization issue in the creation of the net.

Indeed, in the function Layer::connectLayers(Layer &layerFrom), we iterate through each neuron of a layer (in all depths).

Let's take a case where we connect a ConvolutionNetworkLayer such as this one: 3 * 28x28 convolve 5x5
To fromLayer that is maybe let's say the input Layer 1 * 28x28

Now, the main loop is going to do 28x28x5=3920 iterations and call connectOneNeuronAllDepths() 3920 times.

Now in the Layer::connectOneNeuronAllDepths(...) function, at line 526, we start looking for the Depth of this layer compared to the depth of the previous layer. If they aren't the same, we fully connect our neuron. This brings us to the issue, in line 561 where we check for existing connections. In the example I just gave, we are going to do 3920 find() for no reason. This can get out of hand really fast on bigger nets.

I think a solution to this would be to check the Depths back in Layer::connectLayer() so that we would know if we need to connect either one neuron or all depths neurons. That would of course, require to have 2 functions, one that only connects 1 neuron and takes the depth in parameter, and the other that connects one neuron ALL DEPTHS. The beginning of the function could be done in another function for code redundancy.

I hope that made sense :)

Let me know if I missunderstood something.

Thanks and great work!

Regards,
Tom

"Reload samples" button not implemented in neural2d-gui.py.

The Reload-samples button is intended to make it easy to switch from a training set to a validation set without having to save and reload the weights file and without having to re-invoke the GUI and the neural net. To implement that button, the neural2d-core.cpp code should free the existing SampleSet object and initialize a new one with the new sample data, and leave the program in paused mode (isRunning = false) so that the user can change other parameters as needed before resuming operation.

make test fails on Mac OSX Yosemite

I was able to cmake, then make without issue. When I ran "make test" I got the following:

[ 62%] Built target neural2d-core
[ 75%] Preparing images/digits/...
[100%] Built target neural2d
Creating layer input, one moment...
Creating layer layer1, one moment...
Creating layer output, one moment...

Checking for neurons with no sinks:
neuron(0x7fd9cb01a200) on input
5000 training samples initialized
Unsupported image file format in ../images/digits/test-6.bmp
libc++abi.dylib: terminating with uncaught exception of type NNet::exceptionInputSamplesFile: std::exception
make[3]: *** [CMakeFiles/test] Abort trap: 6
make[2]: *** [CMakeFiles/test.dir/all] Error 2
make[1]: *** [CMakeFiles/test.dir/rule] Error 2
make: *** [test] Error 2

Allow layers in topology config file to be specified in any order

Thanks to Michael Whidden for this great suggestion:

"In the configuration, the layers must be specified in proper order, because the layers list in code is built in the order specified in the configuration. You could allow the layers to be specified arbitrarily if you reordered the list according to the partial ordering provide by the 'from' attributes."

g++ 4.9 fails on implicit initializer in webserver.h

In webserver.h, the constructor for class MessageQueue has an implicit initializer that works on g++ 4.8 but fails on g++ 4.9. The offending line is:

 MessageQueue() { mqueue = { }; };

As far as I can tell, the initializer is not needed and can be removed.

Add the ability to read floating point data files

Hello, I would like to suggest an enhancement to Neural2D. Add the ability to read floating point data files instead of just BMP files. Keep it simple. Assume the files have an extension of .DAT.
The header could look like this.

  1. 4 byte integer magic number -- to identify the file
  2. 4 byte integer -- the width of the data
  3. 4 byte integer -- the height of the data
  4. 4 byte integer -- the number of channels (numbered 0, 1 , 2, etc)
  5. 1 byte character -- S or D to signify the data is single or double precision data (4 bytes or 8 bytes)
  6. a stream of width x height x channels x (4 or 8) bytes

Example. A 640 x 480 matrix of floats with R, G, and B "channels" would look something like

0000 0000 F00D FACE ! 4 byte magic number
0000 0000 0000 0280 ! hex for 640
0000 0000 0000 01E0 ! hex for 480
0000 0000 0000 0003 ! hex for 3
0053 ! ascii for 'S'
.... 1,228,800 bytes for channel 1 in row major format
.... 1,228,800 bytes for channel 2 in row major format
.... 1,228,800 bytes for channel 3 in row major format

Note : 640 x 480 x 4 = 1,228,800

Ideally my inputData.txt file could now look like this ...

images/thumbnails/test-1234.dat -1 -1 -1 -1 1
images/thumbnails/test-1235.dat 1 -1 -1 -1 -1
images/thumbnails/test-1236.dat -1 1 -1 -1 -1

Thanks.

"-p" option for pausing neural network won't work

I found out that the "-p" option does not work for me anymore in the latest release of neural2d. The program still continues to run the training routine. It works perfectly in the older release. Am I doing something wrong?

P.S: I'm running neural2d on Ubuntu.

Thanks in advance!

Cannot make project on Mac OS X

Make project on OS X gives the error below. Any ideas if this could be fixed?

OS X 10.9.5
gcc: stable 4.9.2 (bottled)

neural2d$ make
g++ -std=c++11 -pthread -g -O2 -Wall -Wextra -pedantic -Wno-missing-field-initializers -c neural2d-core.cpp -o neural2d-core.o
neural2d-core.cpp:115:46: error: use of undeclared identifier 'tanh'
float transferFunctionTanh(float x) { return tanh(x); }
                                             ^
neural2d-core.cpp:116:62: error: use of undeclared identifier 'tanh'
float transferFunctionDerivativeTanh(float x) { return 1.0 - tanh(x) * tanh(x); }
                                                             ^
neural2d-core.cpp:116:72: error: use of undeclared identifier 'tanh'
float transferFunctionDerivativeTanh(float x) { return 1.0 - tanh(x) * tanh(x); }
                                                                       ^
neural2d-core.cpp:119:63: error: use of undeclared identifier 'exp'
float transferFunctionLogistic(float x) { return 1.0 / (1.0 + exp(-x)); }
                                                              ^
neural2d-core.cpp:120:60: error: use of undeclared identifier 'exp'
float transferFunctionDerivativeLogistic(float x) { return exp(-x) / pow((exp(-x) + 1.0), 2.0); }
                                                           ^
neural2d-core.cpp:120:75: error: use of undeclared identifier 'exp'
float transferFunctionDerivativeLogistic(float x) { return exp(-x) / pow((exp(-x) + 1.0), 2.0); }
                                                                          ^
neural2d-core.cpp:136:50: error: use of undeclared identifier 'exp'
float transferFunctionGaussian(float x) { return exp(-((x * x) / 2.0)); }
                                                 ^
neural2d-core.cpp:137:65: error: use of undeclared identifier 'exp'
float transferFunctionDerivativeGaussian(float x) { return -x * exp(-(x * x) / 2.0); }
                                                                ^
neural2d-core.cpp:1134:79: error: use of undeclared identifier 'sqrt'
                    connections.back().weight = ((randomFloat() * 2) - 1.0) / sqrt(maxNumSourceNeurons);
                                                                              ^
9 errors generated.
make: *** [neural2d-core.o] Error 1

$ brew info gcc
gcc: stable 4.9.2 (bottled)

UML class diagram of neural2d software

Hi David, I generated a logical view of your neural2d software using IBM Rhapsody MDA Reverse Engineering tool capability. See the .jpeg image of the class diagram. It helps to visualize the software architecture.
neural2d_traian2david_classdiagram

.dat file samples

I am having problems trying to setup a .dat file sample list. Can you please provide me a actual sample of such a file?

I get from the docs that the file should start with such a header:

struct datHeader
{
uint32_t magic; // 0x6c89f6ad
uint32_t width; // >= 1
uint32_t height; // >= 1
uint32_t numChannels; // >= 1
uint32_t bytesPerElement; // 4 (single) or 8 (double) precision
uint32_t offsetToData; // >= sizeof(datHeader)
};

But after that , what should i do, just dump the values spaced or with comma, one after an other below the header? Should i replace magic,width,height, numChannels, bytesPerElement and offsetToData with actual values?

Can you provide an actual example so i can figure out what you mean?

The inputData.txt will contain similar info like it does when using .bmp files?

Please help
Thank you!

Error in a comment.

Hello,

I think there is a mistake in one of your comments.

The comment is in the file neural2d-core.cpp

Line 864

// The error gradient of a hidden-layer neuron is equal to the derivative
// of the activation function of the hidden layer evaluated at the
// local output of the neuron times the sum of the product of
// the primary outputs times their associated hidden-to-output weights.

on the last line of the comment, shouldn't it be "the primary gradient" ?

Thanks !

Webserver on Windows

I'm working on making the Webserver work on Windows. I like working inside the Visual C++ 2015 environment. Here's some initial code if you can use it. Still needs more testing.

/*
webserver.cpp -- embedded web server for the GUI for the neural2d program.
David R. Miller, 2014, 2015
For more information, see neural2d.h and https://github.com/davidrmiller/neural2d .
*/

// C Standard includes

include

include

include

// C++ Standard includes

include

include

include

include

include

include

// POSIX Includes

ifndef WIN32

include <unistd.h> // POSIX, for read(), write(), close()

include <sys/types.h> // For setsockopt() and SO_REUSEADDR

endif

include "webserver.h"

int readSocket(int fd,void buf,size_t count)
{
return recv(fd, (char
) buf, count, 0);
}

int writeSocket(int fd,const char *buf,size_t count)
{
return send(fd, buf,count,0);
}

void closeSocket(SOCKET socketFd)
{

ifdef WIN32

closesocket(socketFd);

else

close(socketFd);

endif

}

void closeIt(SOCKET socketFd)
{

ifdef WIN32

shutdown(socketFd,SD_BOTH);
closesocket(socketFd);

else

shutdown(socketFd,SHUT_RDWR);
close(socketFd);

endif

}

namespace NNet {

// *********************************** Web server ***********************************

WebServer::WebServer(void)
{

ifdef WIN32

WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD(2,2);

err = WSAStartup(wVersionRequested,&wsaData);
if(err != 0)
{
    /* Tell the user that we could not find a usable */
    /* WinSock DLL.                                  */
    //      TRACE("No socket dll");
}

endif

socketFd = -1;
firstAccess = true;        // Used to detect when the first HTTP GET arrives
initializeHttpResponse();

}

WebServer::~WebServer(void)
{
stopServer();
}

void WebServer::stopServer(void)
{
if (socketFd != -1) {
//std::cout << "Closing webserver socket..." << std::endl;
closeIt(socketFd);
socketFd = -1;
}
}

// The web server runs in a separate thread. It receives a GET from the browser,
// extracts the message (e.g., "eta=0.1") and appends it to a shared message
// queue. Periodically, the Net object will pop messages and respond to them
// by constructing a parameter block (a string) and calling a function to
// send the http response.
//
void WebServer::initializeHttpResponse(void)
{
// Keep appending lines to firstPart until we get the line with the sentinel:
std::ifstream httpTemplate("http-response-template.txt");
if (!httpTemplate.is_open()) {
firstPart = "Cannot open file "http-response-template.txt"; web server is disabled.\r\n";
return;
}

firstPart = "";
secondPart = "";

int part = 1; // The lines before the sentinel goes into firstPart

while (httpTemplate.good()) {
    std::string line;
    std::getline(httpTemplate, line);

    // Add \r\n; the \r may already be there:

    if (line[line.length() - 1] == '\r') {
        line.append("\n");
    } else {
        line.append("\r\n");
    }

    // Save the line:

    if (part == 1) {
        firstPart.append(line);
    } else {
        secondPart.append(line);
    }

    // If this is the line with the sentinel, we'll change to secondPart for the rest:

    if (line.find("Parameter block") != std::string::npos) {
        part = 2;
    }
}

}

// This sends a 404 Not Found reply
//
void WebServer::replyToUnknownRequest(int httpConnectionFd)
{
std::string response = "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n";

send(httpConnectionFd, response.c_str(), response.length(), 0);
closeIt(httpConnectionFd);

/*
shutdown(httpConnectionFd, SHUT_RDWR);
close(httpConnectionFd);
*/
}

// Look for "POST /" or "GET /?" followed by a message or POST.
// If this is the first GET or POST we receive, we'll treat it as if it were
// "GET / " of the root document.
//
void WebServer::extractAndQueueMessage(std::string s, int httpConnectionFd, MessageQueue &messages)
{
struct Message_t msg;
size_t pos;

if (firstAccess) {
    msg.text = ""; // Causes a default web form html page to be sent back
    firstAccess = false;
} else if ((pos = s.find("POST /")) != std::string::npos) {
    // POST
    pos = s.find("\r\n\r\n");
    assert(pos != std::string::npos);
    msg.text = s.substr(pos + 4);
} else if ((pos = s.find("GET /?")) != std::string::npos) {
    // GET with an argument
    std::string rawMsg = s.substr(pos + 6);
    pos = rawMsg.find(" ");
    assert(pos != std::string::npos);
    msg.text = rawMsg.substr(0, pos);
} else if ((pos = s.find("GET /")) != std::string::npos) {
    // GET without an argument
    msg.text = "";
} else {
    // Unknown HTTP request
    replyToUnknownRequest(httpConnectionFd);
    return;
}

//std::cout << "msg.text = " << msg.text << std::endl;

msg.httpResponseFileDes = httpConnectionFd;
messages.push(msg);

}

void WebServer::start(int portNumber_, MessageQueue &messages)
{
portNumber = portNumber_;
std::thread webThread(&WebServer::webServerThread, this, portNumber, std::ref(messages));
webThread.detach();
}

// The argument parameterBlock needs to be passed by value because it comes from
// a different thread:
//
void WebServer::sendHttpResponse(std::string parameterBlock, int httpResponseFileDes)
{
std::string response = firstPart + parameterBlock + secondPart;
const char *buf = response.c_str();

size_t lenToSend = response.length();
while (lenToSend > 0) {
    int numWritten = writeSocket(httpResponseFileDes, buf, lenToSend);
    if (numWritten < 0) {
        break; // Serious error
    }
    lenToSend -= numWritten;
    buf += numWritten;
}

closeIt(httpResponseFileDes);

/*
shutdown(httpResponseFileDes, SHUT_RDWR);
close(httpResponseFileDes);
*/
}

void WebServer::webServerThread(int portNumber, MessageQueue &messages)
{
static const struct sockaddr_in zero_sockaddr_in = { 0 };
struct sockaddr_in stSockAddr = zero_sockaddr_in;
char buff[2048];

socketFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

if (-1 == socketFd) {
    std::cerr << "Cannot create socket for the web server interface" << std::endl;
    //exit(1);
    return;
}

stSockAddr.sin_family = AF_INET;
stSockAddr.sin_port = htons(portNumber);
stSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);

// Set SO_REUSEADDR so we can bind the port even if there are
// connections in the TIME_WAIT state, thus allowing the webserver
// to be restarted without waiting for the TIME_WAIT to expire.

int optval = 1;

ifndef WIN32

setsockopt(socketFd,SOL_SOCKET,SO_REUSEADDR,NULL, &optval,sizeof(optval));

else

setsockopt(socketFd,SOL_SOCKET,SO_REUSEADDR, (char*) &optval,sizeof(optval));

endif

if (-1 == bind(socketFd, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr))) {
    std::cerr << "Cannot bind socket for the web server interface\n\n" << std::endl;
    closeSocket(socketFd);
    exit(1);
    return;
}

if (-1 == listen(socketFd, 10)) {
    std::cerr << "Web server network failure" << std::endl;
    closeSocket(socketFd);
    //exit(1);
    return;
}

//std::cout << "Web server started." << std::endl;

while (true) {
    int httpConnectionFd = accept(socketFd, NULL, NULL);

    if (0 > httpConnectionFd) {
        std::cerr << "Webserver failed to accept connection" << std::endl;
        closeSocket(socketFd);
        //exit(1);
        return;
    }

    uint32_t numChars = readSocket(httpConnectionFd, buff, sizeof buff - 1);

    if (numChars > 0) {
        assert(numChars < sizeof buff);
        buff[numChars] = '\0';
        extractAndQueueMessage(buff, httpConnectionFd, messages);
    }
}

closeSocket(socketFd);

}

} /* end namespace NNet */

Enhancement: Convolution networking

The purpose of this issue is to discuss implementing convolution neural networking in neural2d. Comments are appreciated.

Neural2d currently implements convolution filtering, but not convolution networking.

Definitions


A convolution filter is an image processing operation such as edge detection, low pass filtering (smoothing), etc. In neural2d, any layer of neurons can be configured as a convolution filter. In a convolution filter layer, all the neurons share the same convolution kernel, which is just a matrix of weights. The weights do not undergo training; they remain constant throughout the life of the net.

A convolution neural network is somewhat similar to convolution filtering, except that the kernel weights undergo training, and the layer is replicated N times so that N separate kernels can be trained.

To be more precise, when we speak of a convolution neural net, we are usually talking about a regular neural net with one or more convolution network layers that form special subnets within the larger neural network.

It's unfortunate that the terms are so similar -- "convolution filtering" vs. "convolution networking." Is there a better terminology we can use?


Purpose

The purpose of convolution neural networking is to uncover a number of image features during training that help with pattern recognition. Commonly, image features are little patches of pixels that look like bits of edges, corners, or other shapes. Ideally, all the features found during training are highly uncorrelated, forming a set of orthogonal mathematical bases that can help partition the classification space.

The output from one convolution network layer can become the input to another convolution network layer, so that each convolution stage can find higher level features.

Implementation plan

Here are the minimum required changes to implement convolution neural networking in neural2d:

  • We would need to devise a syntax to specify a convolution network in the topology configuration file.
  • Expand the Layer structure to include the concept of layer depth.
  • The backprop code would need to update the kernel weights in each convolution networking layer.

Additionally, it would be useful to implement the following features:

  • Rectified linear units (ReLU) -- this is a type of transfer function that goes with convolution networking like chocolate and peanut butter.
  • Pooling -- this is the reduction of the outputs of a regular layer, or convolution network layer into a new layer with fewer neurons, by passing a windowed filter (max or avg) over the source layer.

These sub-tasks are discussed below.

Topology configuration file syntax

A convolution filter layer can be thought of as a degenerate convolution network layer with a depth of 1, and no weight updates during backprop.

The existing topology configuration syntax for convolution filtering could be expanded to allow a depth parameter. For example, for a convolution network layer of 10 kernels:

 input size 32x32
 layerConv size 10*32x32 from input convolve 2x2

The 10 * specifies that this is a convolution network layer with 10 kernels instead of a convolution filter layer with a single kernel. The 2x2 is the size of the convolution kernels to be trained. Specifying the size of the convolution kernels (instead of the curly brace syntax) implies that these kernels are to be included in backprop weight learning.

Expand the Layer data structure

Currently a single layer contains a two-dimensional set of neurons. That can be expanded to implement a layer depth. If a layer is configured as a convolution network layer, then the layer instance will be replicated N times to train N kernels. We'll refer to as the layer depth. (Regular layers of neurons and convolution filter layers have a default depth of 1.)

Adding a depth dimension to the layer structure will make it a little more complicated to loop over neurons during forward or back propagation. Perhaps the Layer class should provide a variety of iterators to hide those details. That would be a nice little refactoring project that could be done before the other changes.

Backprop weight updates

Currently, neural2d does not update input weights on layers flagged as convolution filter layers. For convolution network layers, we would need to add a backprop function to update the weights in each convolution network layer.

Rectified linear units

Here is one possible ReLU transfer function and its derivative:

 f(x) = ln(1 + exp(x))
 f'(x) = 1 / (1 + exp(-x))

Care must be given to the derivative at zero.

This would be just another transfer function specified by the "tf" parameter in the topology config file.

Pooling the output

To pool the output of a convolution network layer, define a new layer smaller than the convolution layer with the convolution layer as the input, and give it the new "pool" parameter. The pool parameter takes a pooling method (max or avg), and a window size over which to apply the pooling method:

 layerPool size 10*8x8 from layerConv pool max 2x2

A pooling layer may also take its input from a regular layer of depth 1.

Example

Following is an example of a convolution network pipeline using the syntax proposed above:

input size 64x64
layerConvolve1 size 10*64x64 from input convolve 7x7
layerPool1 size 10*16x16 from layerConvolve1 pool max 4x4
layerConvolve2 size 10*16x16 from layerPool1 convolve 5x5
layerPool2 size 10*8x8 from layerConvolve2 pool max 2x2
layerReduce size 10 from layerPool2 pool
layerHidden size 10 from layerReduce
output size 3 from layerHidden

Visual Studio 2013 or above version is required to compile the neural2d-master source code

Due to lack of the support for the required C++ 11 features on the part of the C++ compilers of Microsoft Visual Studio 2012 or prior versions on the Windows platform, the neural2d-master source code of the neural2d project must be generated in CMake specifying Visual Studio 2013 or above versions. Otherwise, many compiling errors are expected inside the Visual Studio.

strange output, where Outputs: 0.409617 is considered Correct when expected value is 1

Hi,
I am trying to use neural2d in my thesis project on Voice Activity Detection. I have an input file with more than a million lines (13 input cepstral coefficients, one expected value Voice or Silence – 1/0).
When training the net I noticed strange output, where Outputs: 0.409617 is considered Correct when expected value is 1. It seems to me strange. How the correct or wrong output is calculated.
Thanks a lot

Pass #2600000:
Outputs: 0.409617
Expected 1 Correct
eta=7.00649e-43 Net error = 0.174276, running average = 0.0499153

Pass #2610000:
Outputs: 0.912001
Expected 1 Correct
eta=7.00649e-43 Net error = 0.00387187, running average = 0.0384916

Pass #2620000:
Outputs: 0.533725
Expected 0 Wrong
eta=7.00649e-43 Net error = 0.142431, running average = 0.0484277

MVSC 2015 compile error

Building under MVSC 2015 causes a compile error :
Error C2039 'back_inserter': is not a member of 'std' neural2d-core
solution:
in neural2d.h , the following header
#include
should be added

How do I input custom 2D values?

I'm currently using numerical inputs as training data, but I can only input 1-dimensional values in the following format:
{x x x x x} y y
as explained in the documentation.

Is there a way to directly enter 2D data as well? Just wondering!

Thanks :)

Matrix transpose bug in Net::parseMatrixSpec

Thanks to Michael Whidden for reporting the following:

I noticed in Net::parseMatrixSpec that the code that is documented as doing a matrix transpose of the convolution matrix isn't actually doing so. I changed it to this to get it to work, but I did not actually test running a net with a convolution layer to make sure the "working" transpose doesn't end up causing some downstream issues.

    for (unsigned x = 0; x < mat.size(); ++x) {
        if (x == 0) {
            firstRowSize = mat[x].size(); // Remember the first row size
        } else if (mat[x].size() != firstRowSize){
            cout << "Error: in convolution matrix in topology config file, inconsistent matrix row size" << endl;
            throw("Error in topology config file: inconsistent row size in convolve matrix spec");
        }
    }
    for(unsigned y=0; y < firstRowSize; ++y){
        convMat.push_back(vector<float>());
        for (unsigned x = 0; x < mat.size(); ++x) {
            convMat.back().push_back(mat[x][y]);
        }
    }

neural2d-gui.py comm channel fails on Windows

The GUI communicates commands to the neural2d program using a named pipe on Linux, which works well. In Windows, the comm channel is a regular file (named neural2d-command), opened as an ifstream, but this isn't working. In Net::doCommand() (in neural2d-core.cpp), incoming commands are not received correctly.

Question about colors

This is not so much an 'issue' as a question about how this neural net works, and forgive my ignorance if this was mentioned in your documentation. Since this is a 2D NN, if I were to imagine the input layer as one dimension being input pixels along the x axis and the other being input pixels along the y axis, how is the color information managed? Do you assign a specific range (between, say, -1 to 1) to a single channel?

Thanks in advance!

Madhu

Get neural2d working in Microsoft Visual Studio

Bob Zigon suggests: Get neural2d working in Microsoft Visual Studio.

The biggest hurdle is the bit of networking used to support the webserver GUI interface. Apparently Microsoft does not support the POSIX standard very well for networking, and a few things would have to be recoded in Microsoft-specific terms.

Switch param names in neural2d.h

The to/from layer parameter names in neural2d.h are switched from the actual parameter names in neural2d-core.cpp, which may lead some (like me) to confusion.

void createNeurons(Layer &layerFrom, Layer &layerTo, layerParams_t &params);
void connectNeuron(Layer &layerFrom, Layer &layerTo, Neuron &neuron,
                   uint32_t nx, uint32_t ny, layerParams_t &params);

vs.

void Net::createNeurons(Layer &layerTo, Layer &layerFrom, layerParams_t &params)
void Net::connectNeuron(Layer &layerTo, Layer &fromLayer, Neuron &neuron,
    uint32_t nx, uint32_t ny, layerParams_t &params)

Are the TF derivatives correctly implemented?

Hello David.

I'm having doubts about the implementation of transfer functions in Neural2D, specifically - their derivatives. So far I've only analyzed and used the TanH and Logistic TFs, but let's get to it.

First of, when feeding forward you call the TF and store it's output for x in the neuron output, so far correct. What I'm having issues with are the derivatives. While they're mathematically correct, I think the code logic might be flawed here. When doing backward propagation gradient calculation (I'm referring to regular layers), you take the said neuron output (which is at that time "tanh(x)" from feeding forward) and use it as a parameter for the TFs derivative, which is also a full math equivalent (so you're calculating: "1.0f - tanh(tanh(x)) * tanh(tanh(x))" - pretty much the same thing happens for the Logistic TF).

That's what I have trouble understanding. Is it a bug that the gradient is double-functioned ("tanh(tanh(x))") or should it be like that on purpose? Is so, that why? Shouldn't the derivatives include the fact, that the basic function has already been called (making tanh's code derivative like: "1.0f - x * x")?

EDIT: I did an experiment for the XOR function. The original code needs over 8000 iterations to solve the problem. After reimplementing the TanH TF derivative as mentioned above, it completed the calculations in 805 iterations only and got a lot more "Correct" outputs than in the original code (I know they're used in classification, but I'm just mentioning it).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.