lysergic
Version:
Synaptic's neural network compiler
217 lines • 8.02 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const activations_1 = require("./ast/activations");
class Topology {
constructor(options) {
this.heap = null;
this.biasUnit = null;
this.inputsOf = [];
this.unitParameters = [];
this.projectedBy = [];
this.gatersOf = [];
this.gatedBy = [];
this.inputsOfGatedBy = [];
this.projectionSet = [];
this.gateSet = [];
this.inputSet = [];
this.connections = [];
this.gates = [];
this.layers = [];
this.activationFunction = [];
this.units = 0;
const { heap } = options;
this.heap = heap;
this.biasUnit = this.addUnit({ bias: false });
this.heap.setVariable('state', this.biasUnit, 1);
this.heap.setVariable('activation', this.biasUnit, 1);
}
normalize2D(key) {
let arr = this[key];
if (!(arr instanceof Array)) {
this[key] = [];
return;
}
else {
for (let i in arr) {
this[key][i] = this[key][i] || [];
}
}
}
normalize3D(key) {
let arr = this[key];
if (!(arr instanceof Array)) {
this[key] = [];
return;
}
else {
for (let i in arr) {
let subArr = arr[i];
if (!(subArr instanceof Array)) {
subArr[i] = [];
}
else {
for (let i in subArr) {
subArr[i] = subArr[i] || [];
}
}
}
}
}
normalize() {
this.normalize2D('inputsOf');
this.normalize2D('projectedBy');
this.normalize2D('gatersOf');
this.normalize2D('gatedBy');
this.normalize3D('inputsOfGatedBy');
this.normalize2D('projectionSet');
this.normalize2D('gateSet');
this.normalize2D('inputSet');
this.normalize2D('layers');
}
addUnit(options = {}) {
const { bias = true, activationFunction = activations_1.ActivationTypes.LOGISTIC_SIGMOID, l1 = 0, l2 = 0, parameters = [] } = options;
const unit = this.units++;
this.inputsOf[unit] = [];
this.projectedBy[unit] = [];
this.gatersOf[unit] = [];
this.gatedBy[unit] = [];
this.inputsOfGatedBy[unit] = [];
this.inputSet[unit] = [];
this.projectionSet[unit] = [];
this.gateSet[unit] = [];
this.unitParameters[unit] = {
l1,
l2,
parameters
};
this.activationFunction[unit] = activationFunction;
this.heap.setVariable('state', unit, 0);
this.heap.setVariable('activation', unit, 0);
this.heap.setVariable('derivative', unit, 0);
this.heap.setVariable('gain', unit, unit, 1);
this.heap.setVariable('elegibilityTrace', unit, unit, 0);
this.heap.setVariable('errorResponsibility', unit, 0);
this.heap.setVariable('projectedErrorResponsibility', unit, 0);
this.heap.setVariable('gatedErrorResponsibility', unit, 0);
if (bias) {
this.addConnection(this.biasUnit, unit, 1);
}
return unit;
}
addConnection(from, to, weight) {
if (this.connections.some(connection => connection.from === from && connection.to === to)) {
return;
}
this.connections.push({ from, to });
const isSelfConnection = (from === to);
this.heap.setVariable('gain', to, from, 1);
this.heap.setVariable('gradient', to, from, 0);
this.heap.setVariable('weight', to, from, isSelfConnection ? 1 : weight);
this.heap.setVariable('elegibilityTrace', to, from, 0);
this.track(to);
this.track(from);
}
addGate(from, to, gater) {
const alreadyGated = this.gates.some(gate => gate.from === from && gate.to === to);
const isBias = from === this.biasUnit;
if (alreadyGated || isBias) {
return;
}
this.gates.push({ from, to, gater });
this.track(to);
this.track(from);
this.track(gater);
}
addLayer(size = 0, options) {
const layer = [];
for (let i = 0; i < size; i++) {
const unit = this.addUnit(options);
layer.push(unit);
}
this.layers.push(layer);
return layer;
}
track(unit) {
this.inputsOf[unit] = distinct(this.connections
.filter(connection => connection.to === unit)
.map(connection => connection.from));
this.projectedBy[unit] = distinct(this.connections
.filter(connection => connection.from === unit)
.map(connection => connection.to));
this.gatersOf[unit] = distinct(this.gates
.filter(gate => gate.to === unit)
.map(gate => gate.gater));
this.gatedBy[unit] = distinct(this.gates
.filter(gate => gate.gater === unit)
.map(gate => gate.to));
this.inputsOf[unit].forEach(i => {
this.gatedBy[unit].forEach(k => {
this.heap.setVariable('extendedElegibilityTrace', unit, i, k, 0);
});
});
this.projectedBy[unit].forEach(j => {
this.gatedBy[j].forEach(k => {
this.heap.setVariable('extendedElegibilityTrace', j, unit, k, 0);
});
});
this.gatersOf[unit].forEach(j => {
this.inputsOf[j].forEach(i => {
this.heap.setVariable('extendedElegibilityTrace', j, i, unit, 0);
});
});
this.inputsOf[unit].forEach(i => {
this.gatersOf[unit].forEach(j => {
this.inputsOfGatedBy[unit][j] = distinct(this.inputsOfGatedBy[unit][j], this.gates
.filter(gate => gate.gater === j && gate.to === unit && gate.from === i)
.map(gate => gate.from));
});
});
this.gatedBy[unit].forEach(k => {
this.inputsOf[k].forEach(i => {
this.inputsOfGatedBy[k][unit] = distinct(this.inputsOfGatedBy[k][unit], this.gates
.filter(gate => gate.gater === unit && gate.to === k && gate.from === i)
.map(gate => gate.from));
});
});
this.gatedBy[unit].forEach(k => {
if (this.gates.some(gate => gate.to === k && gate.from === k && gate.gater === unit)) {
this.heap.setVariable('derivativeTerm', k, unit, 1);
}
});
this.gatersOf[unit].forEach(j => {
if (this.gates.some(gate => gate.to === unit && gate.from === unit && gate.gater === j)) {
this.heap.setVariable('derivativeTerm', unit, j, 1);
}
});
this.inputSet[unit] = this.inputsOf[unit].filter(input => input !== unit);
this.projectionSet[unit] = this.projectedBy[unit].filter(projected => projected > unit);
this.gateSet[unit] = this.gatedBy[unit].filter(gated => gated > unit);
}
toJSON() {
return {
biasUnit: this.biasUnit,
inputsOf: this.inputsOf,
projectedBy: this.projectedBy,
gatersOf: this.gatersOf,
gatedBy: this.gatedBy,
inputsOfGatedBy: this.inputsOfGatedBy,
projectionSet: this.projectionSet,
gateSet: this.gateSet,
inputSet: this.inputSet,
connections: this.connections,
gates: this.gates,
layers: this.layers
};
}
}
exports.Topology = Topology;
function distinct(...arrays) {
const concated = arrays.reduce((concated, array) => concated.concat(array || []), []);
let o = {}, a = [], i;
for (i = 0; i < concated.length; o[concated[i++]] = 1)
;
for (i in o)
a.push(+i);
return a;
}
//# sourceMappingURL=Topology.js.map