UNPKG

novabrain

Version:

Neural network library for NodeJS and browser

538 lines (425 loc) 20.2 kB
var Novabrain = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; module.exports = { Neuron: __webpack_require__(1), Layer: __webpack_require__(3), Network: __webpack_require__(4), Trainer: __webpack_require__(5), Transfer: __webpack_require__(2), Samples: __webpack_require__(6) }; /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var Transfer = __webpack_require__(2); var Neuron = (function () { function Neuron(size) { _classCallCheck(this, Neuron); this.bias = Math.random() * 0.4 - 0.2; this.weights = []; this.changes = []; this.error = 0; this.delta = 0; for (var i = 0; i < size; i++) { this.weights.push(Math.random() * 0.4 - 0.2); this.changes.push(0); } } _createClass(Neuron, [{ key: 'output', value: function output(inputs, transfer) { if (!Array.isArray(inputs)) { throw new Error('Inputs array expected'); } if (inputs.length !== this.weights.length) { throw new Error('Inputs length ' + this.weights.length + ' expected'); } transfer = transfer || Transfer.LOGISTIC; var sum = this.bias; for (var i = 0, imax = this.weights.length; i < imax; i++) { sum += this.weights[i] * inputs[i]; } return transfer(sum); } }, { key: 'export', value: function _export() { return { bias: this.bias, weights: this.weights.slice() }; } }]); return Neuron; })(); module.exports = Neuron; /***/ }, /* 2 */ /***/ function(module, exports) { 'use strict'; module.exports = { LOGISTIC: function LOGISTIC(sum) { return 1 / (1 + Math.exp(-sum)); }, HARDLIMIT: function HARDLIMIT(sum) { return sum > 0 ? 1 : 0; }, BOOLEAN: function BOOLEAN(sum) { return sum > 0 ? true : false; }, IDENTITY: function IDENTITY(sum) { return sum; }, TANH: function TANH(sum) { var eP = Math.exp(sum); var eN = 1 / eP; return (eP - eN) / (eP + eN); } }; /***/ }, /* 3 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var Neuron = __webpack_require__(1); var Layer = (function () { function Layer(numberOfNeurons, sizeOfNeurons) { _classCallCheck(this, Layer); this.neurons = []; for (var i = 0; i < numberOfNeurons; i++) { this.neurons.push(new Neuron(sizeOfNeurons)); } } _createClass(Layer, [{ key: 'output', value: function output(inputs, transfer) { var results = []; for (var i = 0; i < this.neurons.length; i++) { results.push(this.neurons[i].output(inputs, transfer)); } return results; } }, { key: 'export', value: function _export() { var json = []; for (var i = 0; i < this.neurons.length; i++) { json.push(this.neurons[i]['export']()); } return json; } }]); return Layer; })(); module.exports = Layer; /***/ }, /* 4 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var Layer = __webpack_require__(3); var Transfer = __webpack_require__(2); var Network = (function () { function Network() { _classCallCheck(this, Network); this.layers = []; var args = Array.prototype.slice.call(arguments); if (args < 2) { throw new Error('Network expected 2 integers or more'); } if (args.length === 2) { args.splice(1, 0, Math.max(3, Math.floor(args[0] / 2))); } this.layers.push(new Layer(args[0], 1)); for (var i = 1; i < args.length; i++) { this.layers.push(new Layer(args[i], this.layers[i - 1].neurons.length)); } this.transfer = Transfer.LOGISTIC; } _createClass(Network, [{ key: 'output', value: function output(inputs, transfer) { var outputs = []; for (var i = 1; i < this.layers.length; i++) { outputs = inputs = this.layers[i].output(inputs, transfer || this.transfer); } return outputs; } }, { key: 'export', value: function _export() { var json = []; for (var i = 0; i < this.layers.length; i++) { json.push(this.layers[i]['export']()); } return json; } }, { key: 'import', value: function _import(layers) { if (layers instanceof Network) { layers = layers['export'](); } if (layers.length !== this.layers.length) { throw new Error('Network expected [' + this.layers.length + '] layers'); } for (var i = 0; i < this.layers.length; i++) { var neurons = this.layers[i].neurons; if (layers[i].length !== neurons.length) { throw new Error('Layer [' + i + '] expected [' + neurons.length + '] neurons'); } for (var j = 0; j < neurons.length; j++) { var neuron = neurons[j]; if (layers[i][j].bias === undefined) { throw new Error('Neuron [' + j + '] expected a [bias] value'); } neuron.bias = layers[i][j].bias; if (!Array.isArray(layers[i][j].weights)) { throw new Error('Neuron [' + j + '] expected a [weights] array of [' + neuron.weights.length + '] values'); } for (var k = 0; k < neuron.weights.length; k++) { neuron.weights[k] = layers[i][j].weights[k]; } } } return this; } }, { key: 'standalone', value: function standalone(transfer) { transfer = Transfer.LOGISTIC.toString(); var layers = JSON.stringify(this['export']()); var buffer = ''; buffer += 'transfer = transfer || ' + transfer + ';'; buffer += 'var layers = ' + layers + ';'; buffer += 'for (var i = 1; i < layers.length; i++) {'; buffer += 'var layer = layers[i];'; buffer += 'var outputs = [];'; buffer += 'for (var j = 0; j < layer.length; j++) {'; buffer += 'var neuron = layer[j];'; buffer += 'var result = neuron.bias;'; buffer += 'for (var k = 0; k < neuron.weights.length; k++) {'; buffer += 'result += neuron.weights[k] * inputs[k];'; buffer += '}'; buffer += 'outputs[j] = transfer(result);'; buffer += '}'; buffer += 'inputs = outputs;'; buffer += '}'; buffer += 'return outputs;'; return new Function("inputs", "transfer", buffer); } }]); return Network; })(); module.exports = Network; /***/ }, /* 5 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var Network = __webpack_require__(4); var Trainer = (function () { function Trainer(network) { _classCallCheck(this, Trainer); if (!(network instanceof Network)) { throw new Error('Network instance expected'); } this.network = network; this.inputSize = network.layers[0].neurons.length; this.outputSize = network.layers[network.layers.length - 1].neurons.length; this.nbLayers = this.network.layers.length; this.lastLayerId = this.nbLayers - 1; } // // Trainer.train // // Train the network with back propagation // // @param Array : Training data // @param options.iterations : The number of back propagation iterations // @param options.learning : Learning rate // @param options.momentum : Reduction rate // @param options.treshold : Error treshold to break iterations loop // @param options.callback : Callback function for log // @param options.interval : Callback function interval // @return Object // _createClass(Trainer, [{ key: 'train', value: function train(data, options) { options = options || {}; options.iterations = options.iterations || 20000; options.learning = options.learning || 0.3; options.momentum = options.momentum || 0.1; options.treshold = options.treshold || 0.005; options.callback = options.callback || null; options.interval = options.interval || 10; if (!(Array.isArray(data[0].input) && data[0].input.length === this.inputSize)) { throw new Error('Train expected an input data array of ' + this.inputSize); } if (!(Array.isArray(data[0].output) && data[0].output.length === this.outputSize)) { throw new Error('Train expected an output data array of ' + this.outputSize); } var timeStart = new Date().getTime(); var result = { error: 10, iterations: 0, time: 0 }; for (var i = 0; i < options.iterations && result.error > options.treshold; i++) { var iterationError = 0; for (var j = 0; j < data.length; j++) { iterationError += this.trainPattern(data[j].input, data[j].output, options.learning, options.momentum); } result.error = iterationError / data.length; if (options.callback && i % options.interval == 0) { options.callback(result); } result.iterations++; result.time = new Date().getTime() - timeStart; } return result; } }, { key: 'trainPattern', value: function trainPattern(input, target, learning, momentum) { learning = learning || 0.3; momentum = momentum || 0.1; var outputs = this.getOutputs(input); // Calculate errors and deltas for (var layerId = this.lastLayerId; layerId >= 0; layerId--) { var neurons = this.network.layers[layerId].neurons; for (var neuronId = 0; neuronId < neurons.length; neuronId++) { var output = outputs[layerId][neuronId]; var neuronError = 0; if (layerId === this.lastLayerId) { neuronError = target[neuronId] - output; } else { var nextLayerNeurons = this.network.layers[layerId + 1].neurons; for (var k = 0; k < nextLayerNeurons.length; k++) { neuronError += nextLayerNeurons[k].delta * nextLayerNeurons[k].weights[neuronId]; } } neurons[neuronId].error = neuronError; neurons[neuronId].delta = neuronError * output * (1 - output); } } // Back propagate for (var layerId = 1; layerId < this.nbLayers; layerId++) { var incoming = outputs[layerId - 1]; var neurons = this.network.layers[layerId].neurons; for (var neuronId = 0; neuronId < neurons.length; neuronId++) { var neuron = neurons[neuronId]; var delta = neuron.delta; for (var k = 0; k < incoming.length; k++) { var change = neuron.changes[k]; change = learning * delta * incoming[k] + momentum * change; neuron.weights[k] += change; neuron.changes[k] = change; } neuron.bias += learning * delta; } } var errors = []; var neurons = this.network.layers[this.lastLayerId].neurons; for (var i = 0; i < neurons.length; i++) { errors.push(neurons[i].error); } return this.getErrorSum(errors); } }, { key: 'getOutputs', value: function getOutputs(inputs) { var outputs = []; var output = outputs[0] = inputs.slice(); var layers = this.network.layers; for (var i = 1; i < layers.length; i++) { output = outputs[i] = layers[i].output(output); } return outputs; } }, { key: 'getErrorSum', value: function getErrorSum(errors) { var sum = 0; for (var i = 0; i < errors.length; i++) { sum += Math.pow(errors[i], 2); } return sum / errors.length; } }]); return Trainer; })(); module.exports = Trainer; /***/ }, /* 6 */ /***/ function(module, exports) { 'use strict'; module.exports = { XOR: { training: [{ input: [0, 0], output: [0] }, { input: [0, 1], output: [1] }, { input: [1, 0], output: [1] }, { input: [1, 1], output: [0] }], config: [[{ bias: 0.1804561257362366, weights: [-0.167204974219203] }, { bias: -0.04569602627307176, weights: [0.18746992871165274] }], [{ bias: 4.594158542478944, weights: [-3.040062330305626, -3.362846210091373] }, { bias: 2.253482826600183, weights: [-5.98762513515333, -5.965287921412066] }, { bias: 2.2578395038508865, weights: [-2.0587523788017017, -1.562316369066697] }], [{ bias: -3.8152869540660492, weights: [5.941256505289369, -8.507284881253804, 3.1455340193310843] }]] }, AND: { training: [{ input: [0, 0], output: [0] }, { input: [0, 1], output: [0] }, { input: [1, 0], output: [0] }, { input: [1, 1], output: [1] }], config: [[{ bias: 0.05568741559982299, weights: [-0.07880215616896749] }, { bias: 0.11339050624519587, weights: [-0.08192619075998664] }], [{ bias: 1.2162003373115722, weights: [-1.5325596790646399, -1.6694862833366626] }, { bias: 3.5218949042093537, weights: [-2.9473826605615274, -2.6480166644816325] }, { bias: 1.2894144846904376, weights: [-1.3971381146583233, -1.8841189975945027] }], [{ bias: 3.4025251093426854, weights: [-2.7717050850924494, -5.672159962134176, -2.836860716358213] }]] }, OR: { training: [{ input: [0, 0], output: [0] }, { input: [0, 1], output: [1] }, { input: [1, 0], output: [1] }, { input: [1, 1], output: [1] }], config: [[{ bias: 0.023853175062686194, weights: [-0.05087699200958015] }, { bias: -0.04783560279756785, weights: [-0.12696466147899627] }], [{ bias: 0.7767897854256859, weights: [-1.7520145026333327, -1.7771349756367834] }, { bias: -0.47207093390546423, weights: [1.0731066688291095, 1.040178424526655] }, { bias: -1.5422804887749049, weights: [3.1529762364879015, 3.1483531621536285] }], [{ bias: -1.2640437852289894, weights: [-3.1821062179619575, 1.162433847357973, 4.845167062525612] }]] } }; /***/ } /******/ ]); //# sourceMappingURL=novabrain.js.map