Skip to content

Commit

Permalink
Merge pull request #5 from will-newmarch/release-0.4.0
Browse files Browse the repository at this point in the history
Release 0.4.0
  • Loading branch information
will-newmarch authored Jul 13, 2019
2 parents ecb9348 + a1f300a commit 030cbeb
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 60 deletions.
50 changes: 16 additions & 34 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "intuitive-neural-network",
"version": "0.3.0",
"version": "0.4.0",
"description": "An intuitive, object-orientated approach to a Neural Network library.",
"main": "src/Network.js",
"scripts": {
Expand All @@ -26,5 +26,8 @@
"homepage": "https://github.com/will-newmarch/intuitive-neural-network#readme",
"devDependencies": {
"jest": "^24.5.0"
},
"dependencies": {
"fs": "0.0.1-security"
}
}
6 changes: 6 additions & 0 deletions src/Layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ class Layer {
}
return totalError;
}

toObject() {
return {
neurons: this.neurons.map(n => n.toObject())
};
}
};

module.exports = Layer;
16 changes: 10 additions & 6 deletions src/Network.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const fs = require('fs');

const Layer = require('./Layer.js');
const Input = require('./neuron/Input.js');
const Hidden = require('./neuron/Hidden.js');
Expand Down Expand Up @@ -175,14 +177,16 @@ class Network {
return this;
}

/**
* Log the network in a human readable fashion
*/
log(synapses = false) { // This could definitely be improved...
this.layers.map(l => {
l.neurons.map(n => console.log(n.label,n.outputs.map(s => s.weight)));
toJSON() {
return JSON.stringify({
layers: this.layers.map(l => l.toObject())
});
}

save(filename,callback) {
const model = this.toJSON();
fs.writeFile(filename, model, callback);
}
};

module.exports = Network;
10 changes: 10 additions & 0 deletions src/Synapse.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ class Synapse {
applyError(learningRate) {
this.weight -= learningRate * this.error;
}

toObject() {
return {
type: this.constructor.name,
label: this.label,
inputLabel: this.input.label,
outputLabel: this.output.label,
weight: this.weight
}
}
};

module.exports = Synapse;
7 changes: 0 additions & 7 deletions src/neuron/Hidden.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,6 @@ class Hidden extends Neuron {
*/
constructor(label) {
super(label);

this.inputs = []; // Reference to the input synapses
this.inputSignals = []; // Array to collect signals from inputs (when firing)
this.outputs = []; // Reference to the output synapses
this.outputSignals = []; // Array to collect signals FROM outputs (when backpropagating)
this.activation = 0; // Activation of the neuron
this.error = 0; // Error to be persisted (not actually used in Input neuron, more kept for interest)
}

/**
Expand Down
5 changes: 0 additions & 5 deletions src/neuron/Input.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@ class Input extends Neuron {
*/
constructor(label) {
super(label);

this.outputs = []; // Reference to the output synapses
this.outputSignals = []; // Array to collect signals FROM outputs (when backpropagating)
this.activation = 0; // Activation of the neuron
this.error = 0; // Error to be persisted (not actually used in Input neuron, more kept for interest)
}

/**
Expand Down
13 changes: 13 additions & 0 deletions src/neuron/Neuron.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ class Neuron {
*/
constructor(label) {
this.label = label; // Human readable label
this.inputs = []; // Reference to the input synapses
this.inputSignals = []; // Array to collect signals from inputs (when firing)
this.outputs = []; // Reference to the output synapses
this.outputSignals = []; // Array to collect signals FROM outputs (when backpropagating)
this.activation = 0; // Activation of the neuron
this.error = 0; // Error to be persisted (not actually used in Input neuron, more kept for interest)
this.setActivationType('sigmoid'); // Neuron activation function (defaulting to sigmoid)
Expand Down Expand Up @@ -46,6 +50,15 @@ class Neuron {
backPropagate(backSignal) {
throw 'backPropagate method must be overidden!';
}

toObject() {
return {
type: this.constructor.name,
label: this.label,
activationType: this.activationType,
outputs: this.outputs.map(o => o.toObject())
};
}
};

module.exports = Neuron;
6 changes: 0 additions & 6 deletions src/neuron/Output.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,6 @@ class Output extends Neuron {
*/
constructor(label) {
super(label);

this.inputs = []; // Reference to the input synapses
this.inputSignals = []; // Array to collect signals from inputs (when firing)
this.activation = 0; // Activation of the neuron
this.error = 0; // Error to be persisted and applied by network

}

/**
Expand Down
27 changes: 27 additions & 0 deletions tests/model-to-json.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use strict';

const Network = require('../src/Network.js');

test('library can convert a model to JSON', () => {

// Build the network...
var network = new Network({
layers: [2,2,1],
bias: false
});

// Hard-code weights to create exact JSON
network.layers.map(l => {
l.neurons.map(n => {
n.outputs.map(o => {
o.weight = 0.5;
});
});
});

const expectedJSON = '{"layers":[{"neurons":[{"type":"Input","label":"input-0","activationType":"sigmoid","outputs":[{"type":"Synapse","label":"input-0--hidden-0","inputLabel":"input-0","outputLabel":"hidden-0","weight":0.5},{"type":"Synapse","label":"input-0--hidden-1","inputLabel":"input-0","outputLabel":"hidden-1","weight":0.5}]},{"type":"Input","label":"input-1","activationType":"sigmoid","outputs":[{"type":"Synapse","label":"input-1--hidden-0","inputLabel":"input-1","outputLabel":"hidden-0","weight":0.5},{"type":"Synapse","label":"input-1--hidden-1","inputLabel":"input-1","outputLabel":"hidden-1","weight":0.5}]}]},{"neurons":[{"type":"Hidden","label":"hidden-0","activationType":"sigmoid","outputs":[{"type":"Synapse","label":"hidden-0--output-0","inputLabel":"hidden-0","outputLabel":"output-0","weight":0.5}]},{"type":"Hidden","label":"hidden-1","activationType":"sigmoid","outputs":[{"type":"Synapse","label":"hidden-1--output-0","inputLabel":"hidden-1","outputLabel":"output-0","weight":0.5}]}]},{"neurons":[{"type":"Output","label":"output-0","activationType":"identity","outputs":[]}]}]}';

expect(network.toJSON()).toBe(expectedJSON);

});

28 changes: 28 additions & 0 deletions tests/saves-models-to-file.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict';

const fs = require('fs');

const Network = require('../src/Network.js');

test('library can convert a model to JSON', (done) => {

// Build the network...
var network = new Network({
layers: [2,2,1],
bias: false
});

const filename = './temp.json';

network.save(filename,() => {

expect(fs.existsSync(filename)).toBe(true);

fs.unlinkSync(filename);

done();

});

});

2 changes: 1 addition & 1 deletion xor-problem.test.js → tests/xor-problem.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

const Network = require('./src/Network.js');
const Network = require('../src/Network.js');

test('library solves XOR problem', () => {

Expand Down

0 comments on commit 030cbeb

Please sign in to comment.