整理桌面

This commit is contained in:
2022-04-10 00:37:53 +08:00
parent 82e3f2623f
commit e25c8bb318
728 changed files with 986384 additions and 16 deletions

369
node_modules/neataptic/src/architecture/architect.js generated vendored Normal file
View File

@@ -0,0 +1,369 @@
/* Import */
var methods = require('../methods/methods');
var Network = require('./network');
var Group = require('./group');
var Layer = require('./layer');
var Node = require('./node');
/*******************************************************************************
architect
*******************************************************************************/
var architect = {
/**
* Constructs a network from a given array of connected nodes
*/
Construct: function (list) {
// Create a network
var network = new Network(0, 0);
// Transform all groups into nodes
var nodes = [];
var i;
for (i = 0; i < list.length; i++) {
let j;
if (list[i] instanceof Group) {
for (j = 0; j < list[i].nodes.length; j++) {
nodes.push(list[i].nodes[j]);
}
} else if (list[i] instanceof Layer) {
for (j = 0; j < list[i].nodes.length; j++) {
for (var k = 0; k < list[i].nodes[j].nodes.length; k++) {
nodes.push(list[i].nodes[j].nodes[k]);
}
}
} else if (list[i] instanceof Node) {
nodes.push(list[i]);
}
}
// Determine input and output nodes
var inputs = [];
var outputs = [];
for (i = nodes.length - 1; i >= 0; i--) {
if (nodes[i].type === 'output' || nodes[i].connections.out.length + nodes[i].connections.gated.length === 0) {
nodes[i].type = 'output';
network.output++;
outputs.push(nodes[i]);
nodes.splice(i, 1);
} else if (nodes[i].type === 'input' || !nodes[i].connections.in.length) {
nodes[i].type = 'input';
network.input++;
inputs.push(nodes[i]);
nodes.splice(i, 1);
}
}
// Input nodes are always first, output nodes are always last
nodes = inputs.concat(nodes).concat(outputs);
if (network.input === 0 || network.output === 0) {
throw new Error('Given nodes have no clear input/output node!');
}
for (i = 0; i < nodes.length; i++) {
let j;
for (j = 0; j < nodes[i].connections.out.length; j++) {
network.connections.push(nodes[i].connections.out[j]);
}
for (j = 0; j < nodes[i].connections.gated.length; j++) {
network.gates.push(nodes[i].connections.gated[j]);
}
if (nodes[i].connections.self.weight !== 0) {
network.selfconns.push(nodes[i].connections.self);
}
}
network.nodes = nodes;
return network;
},
/**
* Creates a multilayer perceptron (MLP)
*/
Perceptron: function () {
// Convert arguments to Array
var layers = Array.prototype.slice.call(arguments);
if (layers.length < 3) {
throw new Error('You have to specify at least 3 layers');
}
// Create a list of nodes/groups
var nodes = [];
nodes.push(new Group(layers[0]));
for (var i = 1; i < layers.length; i++) {
var layer = layers[i];
layer = new Group(layer);
nodes.push(layer);
nodes[i - 1].connect(nodes[i], methods.connection.ALL_TO_ALL);
}
// Construct the network
return architect.Construct(nodes);
},
/**
* Creates a randomly connected network
*/
Random: function (input, hidden, output, options) {
options = options || {};
var connections = options.connections || hidden * 2;
var backconnections = options.backconnections || 0;
var selfconnections = options.selfconnections || 0;
var gates = options.gates || 0;
var network = new Network(input, output);
var i;
for (i = 0; i < hidden; i++) {
network.mutate(methods.mutation.ADD_NODE);
}
for (i = 0; i < connections - hidden; i++) {
network.mutate(methods.mutation.ADD_CONN);
}
for (i = 0; i < backconnections; i++) {
network.mutate(methods.mutation.ADD_BACK_CONN);
}
for (i = 0; i < selfconnections; i++) {
network.mutate(methods.mutation.ADD_SELF_CONN);
}
for (i = 0; i < gates; i++) {
network.mutate(methods.mutation.ADD_GATE);
}
return network;
},
/**
* Creates a long short-term memory network
*/
LSTM: function () {
var args = Array.prototype.slice.call(arguments);
if (args.length < 3) {
throw new Error('You have to specify at least 3 layers');
}
var last = args.pop();
var outputLayer;
if (typeof last === 'number') {
outputLayer = new Group(last);
last = {};
} else {
outputLayer = new Group(args.pop()); // last argument
}
outputLayer.set({
type: 'output'
});
var options = {};
options.memoryToMemory = last.memoryToMemory || false;
options.outputToMemory = last.outputToMemory || false;
options.outputToGates = last.outputToGates || false;
options.inputToOutput = last.inputToOutput === undefined ? true : last.inputToOutput;
options.inputToDeep = last.inputToDeep === undefined ? true : last.inputToDeep;
var inputLayer = new Group(args.shift()); // first argument
inputLayer.set({
type: 'input'
});
var blocks = args; // all the arguments in the middle
var nodes = [];
nodes.push(inputLayer);
var previous = inputLayer;
for (var i = 0; i < blocks.length; i++) {
var block = blocks[i];
// Init required nodes (in activation order)
var inputGate = new Group(block);
var forgetGate = new Group(block);
var memoryCell = new Group(block);
var outputGate = new Group(block);
var outputBlock = i === blocks.length - 1 ? outputLayer : new Group(block);
inputGate.set({
bias: 1
});
forgetGate.set({
bias: 1
});
outputGate.set({
bias: 1
});
// Connect the input with all the nodes
var input = previous.connect(memoryCell, methods.connection.ALL_TO_ALL);
previous.connect(inputGate, methods.connection.ALL_TO_ALL);
previous.connect(outputGate, methods.connection.ALL_TO_ALL);
previous.connect(forgetGate, methods.connection.ALL_TO_ALL);
// Set up internal connections
memoryCell.connect(inputGate, methods.connection.ALL_TO_ALL);
memoryCell.connect(forgetGate, methods.connection.ALL_TO_ALL);
memoryCell.connect(outputGate, methods.connection.ALL_TO_ALL);
var forget = memoryCell.connect(memoryCell, methods.connection.ONE_TO_ONE);
var output = memoryCell.connect(outputBlock, methods.connection.ALL_TO_ALL);
// Set up gates
inputGate.gate(input, methods.gating.INPUT);
forgetGate.gate(forget, methods.gating.SELF);
outputGate.gate(output, methods.gating.OUTPUT);
// Input to all memory cells
if (options.inputToDeep && i > 0) {
let input = inputLayer.connect(memoryCell, methods.connection.ALL_TO_ALL);
inputGate.gate(input, methods.gating.INPUT);
}
// Optional connections
if (options.memoryToMemory) {
let input = memoryCell.connect(memoryCell, methods.connection.ALL_TO_ELSE);
inputGate.gate(input, methods.gating.INPUT);
}
if (options.outputToMemory) {
let input = outputLayer.connect(memoryCell, methods.connection.ALL_TO_ALL);
inputGate.gate(input, methods.gating.INPUT);
}
if (options.outputToGates) {
outputLayer.connect(inputGate, methods.connection.ALL_TO_ALL);
outputLayer.connect(forgetGate, methods.connection.ALL_TO_ALL);
outputLayer.connect(outputGate, methods.connection.ALL_TO_ALL);
}
// Add to array
nodes.push(inputGate);
nodes.push(forgetGate);
nodes.push(memoryCell);
nodes.push(outputGate);
if (i !== blocks.length - 1) nodes.push(outputBlock);
previous = outputBlock;
}
// input to output direct connection
if (options.inputToOutput) {
inputLayer.connect(outputLayer, methods.connection.ALL_TO_ALL);
}
nodes.push(outputLayer);
return architect.Construct(nodes);
},
/**
* Creates a gated recurrent unit network
*/
GRU: function () {
var args = Array.prototype.slice.call(arguments);
if (args.length < 3) {
throw new Error('not enough layers (minimum 3) !!');
}
var inputLayer = new Group(args.shift()); // first argument
var outputLayer = new Group(args.pop()); // last argument
var blocks = args; // all the arguments in the middle
var nodes = [];
nodes.push(inputLayer);
var previous = inputLayer;
for (var i = 0; i < blocks.length; i++) {
var layer = new Layer.GRU(blocks[i]);
previous.connect(layer);
previous = layer;
nodes.push(layer);
}
previous.connect(outputLayer);
nodes.push(outputLayer);
return architect.Construct(nodes);
},
/**
* Creates a hopfield network of the given size
*/
Hopfield: function (size) {
var input = new Group(size);
var output = new Group(size);
input.connect(output, methods.connection.ALL_TO_ALL);
input.set({
type: 'input'
});
output.set({
squash: methods.activation.STEP,
type: 'output'
});
var network = new architect.Construct([input, output]);
return network;
},
/**
* Creates a NARX network (remember previous inputs/outputs)
*/
NARX: function (inputSize, hiddenLayers, outputSize, previousInput, previousOutput) {
if (!Array.isArray(hiddenLayers)) {
hiddenLayers = [hiddenLayers];
}
var nodes = [];
var input = new Layer.Dense(inputSize);
var inputMemory = new Layer.Memory(inputSize, previousInput);
var hidden = [];
var output = new Layer.Dense(outputSize);
var outputMemory = new Layer.Memory(outputSize, previousOutput);
nodes.push(input);
nodes.push(outputMemory);
for (var i = 0; i < hiddenLayers.length; i++) {
var hiddenLayer = new Layer.Dense(hiddenLayers[i]);
hidden.push(hiddenLayer);
nodes.push(hiddenLayer);
if (typeof hidden[i - 1] !== 'undefined') {
hidden[i - 1].connect(hiddenLayer, methods.connection.ALL_TO_ALL);
}
}
nodes.push(inputMemory);
nodes.push(output);
input.connect(hidden[0], methods.connection.ALL_TO_ALL);
input.connect(inputMemory, methods.connection.ONE_TO_ONE, 1);
inputMemory.connect(hidden[0], methods.connection.ALL_TO_ALL);
hidden[hidden.length - 1].connect(output, methods.connection.ALL_TO_ALL);
output.connect(outputMemory, methods.connection.ONE_TO_ONE, 1);
outputMemory.connect(hidden[0], methods.connection.ALL_TO_ALL);
input.set({
type: 'input'
});
output.set({
type: 'output'
});
return architect.Construct(nodes);
}
};
/* Export */
module.exports = architect;

49
node_modules/neataptic/src/architecture/connection.js generated vendored Normal file
View File

@@ -0,0 +1,49 @@
/* Export */
module.exports = Connection;
/*******************************************************************************
CONNECTION
*******************************************************************************/
function Connection (from, to, weight) {
this.from = from;
this.to = to;
this.gain = 1;
this.weight = (typeof weight === 'undefined') ? Math.random() * 0.2 - 0.1 : weight;
this.gater = null;
this.elegibility = 0;
// For tracking momentum
this.previousDeltaWeight = 0;
// Batch training
this.totalDeltaWeight = 0;
this.xtrace = {
nodes: [],
values: []
};
}
Connection.prototype = {
/**
* Converts the connection to a json object
*/
toJSON: function () {
var json = {
weight: this.weight
};
return json;
}
};
/**
* Returns an innovation ID
* https://en.wikipedia.org/wiki/Pairing_function (Cantor pairing function)
*/
Connection.innovationID = function (a, b) {
return 1 / 2 * (a + b) * (a + b + 1) + b;
};

263
node_modules/neataptic/src/architecture/group.js generated vendored Normal file
View File

@@ -0,0 +1,263 @@
/* Export */
module.exports = Group;
/* Import */
var methods = require('../methods/methods');
var config = require('../config');
var Layer = require('./layer');
var Node = require('./node');
/*******************************************************************************
Group
*******************************************************************************/
function Group (size) {
this.nodes = [];
this.connections = {
in: [],
out: [],
self: []
};
for (var i = 0; i < size; i++) {
this.nodes.push(new Node());
}
}
Group.prototype = {
/**
* Activates all the nodes in the group
*/
activate: function (value) {
var values = [];
if (typeof value !== 'undefined' && value.length !== this.nodes.length) {
throw new Error('Array with values should be same as the amount of nodes!');
}
for (var i = 0; i < this.nodes.length; i++) {
var activation;
if (typeof value === 'undefined') {
activation = this.nodes[i].activate();
} else {
activation = this.nodes[i].activate(value[i]);
}
values.push(activation);
}
return values;
},
/**
* Propagates all the node in the group
*/
propagate: function (rate, momentum, target) {
if (typeof target !== 'undefined' && target.length !== this.nodes.length) {
throw new Error('Array with values should be same as the amount of nodes!');
}
for (var i = this.nodes.length - 1; i >= 0; i--) {
if (typeof target === 'undefined') {
this.nodes[i].propagate(rate, momentum, true);
} else {
this.nodes[i].propagate(rate, momentum, true, target[i]);
}
}
},
/**
* Connects the nodes in this group to nodes in another group or just a node
*/
connect: function (target, method, weight) {
var connections = [];
var i, j;
if (target instanceof Group) {
if (typeof method === 'undefined') {
if (this !== target) {
if (config.warnings) console.warn('No group connection specified, using ALL_TO_ALL');
method = methods.connection.ALL_TO_ALL;
} else {
if (config.warnings) console.warn('No group connection specified, using ONE_TO_ONE');
method = methods.connection.ONE_TO_ONE;
}
}
if (method === methods.connection.ALL_TO_ALL || method === methods.connection.ALL_TO_ELSE) {
for (i = 0; i < this.nodes.length; i++) {
for (j = 0; j < target.nodes.length; j++) {
if (method === methods.connection.ALL_TO_ELSE && this.nodes[i] === target.nodes[j]) continue;
let connection = this.nodes[i].connect(target.nodes[j], weight);
this.connections.out.push(connection[0]);
target.connections.in.push(connection[0]);
connections.push(connection[0]);
}
}
} else if (method === methods.connection.ONE_TO_ONE) {
if (this.nodes.length !== target.nodes.length) {
throw new Error('From and To group must be the same size!');
}
for (i = 0; i < this.nodes.length; i++) {
let connection = this.nodes[i].connect(target.nodes[i], weight);
this.connections.self.push(connection[0]);
connections.push(connection[0]);
}
}
} else if (target instanceof Layer) {
connections = target.input(this, method, weight);
} else if (target instanceof Node) {
for (i = 0; i < this.nodes.length; i++) {
let connection = this.nodes[i].connect(target, weight);
this.connections.out.push(connection[0]);
connections.push(connection[0]);
}
}
return connections;
},
/**
* Make nodes from this group gate the given connection(s)
*/
gate: function (connections, method) {
if (typeof method === 'undefined') {
throw new Error('Please specify Gating.INPUT, Gating.OUTPUT');
}
if (!Array.isArray(connections)) {
connections = [connections];
}
var nodes1 = [];
var nodes2 = [];
var i, j;
for (i = 0; i < connections.length; i++) {
var connection = connections[i];
if (!nodes1.includes(connection.from)) nodes1.push(connection.from);
if (!nodes2.includes(connection.to)) nodes2.push(connection.to);
}
switch (method) {
case methods.gating.INPUT:
for (i = 0; i < nodes2.length; i++) {
let node = nodes2[i];
let gater = this.nodes[i % this.nodes.length];
for (j = 0; j < node.connections.in.length; j++) {
let conn = node.connections.in[j];
if (connections.includes(conn)) {
gater.gate(conn);
}
}
}
break;
case methods.gating.OUTPUT:
for (i = 0; i < nodes1.length; i++) {
let node = nodes1[i];
let gater = this.nodes[i % this.nodes.length];
for (j = 0; j < node.connections.out.length; j++) {
let conn = node.connections.out[j];
if (connections.includes(conn)) {
gater.gate(conn);
}
}
}
break;
case methods.gating.SELF:
for (i = 0; i < nodes1.length; i++) {
let node = nodes1[i];
let gater = this.nodes[i % this.nodes.length];
if (connections.includes(node.connections.self)) {
gater.gate(node.connections.self);
}
}
}
},
/**
* Sets the value of a property for every node
*/
set: function (values) {
for (var i = 0; i < this.nodes.length; i++) {
if (typeof values.bias !== 'undefined') {
this.nodes[i].bias = values.bias;
}
this.nodes[i].squash = values.squash || this.nodes[i].squash;
this.nodes[i].type = values.type || this.nodes[i].type;
}
},
/**
* Disconnects all nodes from this group from another given group/node
*/
disconnect: function (target, twosided) {
twosided = twosided || false;
// In the future, disconnect will return a connection so indexOf can be used
var i, j, k;
if (target instanceof Group) {
for (i = 0; i < this.nodes.length; i++) {
for (j = 0; j < target.nodes.length; j++) {
this.nodes[i].disconnect(target.nodes[j], twosided);
for (k = this.connections.out.length - 1; k >= 0; k--) {
let conn = this.connections.out[k];
if (conn.from === this.nodes[i] && conn.to === target.nodes[j]) {
this.connections.out.splice(k, 1);
break;
}
}
if (twosided) {
for (k = this.connections.in.length - 1; k >= 0; k--) {
let conn = this.connections.in[k];
if (conn.from === target.nodes[j] && conn.to === this.nodes[i]) {
this.connections.in.splice(k, 1);
break;
}
}
}
}
}
} else if (target instanceof Node) {
for (i = 0; i < this.nodes.length; i++) {
this.nodes[i].disconnect(target, twosided);
for (j = this.connections.out.length - 1; j >= 0; j--) {
let conn = this.connections.out[j];
if (conn.from === this.nodes[i] && conn.to === target) {
this.connections.out.splice(j, 1);
break;
}
}
if (twosided) {
for (j = this.connections.in.length - 1; j >= 0; j--) {
var conn = this.connections.in[j];
if (conn.from === target && conn.to === this.nodes[i]) {
this.connections.in.splice(j, 1);
break;
}
}
}
}
}
},
/**
* Clear the context of this group
*/
clear: function () {
for (var i = 0; i < this.nodes.length; i++) {
this.nodes[i].clear();
}
}
};

378
node_modules/neataptic/src/architecture/layer.js generated vendored Normal file
View File

@@ -0,0 +1,378 @@
/* Export */
module.exports = Layer;
/* Import */
var methods = require('../methods/methods');
var Group = require('./group');
var Node = require('./node');
/*******************************************************************************
Group
*******************************************************************************/
function Layer () {
this.output = null;
this.nodes = [];
this.connections = { in: [],
out: [],
self: []
};
}
Layer.prototype = {
/**
* Activates all the nodes in the group
*/
activate: function (value) {
var values = [];
if (typeof value !== 'undefined' && value.length !== this.nodes.length) {
throw new Error('Array with values should be same as the amount of nodes!');
}
for (var i = 0; i < this.nodes.length; i++) {
var activation;
if (typeof value === 'undefined') {
activation = this.nodes[i].activate();
} else {
activation = this.nodes[i].activate(value[i]);
}
values.push(activation);
}
return values;
},
/**
* Propagates all the node in the group
*/
propagate: function (rate, momentum, target) {
if (typeof target !== 'undefined' && target.length !== this.nodes.length) {
throw new Error('Array with values should be same as the amount of nodes!');
}
for (var i = this.nodes.length - 1; i >= 0; i--) {
if (typeof target === 'undefined') {
this.nodes[i].propagate(rate, momentum, true);
} else {
this.nodes[i].propagate(rate, momentum, true, target[i]);
}
}
},
/**
* Connects the nodes in this group to nodes in another group or just a node
*/
connect: function (target, method, weight) {
var connections;
if (target instanceof Group || target instanceof Node) {
connections = this.output.connect(target, method, weight);
} else if (target instanceof Layer) {
connections = target.input(this, method, weight);
}
return connections;
},
/**
* Make nodes from this group gate the given connection(s)
*/
gate: function (connections, method) {
this.output.gate(connections, method);
},
/**
* Sets the value of a property for every node
*/
set: function (values) {
for (var i = 0; i < this.nodes.length; i++) {
var node = this.nodes[i];
if (node instanceof Node) {
if (typeof values.bias !== 'undefined') {
node.bias = values.bias;
}
node.squash = values.squash || node.squash;
node.type = values.type || node.type;
} else if (node instanceof Group) {
node.set(values);
}
}
},
/**
* Disconnects all nodes from this group from another given group/node
*/
disconnect: function (target, twosided) {
twosided = twosided || false;
// In the future, disconnect will return a connection so indexOf can be used
var i, j, k;
if (target instanceof Group) {
for (i = 0; i < this.nodes.length; i++) {
for (j = 0; j < target.nodes.length; j++) {
this.nodes[i].disconnect(target.nodes[j], twosided);
for (k = this.connections.out.length - 1; k >= 0; k--) {
let conn = this.connections.out[k];
if (conn.from === this.nodes[i] && conn.to === target.nodes[j]) {
this.connections.out.splice(k, 1);
break;
}
}
if (twosided) {
for (k = this.connections.in.length - 1; k >= 0; k--) {
let conn = this.connections.in[k];
if (conn.from === target.nodes[j] && conn.to === this.nodes[i]) {
this.connections.in.splice(k, 1);
break;
}
}
}
}
}
} else if (target instanceof Node) {
for (i = 0; i < this.nodes.length; i++) {
this.nodes[i].disconnect(target, twosided);
for (j = this.connections.out.length - 1; j >= 0; j--) {
let conn = this.connections.out[j];
if (conn.from === this.nodes[i] && conn.to === target) {
this.connections.out.splice(j, 1);
break;
}
}
if (twosided) {
for (k = this.connections.in.length - 1; k >= 0; k--) {
let conn = this.connections.in[k];
if (conn.from === target && conn.to === this.nodes[i]) {
this.connections.in.splice(k, 1);
break;
}
}
}
}
}
},
/**
* Clear the context of this group
*/
clear: function () {
for (var i = 0; i < this.nodes.length; i++) {
this.nodes[i].clear();
}
}
};
Layer.Dense = function (size) {
// Create the layer
var layer = new Layer();
// Init required nodes (in activation order)
var block = new Group(size);
layer.nodes.push(block);
layer.output = block;
layer.input = function (from, method, weight) {
if (from instanceof Layer) from = from.output;
method = method || methods.connection.ALL_TO_ALL;
return from.connect(block, method, weight);
};
return layer;
};
Layer.LSTM = function (size) {
// Create the layer
var layer = new Layer();
// Init required nodes (in activation order)
var inputGate = new Group(size);
var forgetGate = new Group(size);
var memoryCell = new Group(size);
var outputGate = new Group(size);
var outputBlock = new Group(size);
inputGate.set({
bias: 1
});
forgetGate.set({
bias: 1
});
outputGate.set({
bias: 1
});
// Set up internal connections
memoryCell.connect(inputGate, methods.connection.ALL_TO_ALL);
memoryCell.connect(forgetGate, methods.connection.ALL_TO_ALL);
memoryCell.connect(outputGate, methods.connection.ALL_TO_ALL);
var forget = memoryCell.connect(memoryCell, methods.connection.ONE_TO_ONE);
var output = memoryCell.connect(outputBlock, methods.connection.ALL_TO_ALL);
// Set up gates
forgetGate.gate(forget, methods.gating.SELF);
outputGate.gate(output, methods.gating.OUTPUT);
// Add to nodes array
layer.nodes = [inputGate, forgetGate, memoryCell, outputGate, outputBlock];
// Define output
layer.output = outputBlock;
layer.input = function (from, method, weight) {
if (from instanceof Layer) from = from.output;
method = method || methods.connection.ALL_TO_ALL;
var connections = [];
var input = from.connect(memoryCell, method, weight);
connections = connections.concat(input);
connections = connections.concat(from.connect(inputGate, method, weight));
connections = connections.concat(from.connect(outputGate, method, weight));
connections = connections.concat(from.connect(forgetGate, method, weight));
inputGate.gate(input, methods.gating.INPUT);
return connections;
};
return layer;
};
Layer.GRU = function (size) {
// Create the layer
var layer = new Layer();
var updateGate = new Group(size);
var inverseUpdateGate = new Group(size);
var resetGate = new Group(size);
var memoryCell = new Group(size);
var output = new Group(size);
var previousOutput = new Group(size);
previousOutput.set({
bias: 0,
squash: methods.activation.IDENTITY,
type: 'constant'
});
memoryCell.set({
squash: methods.activation.TANH
});
inverseUpdateGate.set({
bias: 0,
squash: methods.activation.INVERSE,
type: 'constant'
});
updateGate.set({
bias: 1
});
resetGate.set({
bias: 0
});
// Update gate calculation
previousOutput.connect(updateGate, methods.connection.ALL_TO_ALL);
// Inverse update gate calculation
updateGate.connect(inverseUpdateGate, methods.connection.ONE_TO_ONE, 1);
// Reset gate calculation
previousOutput.connect(resetGate, methods.connection.ALL_TO_ALL);
// Memory calculation
var reset = previousOutput.connect(memoryCell, methods.connection.ALL_TO_ALL);
resetGate.gate(reset, methods.gating.OUTPUT); // gate
// Output calculation
var update1 = previousOutput.connect(output, methods.connection.ALL_TO_ALL);
var update2 = memoryCell.connect(output, methods.connection.ALL_TO_ALL);
updateGate.gate(update1, methods.gating.OUTPUT);
inverseUpdateGate.gate(update2, methods.gating.OUTPUT);
// Previous output calculation
output.connect(previousOutput, methods.connection.ONE_TO_ONE, 1);
// Add to nodes array
layer.nodes = [updateGate, inverseUpdateGate, resetGate, memoryCell, output, previousOutput];
layer.output = output;
layer.input = function (from, method, weight) {
if (from instanceof Layer) from = from.output;
method = method || methods.connection.ALL_TO_ALL;
var connections = [];
connections = connections.concat(from.connect(updateGate, method, weight));
connections = connections.concat(from.connect(resetGate, method, weight));
connections = connections.concat(from.connect(memoryCell, method, weight));
return connections;
};
return layer;
};
Layer.Memory = function (size, memory) {
// Create the layer
var layer = new Layer();
// Because the output can only be one group, we have to put the nodes all in óne group
var previous = null;
var i;
for (i = 0; i < memory; i++) {
var block = new Group(size);
block.set({
squash: methods.activation.IDENTITY,
bias: 0,
type: 'constant'
});
if (previous != null) {
previous.connect(block, methods.connection.ONE_TO_ONE, 1);
}
layer.nodes.push(block);
previous = block;
}
layer.nodes.reverse();
for (i = 0; i < layer.nodes.length; i++) {
layer.nodes[i].nodes.reverse();
}
// Because output can only be óne group, fit all memory nodes in óne group
var outputGroup = new Group(0);
for (var group in layer.nodes) {
outputGroup.nodes = outputGroup.nodes.concat(layer.nodes[group].nodes);
}
layer.output = outputGroup;
layer.input = function (from, method, weight) {
if (from instanceof Layer) from = from.output;
method = method || methods.connection.ALL_TO_ALL;
if (from.nodes.length !== layer.nodes[layer.nodes.length - 1].nodes.length) {
throw new Error('Previous layer size must be same as memory size');
}
return from.connect(layer.nodes[layer.nodes.length - 1], methods.connection.ONE_TO_ONE, 1);
};
return layer;
};

1341
node_modules/neataptic/src/architecture/network.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

431
node_modules/neataptic/src/architecture/node.js generated vendored Normal file
View File

@@ -0,0 +1,431 @@
/* Export */
module.exports = Node;
/* Import */
var methods = require('../methods/methods');
var Connection = require('./connection');
var config = require('../config');
/*******************************************************************************
NODE
*******************************************************************************/
function Node (type) {
this.bias = (type === 'input') ? 0 : Math.random() * 0.2 - 0.1;
this.squash = methods.activation.LOGISTIC;
this.type = type || 'hidden';
this.activation = 0;
this.state = 0;
this.old = 0;
// For dropout
this.mask = 1;
// For tracking momentum
this.previousDeltaBias = 0;
// Batch training
this.totalDeltaBias = 0;
this.connections = {
in: [],
out: [],
gated: [],
self: new Connection(this, this, 0)
};
// Data for backpropagation
this.error = {
responsibility: 0,
projected: 0,
gated: 0
};
}
Node.prototype = {
/**
* Activates the node
*/
activate: function (input) {
// Check if an input is given
if (typeof input !== 'undefined') {
this.activation = input;
return this.activation;
}
this.old = this.state;
// All activation sources coming from the node itself
this.state = this.connections.self.gain * this.connections.self.weight * this.state + this.bias;
// Activation sources coming from connections
var i;
for (i = 0; i < this.connections.in.length; i++) {
var connection = this.connections.in[i];
this.state += connection.from.activation * connection.weight * connection.gain;
}
// Squash the values received
this.activation = this.squash(this.state) * this.mask;
this.derivative = this.squash(this.state, true);
// Update traces
var nodes = [];
var influences = [];
for (i = 0; i < this.connections.gated.length; i++) {
let conn = this.connections.gated[i];
let node = conn.to;
let index = nodes.indexOf(node);
if (index > -1) {
influences[index] += conn.weight * conn.from.activation;
} else {
nodes.push(node);
influences.push(conn.weight * conn.from.activation +
(node.connections.self.gater === this ? node.old : 0));
}
// Adjust the gain to this nodes' activation
conn.gain = this.activation;
}
for (i = 0; i < this.connections.in.length; i++) {
let connection = this.connections.in[i];
// Elegibility trace
connection.elegibility = this.connections.self.gain * this.connections.self.weight *
connection.elegibility + connection.from.activation * connection.gain;
// Extended trace
for (var j = 0; j < nodes.length; j++) {
let node = nodes[j];
let influence = influences[j];
let index = connection.xtrace.nodes.indexOf(node);
if (index > -1) {
connection.xtrace.values[index] = node.connections.self.gain * node.connections.self.weight *
connection.xtrace.values[index] + this.derivative * connection.elegibility * influence;
} else {
// Does not exist there yet, might be through mutation
connection.xtrace.nodes.push(node);
connection.xtrace.values.push(this.derivative * connection.elegibility * influence);
}
}
}
return this.activation;
},
/**
* Activates the node without calculating elegibility traces and such
*/
noTraceActivate: function (input) {
// Check if an input is given
if (typeof input !== 'undefined') {
this.activation = input;
return this.activation;
}
// All activation sources coming from the node itself
this.state = this.connections.self.gain * this.connections.self.weight * this.state + this.bias;
// Activation sources coming from connections
var i;
for (i = 0; i < this.connections.in.length; i++) {
var connection = this.connections.in[i];
this.state += connection.from.activation * connection.weight * connection.gain;
}
// Squash the values received
this.activation = this.squash(this.state);
for (i = 0; i < this.connections.gated.length; i++) {
this.connections.gated[i].gain = this.activation;
}
return this.activation;
},
/**
* Back-propagate the error, aka learn
*/
propagate: function (rate, momentum, update, target) {
momentum = momentum || 0;
rate = rate || 0.3;
// Error accumulator
var error = 0;
// Output nodes get their error from the enviroment
if (this.type === 'output') {
this.error.responsibility = this.error.projected = target - this.activation;
} else { // the rest of the nodes compute their error responsibilities by backpropagation
// error responsibilities from all the connections projected from this node
var i;
for (i = 0; i < this.connections.out.length; i++) {
let connection = this.connections.out[i];
let node = connection.to;
// Eq. 21
error += node.error.responsibility * connection.weight * connection.gain;
}
// Projected error responsibility
this.error.projected = this.derivative * error;
// Error responsibilities from all connections gated by this neuron
error = 0;
for (i = 0; i < this.connections.gated.length; i++) {
let conn = this.connections.gated[i];
let node = conn.to;
let influence = node.connections.self.gater === this ? node.old : 0;
influence += conn.weight * conn.from.activation;
error += node.error.responsibility * influence;
}
// Gated error responsibility
this.error.gated = this.derivative * error;
// Error responsibility
this.error.responsibility = this.error.projected + this.error.gated;
}
if (this.type === 'constant') return;
// Adjust all the node's incoming connections
for (i = 0; i < this.connections.in.length; i++) {
let connection = this.connections.in[i];
let gradient = this.error.projected * connection.elegibility;
for (var j = 0; j < connection.xtrace.nodes.length; j++) {
let node = connection.xtrace.nodes[j];
let value = connection.xtrace.values[j];
gradient += node.error.responsibility * value;
}
// Adjust weight
let deltaWeight = rate * gradient * this.mask;
connection.totalDeltaWeight += deltaWeight;
if (update) {
connection.totalDeltaWeight += momentum * connection.previousDeltaWeight;
connection.weight += connection.totalDeltaWeight;
connection.previousDeltaWeight = connection.totalDeltaWeight;
connection.totalDeltaWeight = 0;
}
}
// Adjust bias
var deltaBias = rate * this.error.responsibility;
this.totalDeltaBias += deltaBias;
if (update) {
this.totalDeltaBias += momentum * this.previousDeltaBias;
this.bias += this.totalDeltaBias;
this.previousDeltaBias = this.totalDeltaBias;
this.totalDeltaBias = 0;
}
},
/**
* Creates a connection from this node to the given node
*/
connect: function (target, weight) {
var connections = [];
if (typeof target.bias !== 'undefined') { // must be a node!
if (target === this) {
// Turn on the self connection by setting the weight
if (this.connections.self.weight !== 0) {
if (config.warnings) console.warn('This connection already exists!');
} else {
this.connections.self.weight = weight || 1;
}
connections.push(this.connections.self);
} else if (this.isProjectingTo(target)) {
throw new Error('Already projecting a connection to this node!');
} else {
let connection = new Connection(this, target, weight);
target.connections.in.push(connection);
this.connections.out.push(connection);
connections.push(connection);
}
} else { // should be a group
for (var i = 0; i < target.nodes.length; i++) {
let connection = new Connection(this, target.nodes[i], weight);
target.nodes[i].connections.in.push(connection);
this.connections.out.push(connection);
target.connections.in.push(connection);
connections.push(connection);
}
}
return connections;
},
/**
* Disconnects this node from the other node
*/
disconnect: function (node, twosided) {
if (this === node) {
this.connections.self.weight = 0;
return;
}
for (var i = 0; i < this.connections.out.length; i++) {
let conn = this.connections.out[i];
if (conn.to === node) {
this.connections.out.splice(i, 1);
let j = conn.to.connections.in.indexOf(conn);
conn.to.connections.in.splice(j, 1);
if (conn.gater !== null) conn.gater.ungate(conn);
break;
}
}
if (twosided) {
node.disconnect(this);
}
},
/**
* Make this node gate a connection
*/
gate: function (connections) {
if (!Array.isArray(connections)) {
connections = [connections];
}
for (var i = 0; i < connections.length; i++) {
var connection = connections[i];
this.connections.gated.push(connection);
connection.gater = this;
}
},
/**
* Removes the gates from this node from the given connection(s)
*/
ungate: function (connections) {
if (!Array.isArray(connections)) {
connections = [connections];
}
for (var i = connections.length - 1; i >= 0; i--) {
var connection = connections[i];
var index = this.connections.gated.indexOf(connection);
this.connections.gated.splice(index, 1);
connection.gater = null;
connection.gain = 1;
}
},
/**
* Clear the context of the node
*/
clear: function () {
for (var i = 0; i < this.connections.in.length; i++) {
var connection = this.connections.in[i];
connection.elegibility = 0;
connection.xtrace = {
nodes: [],
values: []
};
}
for (i = 0; i < this.connections.gated.length; i++) {
let conn = this.connections.gated[i];
conn.gain = 0;
}
this.error.responsibility = this.error.projected = this.error.gated = 0;
this.old = this.state = this.activation = 0;
},
/**
* Mutates the node with the given method
*/
mutate: function (method) {
if (typeof method === 'undefined') {
throw new Error('No mutate method given!');
} else if (!(method.name in methods.mutation)) {
throw new Error('This method does not exist!');
}
switch (method) {
case methods.mutation.MOD_ACTIVATION:
// Can't be the same squash
var squash = method.allowed[(method.allowed.indexOf(this.squash) + Math.floor(Math.random() * (method.allowed.length - 1)) + 1) % method.allowed.length];
this.squash = squash;
break;
case methods.mutation.MOD_BIAS:
var modification = Math.random() * (method.max - method.min) + method.min;
this.bias += modification;
break;
}
},
/**
* Checks if this node is projecting to the given node
*/
isProjectingTo: function (node) {
if (node === this && this.connections.self.weight !== 0) return true;
for (var i = 0; i < this.connections.out.length; i++) {
var conn = this.connections.out[i];
if (conn.to === node) {
return true;
}
}
return false;
},
/**
* Checks if the given node is projecting to this node
*/
isProjectedBy: function (node) {
if (node === this && this.connections.self.weight !== 0) return true;
for (var i = 0; i < this.connections.in.length; i++) {
var conn = this.connections.in[i];
if (conn.from === node) {
return true;
}
}
return false;
},
/**
* Converts the node to a json object
*/
toJSON: function () {
var json = {
bias: this.bias,
type: this.type,
squash: this.squash.name,
mask: this.mask
};
return json;
}
};
/**
* Convert a json object to a node
*/
Node.fromJSON = function (json) {
var node = new Node();
node.bias = json.bias;
node.type = json.type;
node.mask = json.mask;
node.squash = methods.activation[json.squash];
return node;
};

11
node_modules/neataptic/src/config.js generated vendored Normal file
View File

@@ -0,0 +1,11 @@
/*******************************************************************************
CONFIG
*******************************************************************************/
// Config
var config = {
warnings: false
};
/* Export */
module.exports = config;

77
node_modules/neataptic/src/methods/activation.js generated vendored Normal file
View File

@@ -0,0 +1,77 @@
/*******************************************************************************
ACTIVATION FUNCTIONS
*******************************************************************************/
// https://en.wikipedia.org/wiki/Activation_function
// https://stats.stackexchange.com/questions/115258/comprehensive-list-of-activation-functions-in-neural-networks-with-pros-cons
var activation = {
LOGISTIC: function (x, derivate) {
var fx = 1 / (1 + Math.exp(-x));
if (!derivate) return fx;
return fx * (1 - fx);
},
TANH: function (x, derivate) {
if (derivate) return 1 - Math.pow(Math.tanh(x), 2);
return Math.tanh(x);
},
IDENTITY: function (x, derivate) {
return derivate ? 1 : x;
},
STEP: function (x, derivate) {
return derivate ? 0 : x > 0 ? 1 : 0;
},
RELU: function (x, derivate) {
if (derivate) return x > 0 ? 1 : 0;
return x > 0 ? x : 0;
},
SOFTSIGN: function (x, derivate) {
var d = 1 + Math.abs(x);
if (derivate) return x / Math.pow(d, 2);
return x / d;
},
SINUSOID: function (x, derivate) {
if (derivate) return Math.cos(x);
return Math.sin(x);
},
GAUSSIAN: function (x, derivate) {
var d = Math.exp(-Math.pow(x, 2));
if (derivate) return -2 * x * d;
return d;
},
BENT_IDENTITY: function (x, derivate) {
var d = Math.sqrt(Math.pow(x, 2) + 1);
if (derivate) return x / (2 * d) + 1;
return (d - 1) / 2 + x;
},
BIPOLAR: function (x, derivate) {
return derivate ? 0 : x > 0 ? 1 : -1;
},
BIPOLAR_SIGMOID: function (x, derivate) {
var d = 2 / (1 + Math.exp(-x)) - 1;
if (derivate) return 1 / 2 * (1 + d) * (1 - d);
return d;
},
HARD_TANH: function (x, derivate) {
if (derivate) return x > -1 && x < 1 ? 1 : 0;
return Math.max(-1, Math.min(1, x));
},
ABSOLUTE: function (x, derivate) {
if (derivate) return x < 0 ? -1 : 1;
return Math.abs(x);
},
INVERSE: function (x, derivate) {
if (derivate) return -1;
return 1 - x;
},
// https://arxiv.org/pdf/1706.02515.pdf
SELU: function (x, derivate) {
var alpha = 1.6732632423543772848170429916717;
var scale = 1.0507009873554804934193349852946;
var fx = x > 0 ? x : alpha * Math.exp(x) - alpha;
if (derivate) { return x > 0 ? scale : (fx + alpha) * scale; }
return fx * scale;
}
};
/* Export */
module.exports = activation;

19
node_modules/neataptic/src/methods/connection.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
/*******************************************************************************
CONNECTION
*******************************************************************************/
// Specifies in what manner two groups are connected
var connection = {
ALL_TO_ALL: {
name: 'OUTPUT'
},
ALL_TO_ELSE: {
name: 'INPUT'
},
ONE_TO_ONE: {
name: 'SELF'
}
};
/* Export */
module.exports = connection;

73
node_modules/neataptic/src/methods/cost.js generated vendored Normal file
View File

@@ -0,0 +1,73 @@
/*******************************************************************************
COST FUNCTIONS
*******************************************************************************/
// https://en.wikipedia.org/wiki/Loss_function
var cost = {
// Cross entropy error
CROSS_ENTROPY: function (target, output) {
var error = 0;
for (var i = 0; i < output.length; i++) {
// Avoid negative and zero numbers, use 1e-15 http://bit.ly/2p5W29A
error -= target[i] * Math.log(Math.max(output[i], 1e-15)) + (1 - target[i]) * Math.log(1 - Math.max(output[i], 1e-15));
}
return error / output.length;
},
// Mean Squared Error
MSE: function (target, output) {
var error = 0;
for (var i = 0; i < output.length; i++) {
error += Math.pow(target[i] - output[i], 2);
}
return error / output.length;
},
// Binary error
BINARY: function (target, output) {
var misses = 0;
for (var i = 0; i < output.length; i++) {
misses += Math.round(target[i] * 2) !== Math.round(output[i] * 2);
}
return misses;
},
// Mean Absolute Error
MAE: function (target, output) {
var error = 0;
for (var i = 0; i < output.length; i++) {
error += Math.abs(target[i] - output[i]);
}
return error / output.length;
},
// Mean Absolute Percentage Error
MAPE: function (target, output) {
var error = 0;
for (var i = 0; i < output.length; i++) {
error += Math.abs((output[i] - target[i]) / Math.max(target[i], 1e-15));
}
return error / output.length;
},
// Mean Squared Logarithmic Error
MSLE: function (target, output) {
var error = 0;
for (var i = 0; i < output.length; i++) {
error += Math.log(Math.max(target[i], 1e-15)) - Math.log(Math.max(output[i], 1e-15));
}
return error;
},
// Hinge loss, for classifiers
HINGE: function (target, output) {
var error = 0;
for (var i = 0; i < output.length; i++) {
error += Math.max(0, 1 - target[i] * output[i]);
}
return error;
}
};
/* Export */
module.exports = cost;

24
node_modules/neataptic/src/methods/crossover.js generated vendored Normal file
View File

@@ -0,0 +1,24 @@
/*******************************************************************************
CROSSOVER
*******************************************************************************/
// https://en.wikipedia.org/wiki/Crossover_(genetic_algorithm)
var crossover = {
SINGLE_POINT: {
name: 'SINGLE_POINT',
config: [0.4]
},
TWO_POINT: {
name: 'TWO_POINT',
config: [0.4, 0.9]
},
UNIFORM: {
name: 'UNIFORM'
},
AVERAGE: {
name: 'AVERAGE'
}
};
/* Export */
module.exports = crossover;

19
node_modules/neataptic/src/methods/gating.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
/*******************************************************************************
GATING
*******************************************************************************/
// Specifies how to gate a connection between two groups of multiple neurons
var gating = {
OUTPUT: {
name: 'OUTPUT'
},
INPUT: {
name: 'INPUT'
},
SELF: {
name: 'SELF'
}
};
/* Export */
module.exports = gating;

17
node_modules/neataptic/src/methods/methods.js generated vendored Normal file
View File

@@ -0,0 +1,17 @@
/*******************************************************************************
METHODS
*******************************************************************************/
var methods = {
activation: require('./activation'),
mutation: require('./mutation'),
selection: require('./selection'),
crossover: require('./crossover'),
cost: require('./cost'),
gating: require('./gating'),
connection: require('./connection'),
rate: require('./rate')
};
/** Export */
module.exports = methods;

107
node_modules/neataptic/src/methods/mutation.js generated vendored Normal file
View File

@@ -0,0 +1,107 @@
/* Import */
var activation = require('./activation');
/*******************************************************************************
MUTATION
*******************************************************************************/
// https://en.wikipedia.org/wiki/mutation_(genetic_algorithm)
var mutation = {
ADD_NODE: {
name: 'ADD_NODE'
},
SUB_NODE: {
name: 'SUB_NODE',
keep_gates: true
},
ADD_CONN: {
name: 'ADD_CONN'
},
SUB_CONN: {
name: 'REMOVE_CONN'
},
MOD_WEIGHT: {
name: 'MOD_WEIGHT',
min: -1,
max: 1
},
MOD_BIAS: {
name: 'MOD_BIAS',
min: -1,
max: 1
},
MOD_ACTIVATION: {
name: 'MOD_ACTIVATION',
mutateOutput: true,
allowed: [
activation.LOGISTIC,
activation.TANH,
activation.RELU,
activation.IDENTITY,
activation.STEP,
activation.SOFTSIGN,
activation.SINUSOID,
activation.GAUSSIAN,
activation.BENT_IDENTITY,
activation.BIPOLAR,
activation.BIPOLAR_SIGMOID,
activation.HARD_TANH,
activation.ABSOLUTE,
activation.INVERSE,
activation.SELU
]
},
ADD_SELF_CONN: {
name: 'ADD_SELF_CONN'
},
SUB_SELF_CONN: {
name: 'SUB_SELF_CONN'
},
ADD_GATE: {
name: 'ADD_GATE'
},
SUB_GATE: {
name: 'SUB_GATE'
},
ADD_BACK_CONN: {
name: 'ADD_BACK_CONN'
},
SUB_BACK_CONN: {
name: 'SUB_BACK_CONN'
},
SWAP_NODES: {
name: 'SWAP_NODES',
mutateOutput: true
}
};
mutation.ALL = [
mutation.ADD_NODE,
mutation.SUB_NODE,
mutation.ADD_CONN,
mutation.SUB_CONN,
mutation.MOD_WEIGHT,
mutation.MOD_BIAS,
mutation.MOD_ACTIVATION,
mutation.ADD_GATE,
mutation.SUB_GATE,
mutation.ADD_SELF_CONN,
mutation.SUB_SELF_CONN,
mutation.ADD_BACK_CONN,
mutation.SUB_BACK_CONN,
mutation.SWAP_NODES
];
mutation.FFW = [
mutation.ADD_NODE,
mutation.SUB_NODE,
mutation.ADD_CONN,
mutation.SUB_CONN,
mutation.MOD_WEIGHT,
mutation.MOD_BIAS,
mutation.MOD_ACTIVATION,
mutation.SWAP_NODES
];
/* Export */
module.exports = mutation;

43
node_modules/neataptic/src/methods/rate.js generated vendored Normal file
View File

@@ -0,0 +1,43 @@
/*******************************************************************************
RATE
*******************************************************************************/
// https://stackoverflow.com/questions/30033096/what-is-lr-policy-in-caffe/30045244
var rate = {
FIXED: function () {
var func = function (baseRate, iteration) { return baseRate; };
return func;
},
STEP: function (gamma, stepSize) {
gamma = gamma || 0.9;
stepSize = stepSize || 100;
var func = function (baseRate, iteration) {
return baseRate * Math.pow(gamma, Math.floor(iteration / stepSize));
};
return func;
},
EXP: function (gamma) {
gamma = gamma || 0.999;
var func = function (baseRate, iteration) {
return baseRate * Math.pow(gamma, iteration);
};
return func;
},
INV: function (gamma, power) {
gamma = gamma || 0.001;
power = power || 2;
var func = function (baseRate, iteration) {
return baseRate * Math.pow(1 + gamma * iteration, -power);
};
return func;
}
};
/* Export */
module.exports = rate;

23
node_modules/neataptic/src/methods/selection.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
/*******************************************************************************
SELECTION
*******************************************************************************/
// https://en.wikipedia.org/wiki/Selection_(genetic_algorithm)
var selection = {
FITNESS_PROPORTIONATE: {
name: 'FITNESS_PROPORTIONATE'
},
POWER: {
name: 'POWER',
power: 4
},
TOURNAMENT: {
name: 'TOURNAMENT',
size: 5,
probability: 0.5
}
};
/* Export */
module.exports = selection;

107
node_modules/neataptic/src/multithreading/multi.js generated vendored Normal file
View File

@@ -0,0 +1,107 @@
/*******************************************************************************
MULTITHREADING
*******************************************************************************/
var multi = {
/** Workers */
workers: require('./workers/workers'),
/** Serializes a dataset */
serializeDataSet: function (dataSet) {
var serialized = [dataSet[0].input.length, dataSet[0].output.length];
for (var i = 0; i < dataSet.length; i++) {
var j;
for (j = 0; j < serialized[0]; j++) {
serialized.push(dataSet[i].input[j]);
}
for (j = 0; j < serialized[1]; j++) {
serialized.push(dataSet[i].output[j]);
}
}
return serialized;
},
/** Activate a serialized network */
activateSerializedNetwork: function (input, A, S, data, F) {
for (var i = 0; i < data[0]; i++) A[i] = input[i];
for (i = 2; i < data.length; i++) {
let index = data[i++];
let bias = data[i++];
let squash = data[i++];
let selfweight = data[i++];
let selfgater = data[i++];
S[index] = (selfgater === -1 ? 1 : A[selfgater]) * selfweight * S[index] + bias;
while (data[i] !== -2) {
S[index] += A[data[i++]] * data[i++] * (data[i++] === -1 ? 1 : A[data[i - 1]]);
}
A[index] = F[squash](S[index]);
}
var output = [];
for (i = A.length - data[1]; i < A.length; i++) output.push(A[i]);
return output;
},
/** Deserializes a dataset to an array of arrays */
deserializeDataSet: function (serializedSet) {
var set = [];
var sampleSize = serializedSet[0] + serializedSet[1];
for (var i = 0; i < (serializedSet.length - 2) / sampleSize; i++) {
let input = [];
for (var j = 2 + i * sampleSize; j < 2 + i * sampleSize + serializedSet[0]; j++) {
input.push(serializedSet[j]);
}
let output = [];
for (j = 2 + i * sampleSize + serializedSet[0]; j < 2 + i * sampleSize + sampleSize; j++) {
output.push(serializedSet[j]);
}
set.push(input);
set.push(output);
}
return set;
},
/** A list of compiled activation functions in a certain order */
activations: [
function (x) { return 1 / (1 + Math.exp(-x)); },
function (x) { return Math.tanh(x); },
function (x) { return x; },
function (x) { return x > 0 ? 1 : 0; },
function (x) { return x > 0 ? x : 0; },
function (x) { return x / (1 + Math.abs(x)); },
function (x) { return Math.sin(x); },
function (x) { return Math.exp(-Math.pow(x, 2)); },
function (x) { return (Math.sqrt(Math.pow(x, 2) + 1) - 1) / 2 + x; },
function (x) { return x > 0 ? 1 : -1; },
function (x) { return 2 / (1 + Math.exp(-x)) - 1; },
function (x) { return Math.max(-1, Math.min(1, x)); },
function (x) { return Math.abs(x); },
function (x) { return 1 - x; },
function (x) {
var a = 1.6732632423543772848170429916717;
return (x > 0 ? x : a * Math.exp(x) - a) * 1.0507009873554804934193349852946;
}
]
};
multi.testSerializedSet = function (set, cost, A, S, data, F) {
// Calculate how much samples are in the set
var error = 0;
for (var i = 0; i < set.length; i += 2) {
let output = multi.activateSerializedNetwork(set[i], A, S, data, F);
error += cost(set[i + 1], output);
}
return error / (set.length / 2);
};
/* Export */
for (var i in multi) {
module.exports[i] = multi[i];
}

View File

@@ -0,0 +1,72 @@
/* Export */
module.exports = TestWorker;
/* Import */
var multi = require('../../multi');
/*******************************************************************************
WEBWORKER
*******************************************************************************/
function TestWorker (dataSet, cost) {
var blob = new Blob([this._createBlobString(cost)]);
this.url = window.URL.createObjectURL(blob);
this.worker = new Worker(this.url);
var data = { set: new Float64Array(dataSet).buffer };
this.worker.postMessage(data, [data.set]);
}
TestWorker.prototype = {
evaluate: function (network) {
return new Promise((resolve, reject) => {
var serialized = network.serialize();
var data = {
activations: new Float64Array(serialized[0]).buffer,
states: new Float64Array(serialized[1]).buffer,
conns: new Float64Array(serialized[2]).buffer
};
this.worker.onmessage = function (e) {
var error = new Float64Array(e.data.buffer)[0];
resolve(error);
};
this.worker.postMessage(data, [data.activations, data.states, data.conns]);
});
},
terminate: function () {
this.worker.terminate();
window.URL.revokeObjectURL(this.url);
},
_createBlobString: function (cost) {
var source = `
var F = [${multi.activations.toString()}];
var cost = ${cost.toString()};
var multi = {
deserializeDataSet: ${multi.deserializeDataSet.toString()},
testSerializedSet: ${multi.testSerializedSet.toString()},
activateSerializedNetwork: ${multi.activateSerializedNetwork.toString()}
};
this.onmessage = function (e) {
if(typeof e.data.set === 'undefined'){
var A = new Float64Array(e.data.activations);
var S = new Float64Array(e.data.states);
var data = new Float64Array(e.data.conns);
var error = multi.testSerializedSet(set, cost, A, S, data, F);
var answer = { buffer: new Float64Array([error ]).buffer };
postMessage(answer, [answer.buffer]);
} else {
set = multi.deserializeDataSet(new Float64Array(e.data.set));
}
};`;
return source;
}
};

View File

@@ -0,0 +1,42 @@
/* Export */
module.exports = TestWorker;
/* Import */
var cp = require('child_process');
var path = require('path');
/*******************************************************************************
WEBWORKER
*******************************************************************************/
function TestWorker (dataSet, cost) {
this.worker = cp.fork(path.join(__dirname, '/worker'));
this.worker.send({ set: dataSet, cost: cost.name });
}
TestWorker.prototype = {
evaluate: function (network) {
return new Promise((resolve, reject) => {
var serialized = network.serialize();
var data = {
activations: serialized[0],
states: serialized[1],
conns: serialized[2]
};
var _that = this.worker;
this.worker.on('message', function callback (e) {
_that.removeListener('message', callback);
resolve(e);
});
this.worker.send(data);
});
},
terminate: function () {
this.worker.kill();
}
};

View File

@@ -0,0 +1,20 @@
var { multi, methods } = require('../../../neataptic');
var set = [];
var cost;
var F = multi.activations;
process.on('message', function (e) {
if (typeof e.set === 'undefined') {
var A = e.activations;
var S = e.states;
var data = e.conns;
var result = multi.testSerializedSet(set, cost, A, S, data, F);
process.send(result);
} else {
cost = methods.cost[e.cost];
set = multi.deserializeDataSet(e.set);
}
});

View File

@@ -0,0 +1,15 @@
/*******************************************************************************
WORKERS
*******************************************************************************/
var workers = {
node: {
TestWorker: require('./node/testworker')
},
browser: {
TestWorker: require('./browser/testworker')
}
};
/** Export */
module.exports = workers;

324
node_modules/neataptic/src/neat.js generated vendored Normal file
View File

@@ -0,0 +1,324 @@
/* Export */
module.exports = Neat;
/* Import */
var Network = require('./architecture/network');
var methods = require('./methods/methods');
var config = require('./config');
/* Easier variable naming */
var selection = methods.selection;
/*******************************************************************************
NEAT
*******************************************************************************/
function Neat (input, output, fitness, options) {
this.input = input; // The input size of the networks
this.output = output; // The output size of the networks
this.fitness = fitness; // The fitness function to evaluate the networks
// Configure options
options = options || {};
this.equal = options.equal || false;
this.clear = options.clear || false;
this.popsize = options.popsize || 50;
this.elitism = options.elitism || 0;
this.provenance = options.provenance || 0;
this.mutationRate = options.mutationRate || 0.3;
this.mutationAmount = options.mutationAmount || 1;
this.fitnessPopulation = options.fitnessPopulation || false;
this.selection = options.selection || methods.selection.POWER;
this.crossover = options.crossover || [
methods.crossover.SINGLE_POINT,
methods.crossover.TWO_POINT,
methods.crossover.UNIFORM,
methods.crossover.AVERAGE
];
this.mutation = options.mutation || methods.mutation.FFW;
this.template = options.network || false;
this.maxNodes = options.maxNodes || Infinity;
this.maxConns = options.maxConns || Infinity;
this.maxGates = options.maxGates || Infinity;
// Custom mutation selection function if given
this.selectMutationMethod = typeof options.mutationSelection === 'function' ? options.mutationSelection.bind(this) : this.selectMutationMethod;
// Generation counter
this.generation = 0;
// Initialise the genomes
this.createPool(this.template);
}
Neat.prototype = {
/**
* Create the initial pool of genomes
*/
createPool: function (network) {
this.population = [];
for (var i = 0; i < this.popsize; i++) {
var copy;
if (this.template) {
copy = Network.fromJSON(network.toJSON());
} else {
copy = new Network(this.input, this.output);
}
copy.score = undefined;
this.population.push(copy);
}
},
/**
* Evaluates, selects, breeds and mutates population
*/
evolve: async function () {
// Check if evaluated, sort the population
if (typeof this.population[this.population.length - 1].score === 'undefined') {
await this.evaluate();
}
this.sort();
var fittest = Network.fromJSON(this.population[0].toJSON());
fittest.score = this.population[0].score;
var newPopulation = [];
// Elitism
var elitists = [];
for (var i = 0; i < this.elitism; i++) {
elitists.push(this.population[i]);
}
// Provenance
for (i = 0; i < this.provenance; i++) {
newPopulation.push(Network.fromJSON(this.template.toJSON()));
}
// Breed the next individuals
for (i = 0; i < this.popsize - this.elitism - this.provenance; i++) {
newPopulation.push(this.getOffspring());
}
// Replace the old population with the new population
this.population = newPopulation;
this.mutate();
this.population.push(...elitists);
// Reset the scores
for (i = 0; i < this.population.length; i++) {
this.population[i].score = undefined;
}
this.generation++;
return fittest;
},
/**
* Breeds two parents into an offspring, population MUST be surted
*/
getOffspring: function () {
var parent1 = this.getParent();
var parent2 = this.getParent();
return Network.crossOver(parent1, parent2, this.equal);
},
/**
* Selects a random mutation method for a genome according to the parameters
*/
selectMutationMethod: function (genome) {
var mutationMethod = this.mutation[Math.floor(Math.random() * this.mutation.length)];
if (mutationMethod === methods.mutation.ADD_NODE && genome.nodes.length >= this.maxNodes) {
if (config.warnings) console.warn('maxNodes exceeded!');
return;
}
if (mutationMethod === methods.mutation.ADD_CONN && genome.connections.length >= this.maxConns) {
if (config.warnings) console.warn('maxConns exceeded!');
return;
}
if (mutationMethod === methods.mutation.ADD_GATE && genome.gates.length >= this.maxGates) {
if (config.warnings) console.warn('maxGates exceeded!');
return;
}
return mutationMethod;
},
/**
* Mutates the given (or current) population
*/
mutate: function () {
// Elitist genomes should not be included
for (var i = 0; i < this.population.length; i++) {
if (Math.random() <= this.mutationRate) {
for (var j = 0; j < this.mutationAmount; j++) {
var mutationMethod = this.selectMutationMethod(this.population[i]);
this.population[i].mutate(mutationMethod);
}
}
}
},
/**
* Evaluates the current population
*/
evaluate: async function () {
var i;
if (this.fitnessPopulation) {
if (this.clear) {
for (i = 0; i < this.population.length; i++) {
this.population[i].clear();
}
}
await this.fitness(this.population);
} else {
for (i = 0; i < this.population.length; i++) {
var genome = this.population[i];
if (this.clear) genome.clear();
genome.score = await this.fitness(genome);
}
}
},
/**
* Sorts the population by score
*/
sort: function () {
this.population.sort(function (a, b) {
return b.score - a.score;
});
},
/**
* Returns the fittest genome of the current population
*/
getFittest: function () {
// Check if evaluated
if (typeof this.population[this.population.length - 1].score === 'undefined') {
this.evaluate();
}
if (this.population[0].score < this.population[1].score) {
this.sort();
}
return this.population[0];
},
/**
* Returns the average fitness of the current population
*/
getAverage: function () {
if (typeof this.population[this.population.length - 1].score === 'undefined') {
this.evaluate();
}
var score = 0;
for (var i = 0; i < this.population.length; i++) {
score += this.population[i].score;
}
return score / this.population.length;
},
/**
* Gets a genome based on the selection function
* @return {Network} genome
*/
getParent: function () {
var i;
switch (this.selection) {
case selection.POWER:
if (this.population[0].score < this.population[1].score) this.sort();
var index = Math.floor(Math.pow(Math.random(), this.selection.power) * this.population.length);
return this.population[index];
case selection.FITNESS_PROPORTIONATE:
// As negative fitnesses are possible
// https://stackoverflow.com/questions/16186686/genetic-algorithm-handling-negative-fitness-values
// this is unnecessarily run for every individual, should be changed
var totalFitness = 0;
var minimalFitness = 0;
for (i = 0; i < this.population.length; i++) {
var score = this.population[i].score;
minimalFitness = score < minimalFitness ? score : minimalFitness;
totalFitness += score;
}
minimalFitness = Math.abs(minimalFitness);
totalFitness += minimalFitness * this.population.length;
var random = Math.random() * totalFitness;
var value = 0;
for (i = 0; i < this.population.length; i++) {
let genome = this.population[i];
value += genome.score + minimalFitness;
if (random < value) return genome;
}
// if all scores equal, return random genome
return this.population[Math.floor(Math.random() * this.population.length)];
case selection.TOURNAMENT:
if (this.selection.size > this.popsize) {
throw new Error('Your tournament size should be lower than the population size, please change methods.selection.TOURNAMENT.size');
}
// Create a tournament
var individuals = [];
for (i = 0; i < this.selection.size; i++) {
let random = this.population[Math.floor(Math.random() * this.population.length)];
individuals.push(random);
}
// Sort the tournament individuals by score
individuals.sort(function (a, b) {
return b.score - a.score;
});
// Select an individual
for (i = 0; i < this.selection.size; i++) {
if (Math.random() < this.selection.probability || i === this.selection.size - 1) {
return individuals[i];
}
}
}
},
/**
* Export the current population to a json object
*/
export: function () {
var json = [];
for (var i = 0; i < this.population.length; i++) {
var genome = this.population[i];
json.push(genome.toJSON());
}
return json;
},
/**
* Import population from a json object
*/
import: function (json) {
var population = [];
for (var i = 0; i < json.length; i++) {
var genome = json[i];
population.push(Network.fromJSON(genome));
}
this.population = population;
this.popsize = population.length;
}
};

35
node_modules/neataptic/src/neataptic.js generated vendored Normal file
View File

@@ -0,0 +1,35 @@
var Neataptic = {
methods: require('./methods/methods'),
Connection: require('./architecture/connection'),
architect: require('./architecture/architect'),
Network: require('./architecture/network'),
config: require('./config'),
Group: require('./architecture/group'),
Layer: require('./architecture/layer'),
Node: require('./architecture/node'),
Neat: require('./neat'),
multi: require('./multithreading/multi')
};
// CommonJS & AMD
if (typeof define !== 'undefined' && define.amd) {
define([], function () { return Neataptic; });
}
// Node.js
if (typeof module !== 'undefined' && module.exports) {
module.exports = Neataptic;
}
// Browser
if (typeof window === 'object') {
(function () {
var old = window['neataptic'];
Neataptic.ninja = function () {
window['neataptic'] = old;
return Neataptic;
};
})();
window['neataptic'] = Neataptic;
}