BotBrains
BotBrains is a set of artificial learning tools to automate an Arduino-based robot.
Its been built as part of an educational workshop on artificial learning specifically for International Nodebots Day.
This material here is very basic and aimed more at communicating the core concept of a neural network through practice than dealing with all the theoretical stuff that is available out there.
To read more about how this library came to be see the article on Asynchronous Neural Networks on my blog.
Interact with your robot brains in 3D.
The key aspect of BotBrains is the ability to watch signals travel across your robot's neural network in 3D, and train it with positive and negative reinforcement.
Quick start
You need NodeJS installed, version 6 or above.
$ mkdir my-bot && cd my-bot$ npm install botbrains$ cd node_modules/botbrains$ npm start
The above will perform a quick test with a random visualization. For a full test you need to rig up a robot.
Proper setup
You should be adding this to an existing robot project such as johnny-five.
Here is a longer example:
$ mkdir my-bot && cd my-bot$ npm install johnny-five$ npm install botbrains
robot.js
const five = ;const botbrains = ; const board = port: processargv2 || '' ; board;
Then run it!
$ node robot.js
API :: NeuralNetwork
NeuralNetwork is a class in the botbrains module and can be loaded in the following ways:
; // ES6 const NeuralNetwork = NeuralNetwork; // Node, CommonJS const NeuralNetwork = window || thisbotbrainsNeuralNetwork; // Browser, in global context
new NeuralNetwork(size, opts)
Generates a neural network.
size
: The number of neurons in the neural networkopts
: A map of settings for the network.shape
: Choice of 'drum', 'tube', 'ring', 'ball', 'sausage', 'snake', or any other in NetworkShaper.js. Defaults to 'drum'..shaper
: The shaper function used for giving shape to the network. If available will ignore.shape
..connectionsPerNeuron
: Average synapses per neuron. Defaults to4
..signalFireThreshold
: Threshold (between 0 and 1) needed to trigger onward neurons. Defaults to0.3
..signalSpeed
: Speed in neurons per second. Defaults to20
..startingWeight
: Starting weight per synapse. Defaults tosignalFireThreshold(/3 x connectionsPerNeuron)
..neuronRecovery
: Neuron recovery as fraction ofsignalSpeed
. Defaults to1/5
..learningRate
: Max increase/decrease to connection strength when learning. Defaults to0.05
..learningPeriod
: Milliseconds in the past on which learning applies. Defaults to20 * 1000
ms.
For example, to create a network of 100 neurons using all default options:
let network = 100;
To create a ring-shaped network of 100 neurons with double the speed and learning rate.
let network = 1000 shape: 'ring' signalSpeed: 40 learningRate: 03 ;
If a String
is passed in as the opts
parameter, its interpreted as the network shape.
let network = 100 'ring';
If a Function
is passed as the opts
parameter, its interpreted as the shaper function, see examples in NetworkShaper.js.
let network = 100 Math;
network.input(label [, neurons=1])
Creates an input into the network.
label
: A label used to visually identify the neurons involved.neurons
: OptionalNumber
of neurons involved, or array of numbers (Number[]
) defining the network nodes that are involved in the input.
Returns:
Function(signal 0-1)
: A function that accepts incoming signals (a float between 0 and 1).
Usage:
var input1 = networkinput'Microphone' // 1 x Neuron assigned automaticallysensor; var input2 = networkinput'LightSensor (L)' 3 // How many neurons? => 3 sensor; var input3 = networkinput'LightSensor (R)' 101112 // Which neurons? => 10, 11 & 12sensor;
network.output(label [, neurons=1])
Returns an EventEmitter with 2 events: data
and change
.
label
: A label used to visually identify the neurons involved.neurons
: OptionalNumber
of neurons involved, or array of numbers (Number[]
) defining the network nodes that are involved in the input.
Event: data
:
Fires whenever there is data to output.
The event handler function will receive the following arguments.
data
: A numeric floating point value between 0 and 1, containing the strength of the outgoing signal.
network // 1 x Neuron assigned automatically ; network // How many neurons? => 3 ; network // Which neurons? => 6, 7 & 8 ;
Event: change
:
An event that fires whenever there is a change in the outgoing data.
The event handler function will receive the following arguments.
data
: A numeric floating point value between 0 and 1, containing the strength of the outgoing signal.last
: The previous value output.diff
: The difference betweenlast
anddata
.
network ;
network.join(network, at, surfaceArea)
Merges a network into another network, or into itself.
const network = 100 'ball';network; // join on the middle, using 10% of nodes.network; // join on itself
Shaper Function
A shaper is a function that determines the shape of the network by returning the onward connections made by each neuron.
For example, if a neuron is connected to other neurons at random, the final shape of the network will be a ball. If its connected to nearby neurons the shape will be more of a snake or cylinder. If neurons close to the end are linked to neurons at the beginning, the end product will be more of a ring or a doughnut.
The shaper function is executed once for every synapse in the network. If there are 10 nodes, and 4 synapses per node, it will fire 40 times to determine the onward neuron in each of those synapses.
A shaper function has the following inputs:
count
: The total number of nodes in the network. In other words, in a network of 10 neurons, this will be10
. Useful for linking up the end of the network back to its beginning or for discarding links outside the network.index
: The position of the originating neuron inside thenodes
array. In a network of 10 nodes, the first node is0
, the last node is9
, so a value of9
means the last neuron in the network.connectionCount
: A neuron has several connections (synapses) originating from it. For example if the neuron has 4 connections, this will be 4.connectionIndex
: The position in the array of the connection currently being made. In other words, if there are 4 connections (synapses) in the originating neuron, the shaper function will execute 4 times for it, with aconnectionIndex
value of0
to3
accordingly.
And returns:
target
: The destination position of an onward neuron (for connecting to it). In a network of 10 nodes, when we are mapping a neuronindex
of0
(the first node) andconnectionIndex
of0
(the first synapse), atarget
of9
means that connection is made towards the last neuron.
Bear in mind that since the shaper function will be executed multiple times per neuron to determine the onward neuron for each connection. You will want these to connect to different onward neurons. This can be done either choosing an onward target
at random, or by using the synapseIndex
argument to calculate the target
neuron in a deterministic manner.
Here is an example of simple shaper function:
// Random ball shape100 Math;
Another more involved example:
// Ring shapeconst network = 100 ring; { const width = count / 12; const forwardBias = Math; const target = index + forwardBias; if target < count return target; return target - count; // link to beginning}
There are more examples in NetworkShaper.js.
Why does shape matter?
The Neural Network model used for botbrains is asynchronous. Signal propagate across the network in the same manner as they would in an animal brain, one neuron at a time. Different shapes matter because they create resonance and oscillation patterns that are important for producing particular outputs to inputs in a time-dependent manner.