greataptic
Version:
A simplistic neural network library.
1,667 lines (1,408 loc) • 179 kB
JavaScript
require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
function _logit(x) {
return Math.log(x / (1 - x));
}
let Vector = module.exports.Vector = class Vector {
constructor(data) {
if (data.data != null) data = data.data;
this.data = Array.from(data);
this.dims = this.data.length;
}
co(coord) {
return this.data[coord] != null ? this.data[coord] : null;
}
size() {
return Math.sqrt(this.data.reduce((a, b) => a + Math.pow(b, 2), 0));
}
sum() {
return this.data.reduce((a, b) => a + b, 0);
}
add(_b) {
let b = _b.dims != null ? _b : new Vector(_b);
let res = [];
for (let i = 0; i < Math.min(this.dims, b.dims); i++) res[i] = this.data[i] + b.data[i];
return new Vector(res);
}
pow(pow) {
return new Vector(this.data.map(x => Math.pow(x, pow)));
}
sub(_b) {
let b = _b.dims != null ? _b : new Vector(_b);
let res = [];
for (let i = 0; i < Math.min(this.dims, b.dims); i++) res[i] = this.data[i] - b.data[i];
return new Vector(res);
}
multiplyVec(_b) {
let b = _b.dims != null ? _b : new Vector(_b);
let res = [];
for (let i = 0; i < Math.min(this.dims, b.dims); i++) res[i] = this.data[i] * b.data[i];
return new Vector(res);
}
divideVec(_b) {
let b = _b.dims != null ? _b : new Vector(_b);
let res = [];
for (let i = 0; i < Math.min(this.dims, b.dims); i++) res[i] = this.data[i] / b.data[i];
return new Vector(res);
}
multiplyFac(b) {
return new Vector(this.data.map(a => a * b));
}
divideFac(b) {
return new Vector(this.data.map(a => a / b));
}
combiner(combinerFunc) {
return function (b) {
if (!b.dims) b = new Vector(b);
return new Vector(this.data.map((x, i) => combinerFunc(x, b.data[i])));
};
}
map(func) {
return new Vector(this.data.map(func));
}
dot(b) {
if (this.data.length === 0 || b.dims === 0) return 0;
let res = 0;
for (let i = 0; i < Math.min(this.dims, b.dims); i++) res += this.data[i] * b.data[i];
return res;
}
static is(vec) {
return !!(vec && vec.data && vec.dims && vec.size && vec.combiner && vec.map);
}
static fill(opts) {
if (opts.map != null) return new Vector(new Array(opts.length).fill(0).map((_, i, a) => opts.map(i, a)));else return new Vector(new Array(opts.length).fill(opts.value != null ? opts.value : 0));
}
static random(dims) {
return new Vector(new Array(dims).fill(0).map(() => _logit(0.25 + 0.5 * Math.random())));
}
static randomOne() {
return _logit(0.25 + 0.5 * Math.random());
}
static randomSize(dims, size) {
return new Vector(new Array(dims).fill(0).map(() => (Math.random() * 2 - 1) * size));
}
static zero(dims) {
return new Vector(new Array(dims).fill(0));
}
};
},{}],2:[function(require,module,exports){
if (typeof Object.create === 'function') {
// implementation from standard node.js 'util' module
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
} else {
// old school shim for old browsers
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
var TempCtor = function () {}
TempCtor.prototype = superCtor.prototype
ctor.prototype = new TempCtor()
ctor.prototype.constructor = ctor
}
}
},{}],3:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
// cached from whatever global is present so that test runners that stub it
// don't break things. But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals. It's inside a
// function because try/catches deoptimize in certain engines.
var cachedSetTimeout;
var cachedClearTimeout;
function defaultSetTimout() {
throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout () {
throw new Error('clearTimeout has not been defined');
}
(function () {
try {
if (typeof setTimeout === 'function') {
cachedSetTimeout = setTimeout;
} else {
cachedSetTimeout = defaultSetTimout;
}
} catch (e) {
cachedSetTimeout = defaultSetTimout;
}
try {
if (typeof clearTimeout === 'function') {
cachedClearTimeout = clearTimeout;
} else {
cachedClearTimeout = defaultClearTimeout;
}
} catch (e) {
cachedClearTimeout = defaultClearTimeout;
}
} ())
function runTimeout(fun) {
if (cachedSetTimeout === setTimeout) {
//normal enviroments in sane situations
return setTimeout(fun, 0);
}
// if setTimeout wasn't available but was latter defined
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
cachedSetTimeout = setTimeout;
return setTimeout(fun, 0);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedSetTimeout(fun, 0);
} catch(e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedSetTimeout.call(null, fun, 0);
} catch(e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
return cachedSetTimeout.call(this, fun, 0);
}
}
}
function runClearTimeout(marker) {
if (cachedClearTimeout === clearTimeout) {
//normal enviroments in sane situations
return clearTimeout(marker);
}
// if clearTimeout wasn't available but was latter defined
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
cachedClearTimeout = clearTimeout;
return clearTimeout(marker);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedClearTimeout(marker);
} catch (e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedClearTimeout.call(null, marker);
} catch (e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
return cachedClearTimeout.call(this, marker);
}
}
}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
if (!draining || !currentQueue) {
return;
}
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = runTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
runClearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
runTimeout(drainQueue);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.prependListener = noop;
process.prependOnceListener = noop;
process.listeners = function (name) { return [] }
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };
},{}],4:[function(require,module,exports){
'use strict';
/**
* Randomize the order of the elements in a given array.
* @param {Array} arr - The given array.
* @param {Object} [options] - Optional configuration options.
* @param {Boolean} [options.copy] - Sets if should return a shuffled copy of the given array. By default it's a falsy value.
* @param {Function} [options.rng] - Specifies a custom random number generator.
* @returns {Array}
*/
function shuffle(arr, options) {
if (!Array.isArray(arr)) {
throw new Error('shuffle expect an array as parameter.');
}
options = options || {};
var collection = arr,
len = arr.length,
rng = options.rng || Math.random,
random,
temp;
if (options.copy === true) {
collection = arr.slice();
}
while (len) {
random = Math.floor(rng() * len);
len -= 1;
temp = collection[len];
collection[len] = collection[random];
collection[random] = temp;
}
return collection;
};
/**
* Pick one or more random elements from the given array.
* @param {Array} arr - The given array.
* @param {Object} [options] - Optional configuration options.
* @param {Number} [options.picks] - Specifies how many random elements you want to pick. By default it picks 1.
* @param {Function} [options.rng] - Specifies a custom random number generator.
* @returns {Object}
*/
shuffle.pick = function(arr, options) {
if (!Array.isArray(arr)) {
throw new Error('shuffle.pick() expect an array as parameter.');
}
options = options || {};
var rng = options.rng || Math.random,
picks = options.picks || 1;
if (typeof picks === 'number' && picks !== 1) {
var len = arr.length,
collection = arr.slice(),
random = [],
index;
while (picks && len) {
index = Math.floor(rng() * len);
random.push(collection[index]);
collection.splice(index, 1);
len -= 1;
picks -= 1;
}
return random;
}
return arr[Math.floor(rng() * arr.length)];
};
/**
* Expose
*/
module.exports = shuffle;
},{}],5:[function(require,module,exports){
module.exports = function isBuffer(arg) {
return arg && typeof arg === 'object'
&& typeof arg.copy === 'function'
&& typeof arg.fill === 'function'
&& typeof arg.readUInt8 === 'function';
}
},{}],6:[function(require,module,exports){
(function (process,global){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var formatRegExp = /%[sdj%]/g;
exports.format = function(f) {
if (!isString(f)) {
var objects = [];
for (var i = 0; i < arguments.length; i++) {
objects.push(inspect(arguments[i]));
}
return objects.join(' ');
}
var i = 1;
var args = arguments;
var len = args.length;
var str = String(f).replace(formatRegExp, function(x) {
if (x === '%%') return '%';
if (i >= len) return x;
switch (x) {
case '%s': return String(args[i++]);
case '%d': return Number(args[i++]);
case '%j':
try {
return JSON.stringify(args[i++]);
} catch (_) {
return '[Circular]';
}
default:
return x;
}
});
for (var x = args[i]; i < len; x = args[++i]) {
if (isNull(x) || !isObject(x)) {
str += ' ' + x;
} else {
str += ' ' + inspect(x);
}
}
return str;
};
// Mark that a method should not be used.
// Returns a modified function which warns once by default.
// If --no-deprecation is set, then it is a no-op.
exports.deprecate = function(fn, msg) {
// Allow for deprecating things in the process of starting up.
if (isUndefined(global.process)) {
return function() {
return exports.deprecate(fn, msg).apply(this, arguments);
};
}
if (process.noDeprecation === true) {
return fn;
}
var warned = false;
function deprecated() {
if (!warned) {
if (process.throwDeprecation) {
throw new Error(msg);
} else if (process.traceDeprecation) {
console.trace(msg);
} else {
console.error(msg);
}
warned = true;
}
return fn.apply(this, arguments);
}
return deprecated;
};
var debugs = {};
var debugEnviron;
exports.debuglog = function(set) {
if (isUndefined(debugEnviron))
debugEnviron = process.env.NODE_DEBUG || '';
set = set.toUpperCase();
if (!debugs[set]) {
if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
var pid = process.pid;
debugs[set] = function() {
var msg = exports.format.apply(exports, arguments);
console.error('%s %d: %s', set, pid, msg);
};
} else {
debugs[set] = function() {};
}
}
return debugs[set];
};
/**
* Echos the value of a value. Trys to print the value out
* in the best way possible given the different types.
*
* @param {Object} obj The object to print out.
* @param {Object} opts Optional options object that alters the output.
*/
/* legacy: obj, showHidden, depth, colors*/
function inspect(obj, opts) {
// default options
var ctx = {
seen: [],
stylize: stylizeNoColor
};
// legacy...
if (arguments.length >= 3) ctx.depth = arguments[2];
if (arguments.length >= 4) ctx.colors = arguments[3];
if (isBoolean(opts)) {
// legacy...
ctx.showHidden = opts;
} else if (opts) {
// got an "options" object
exports._extend(ctx, opts);
}
// set default options
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
if (isUndefined(ctx.depth)) ctx.depth = 2;
if (isUndefined(ctx.colors)) ctx.colors = false;
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
if (ctx.colors) ctx.stylize = stylizeWithColor;
return formatValue(ctx, obj, ctx.depth);
}
exports.inspect = inspect;
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
inspect.colors = {
'bold' : [1, 22],
'italic' : [3, 23],
'underline' : [4, 24],
'inverse' : [7, 27],
'white' : [37, 39],
'grey' : [90, 39],
'black' : [30, 39],
'blue' : [34, 39],
'cyan' : [36, 39],
'green' : [32, 39],
'magenta' : [35, 39],
'red' : [31, 39],
'yellow' : [33, 39]
};
// Don't use 'blue' not visible on cmd.exe
inspect.styles = {
'special': 'cyan',
'number': 'yellow',
'boolean': 'yellow',
'undefined': 'grey',
'null': 'bold',
'string': 'green',
'date': 'magenta',
// "name": intentionally not styling
'regexp': 'red'
};
function stylizeWithColor(str, styleType) {
var style = inspect.styles[styleType];
if (style) {
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
'\u001b[' + inspect.colors[style][1] + 'm';
} else {
return str;
}
}
function stylizeNoColor(str, styleType) {
return str;
}
function arrayToHash(array) {
var hash = {};
array.forEach(function(val, idx) {
hash[val] = true;
});
return hash;
}
function formatValue(ctx, value, recurseTimes) {
// Provide a hook for user-specified inspect functions.
// Check that value is an object with an inspect function on it
if (ctx.customInspect &&
value &&
isFunction(value.inspect) &&
// Filter out the util module, it's inspect function is special
value.inspect !== exports.inspect &&
// Also filter out any prototype objects using the circular check.
!(value.constructor && value.constructor.prototype === value)) {
var ret = value.inspect(recurseTimes, ctx);
if (!isString(ret)) {
ret = formatValue(ctx, ret, recurseTimes);
}
return ret;
}
// Primitive types cannot have properties
var primitive = formatPrimitive(ctx, value);
if (primitive) {
return primitive;
}
// Look up the keys of the object.
var keys = Object.keys(value);
var visibleKeys = arrayToHash(keys);
if (ctx.showHidden) {
keys = Object.getOwnPropertyNames(value);
}
// IE doesn't make error fields non-enumerable
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
if (isError(value)
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
return formatError(value);
}
// Some type of object without properties can be shortcutted.
if (keys.length === 0) {
if (isFunction(value)) {
var name = value.name ? ': ' + value.name : '';
return ctx.stylize('[Function' + name + ']', 'special');
}
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
}
if (isDate(value)) {
return ctx.stylize(Date.prototype.toString.call(value), 'date');
}
if (isError(value)) {
return formatError(value);
}
}
var base = '', array = false, braces = ['{', '}'];
// Make Array say that they are Array
if (isArray(value)) {
array = true;
braces = ['[', ']'];
}
// Make functions say that they are functions
if (isFunction(value)) {
var n = value.name ? ': ' + value.name : '';
base = ' [Function' + n + ']';
}
// Make RegExps say that they are RegExps
if (isRegExp(value)) {
base = ' ' + RegExp.prototype.toString.call(value);
}
// Make dates with properties first say the date
if (isDate(value)) {
base = ' ' + Date.prototype.toUTCString.call(value);
}
// Make error with message first say the error
if (isError(value)) {
base = ' ' + formatError(value);
}
if (keys.length === 0 && (!array || value.length == 0)) {
return braces[0] + base + braces[1];
}
if (recurseTimes < 0) {
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
} else {
return ctx.stylize('[Object]', 'special');
}
}
ctx.seen.push(value);
var output;
if (array) {
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
} else {
output = keys.map(function(key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
});
}
ctx.seen.pop();
return reduceToSingleString(output, base, braces);
}
function formatPrimitive(ctx, value) {
if (isUndefined(value))
return ctx.stylize('undefined', 'undefined');
if (isString(value)) {
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
.replace(/'/g, "\\'")
.replace(/\\"/g, '"') + '\'';
return ctx.stylize(simple, 'string');
}
if (isNumber(value))
return ctx.stylize('' + value, 'number');
if (isBoolean(value))
return ctx.stylize('' + value, 'boolean');
// For some reason typeof null is "object", so special case here.
if (isNull(value))
return ctx.stylize('null', 'null');
}
function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']';
}
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
for (var i = 0, l = value.length; i < l; ++i) {
if (hasOwnProperty(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
String(i), true));
} else {
output.push('');
}
}
keys.forEach(function(key) {
if (!key.match(/^\d+$/)) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
key, true));
}
});
return output;
}
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str, desc;
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
if (desc.get) {
if (desc.set) {
str = ctx.stylize('[Getter/Setter]', 'special');
} else {
str = ctx.stylize('[Getter]', 'special');
}
} else {
if (desc.set) {
str = ctx.stylize('[Setter]', 'special');
}
}
if (!hasOwnProperty(visibleKeys, key)) {
name = '[' + key + ']';
}
if (!str) {
if (ctx.seen.indexOf(desc.value) < 0) {
if (isNull(recurseTimes)) {
str = formatValue(ctx, desc.value, null);
} else {
str = formatValue(ctx, desc.value, recurseTimes - 1);
}
if (str.indexOf('\n') > -1) {
if (array) {
str = str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n').substr(2);
} else {
str = '\n' + str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n');
}
}
} else {
str = ctx.stylize('[Circular]', 'special');
}
}
if (isUndefined(name)) {
if (array && key.match(/^\d+$/)) {
return str;
}
name = JSON.stringify('' + key);
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\\'")
.replace(/\\"/g, '"')
.replace(/(^"|"$)/g, "'");
name = ctx.stylize(name, 'string');
}
}
return name + ': ' + str;
}
function reduceToSingleString(output, base, braces) {
var numLinesEst = 0;
var length = output.reduce(function(prev, cur) {
numLinesEst++;
if (cur.indexOf('\n') >= 0) numLinesEst++;
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
}, 0);
if (length > 60) {
return braces[0] +
(base === '' ? '' : base + '\n ') +
' ' +
output.join(',\n ') +
' ' +
braces[1];
}
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}
// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(ar) {
return Array.isArray(ar);
}
exports.isArray = isArray;
function isBoolean(arg) {
return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;
function isNull(arg) {
return arg === null;
}
exports.isNull = isNull;
function isNullOrUndefined(arg) {
return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;
function isNumber(arg) {
return typeof arg === 'number';
}
exports.isNumber = isNumber;
function isString(arg) {
return typeof arg === 'string';
}
exports.isString = isString;
function isSymbol(arg) {
return typeof arg === 'symbol';
}
exports.isSymbol = isSymbol;
function isUndefined(arg) {
return arg === void 0;
}
exports.isUndefined = isUndefined;
function isRegExp(re) {
return isObject(re) && objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
exports.isObject = isObject;
function isDate(d) {
return isObject(d) && objectToString(d) === '[object Date]';
}
exports.isDate = isDate;
function isError(e) {
return isObject(e) &&
(objectToString(e) === '[object Error]' || e instanceof Error);
}
exports.isError = isError;
function isFunction(arg) {
return typeof arg === 'function';
}
exports.isFunction = isFunction;
function isPrimitive(arg) {
return arg === null ||
typeof arg === 'boolean' ||
typeof arg === 'number' ||
typeof arg === 'string' ||
typeof arg === 'symbol' || // ES6 symbol
typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;
exports.isBuffer = require('./support/isBuffer');
function objectToString(o) {
return Object.prototype.toString.call(o);
}
function pad(n) {
return n < 10 ? '0' + n.toString(10) : n.toString(10);
}
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
'Oct', 'Nov', 'Dec'];
// 26 Feb 16:19:34
function timestamp() {
var d = new Date();
var time = [pad(d.getHours()),
pad(d.getMinutes()),
pad(d.getSeconds())].join(':');
return [d.getDate(), months[d.getMonth()], time].join(' ');
}
// log is just a thin wrapper to console.log that prepends a timestamp
exports.log = function() {
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
};
/**
* Inherit the prototype methods from one constructor into another.
*
* The Function.prototype.inherits from lang.js rewritten as a standalone
* function (not on Function.prototype). NOTE: If this file is to be loaded
* during bootstrapping this function needs to be rewritten using some native
* functions as prototype setup using normal JavaScript does not work as
* expected during bootstrapping (see mirror.js in r114903).
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype.
* @param {function} superCtor Constructor function to inherit prototype from.
*/
exports.inherits = require('inherits');
exports._extend = function(origin, add) {
// Don't do anything if add isn't an object
if (!add || !isObject(add)) return origin;
var keys = Object.keys(add);
var i = keys.length;
while (i--) {
origin[keys[i]] = add[keys[i]];
}
return origin;
};
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./support/isBuffer":5,"_process":3,"inherits":2}],"greataptic":[function(require,module,exports){
(function (process){
var util = require('util');
var {
Vector
} = require('./vector.js');
var shuffle = require('shuffle-array');
let words = ['above-mentioned', 'above-listed', 'before-mentioned', 'aforementioned', 'abundance', 'accelerate', 'accentuate', 'accommodation', 'accompany', 'accomplish', 'accorded', 'accordingly', 'accrue', 'accurate', 'acquiesce', 'acquire', 'additional', 'address', 'addressees', 'adjustment', 'admissible', 'advantageous', 'advise', 'aggregate', 'aircraft', 'alleviate', 'allocate', 'alternatively', 'ameliorate', 'and/or', 'anticipate', 'applicant', 'application', 'apparent', 'apprehend', 'appreciable', 'appropriate', 'approximate', 'ascertain', 'attain', 'attempt', 'authorize', 'beg', 'belated', 'beneficial', 'bestow', 'beverage', 'capability', 'caveat', 'cease', 'chauffeur', 'clearly', 'obviously', 'combined', 'commence', 'complete', 'component', 'comprise', 'conceal', 'concerning', 'consequently', 'consolidate', 'constitutes', 'contains', 'convene', 'corridor', 'currently', 'deem', 'delete', 'demonstrate', 'depart', 'designate', 'desire', 'determine', 'disclose', 'different', 'discontinue', 'disseminate', 'duly', 'authorized', 'signed', 'each...apiece', 'economical', 'elect', 'eliminate', 'elucidate', 'emphasize', 'employ', 'encounter', 'endeavor', 'end', 'result', 'product', 'enquiry', 'ensure', 'entitlement', 'enumerate', 'equipments', 'equitable', 'equivalent', 'establish', 'evaluate', 'evidenced', 'evident', 'evince', 'excluding', 'exclusively', 'exhibit', 'expedite', 'expeditious', 'expend', 'expertise', 'expiration', 'facilitate', 'fauna', 'feasible', 'females', 'finalize', 'flora', 'following', 'forfeit', 'formulate', 'forward', 'frequently', 'function', 'furnish', 'grant', 'herein', 'heretofore', 'herewith', 'thereof', 'wherefore', 'wherein', 'however', 'identical', 'identify', 'immediately', 'impacted', 'implement', 'inasmuch', 'inception', 'indicate', 'indication', 'initial', 'initiate', 'interface', 'irregardless', 'liaison', '-ly', 'doubtless', 'fast', 'ill', 'much', 'seldom', 'thus', 'magnitude', 'maintain', 'majority', 'maximum', 'merge', 'methodology', 'minimize', 'minimum', 'modify', 'monitor', 'moreover', 'multiple', 'necessitate', 'nevertheless', 'notify', 'not...unless', 'not...except', 'not...until', 'notwithstanding', 'numerous', 'objective', 'obligate', 'observe', 'obtain', 'operate', 'optimum', 'option', 'orientate', '...out', 'calculate', 'cancel,', 'distribute', 'segregate', 'separate', 'overall', 'parameters', 'participate', 'particulars', 'perchance', 'perform', 'permit', 'perspire', 'peruse', 'place', 'portion', 'possess', 'potentiality', 'practicable', 'preclude', 'preowned', 'previously', 'prioritize', 'proceed', 'procure', 'proficiency', 'promulgate', 'provide', 'purchase', 'reflect', 'regarding', 'relocate', 'remain', 'remainder', 'remuneration', 'render', 'represents', 'request', 'require', 'requirement', 'reside', 'residence', 'respectively', 'retain', 'retire', 'rigorous', 'selection', 'separate', 'shall', 'solicit', 'state-of-the-art', 'strategize', 'subject', 'submit', 'subsequent', 'subsequently', 'substantial', 'sufficient', 'terminate', 'therefore', 'therein', 'timely', 'transpire', 'transmit', 'type', 'validate', 'variation', 'very', 'viable', 'warrant', 'whereas', 'whosoever', 'whomsoever', 'witnessed'];
function _logit(x) {
return Math.log(x / (1 - x));
}
function gaussRand() {
// adapted from https://stackoverflow.com/a/49434653/5129091
var u = Math.random(),
v = Math.random();
if (u === 0) u = 0.5;
if (v === 0) v = 0.5;
let res = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v) / 10 + .5;
if (res > 1 || res < 0) return gaussRand();
return res;
}
let greataptic = {};
greataptic.Vector = Vector;
greataptic.$vec = function $vec(b) {
return new Vector(b);
};
function mutateNum(x, amount) {
return x + 2 * amount * (Math.random() - 0.5);
}
function mutateList(l, amount) {
return l.map(x => mutateNum(x, amount));
}
function stepInterp(a, b, alpha) {
return (1 - alpha) * a + alpha * b;
}
function stepInterpList(la, lb, alpha) {
let res = [];
for (let i = 0; i < Math.min(la.length, lb.length); i++) res[i] = stepInterp(la[i], lb[i], alpha);
return res;
}
class Layer {
constructor(next, name = null, data = null) {
this.size = 0;
this.next = next;
this.type = this.typename();
this.data = data;
this.name = null;
}
process(vec) {
return vec;
}
remake(data) {
return new this.constructor(this.next, this.name, data);
}
_load(data) {
this.data = data;
}
_save() {
return this.data;
}
static load(data) {
let res = new this(data.next, data.name, null);
res._load(data.data);
return res;
}
save() {
return {
type: this.type,
next: this.next,
name: this.name,
data: this._save()
};
}
typename() {
throw new Error("Don't use Layer directly! (tried to call method 'name')");
}
mutate(amount = null) {
return this;
}
breed(layer) {
return Math.random() > 0.5 ? layer : this;
}
applyStep(layer, fitness) {
return this;
}
}
;
class ActivationLayer extends Layer {
mutate() {}
breed(layer) {
return this;
}
applyStep(layer, fitness) {
return this;
}
process(vec) {
return vec.map(this.activate);
}
activate(n) {
return n;
}
} // List of layer types.
let LSTMLayer;
let types = {
// Sequential layer group.
sequence: class GroupLayer extends Layer {
typename() {
return 'sequence';
}
constructor(next, name = null, parts) {
super(next, name);
this.data = parts;
this.size = parts.slice(-1)[0].size;
}
process(vec) {
let res = vec;
this.data.forEach(l => res = l.process(res));
return res;
}
mutate(amount = null) {
this.data.forEach(l => {
if (l.mutate) l.mutate(amount);
});
}
breed(layer) {
let p = this.data.map((l, i) => types[l.type].breed(l, layer.data[i]));
return this.remake(p);
}
applyStep(layer, fitness) {
let p = this.data.map((l, i) => types[l.type].applyStep(l, layer.data[i], fitness));
return this.remake(p);
}
},
combo: class ConcatLayer extends Layer {
typename() {
return 'combo';
}
process(vec) {
let res = this.data.reduce((a, ln) => a.concat(types[ln.type].process(vec, ln).data), []);
return new Vector(res);
}
constructor(next = null, name = null, parts) {
super(next, name = null);
this.data = parts;
this.size = parts.map(p => p.size).reduce((a, b) => a + b, 0);
}
mutate(amount = null) {
this.data.forEach(l => {
if (l.mutate) l.mutate(amount);
});
}
breed(layer2) {
let p = this.data.map((l, i) => types[l.type].breed(l, layer2.data[i]));
return this.remake(p);
}
applyStep(layer2, fitness) {
let p = this.data.map((l, i) => types[l.type].applyStep(l, layer2.data[i], fitness));
return this.remake(p);
}
},
sigmoid: class ASigmoidLayer extends Layer {
typename() {
return 'sigmoid';
}
activate(n) {
return 1 / (1 + Math.exp(-n));
}
},
tanh: class ATanhLayer extends Layer {
typename() {
return 'tanh';
}
activate(n) {
return Math.tanh(n);
}
},
logit: class ALogitLayer extends Layer {
typename() {
return 'logit';
}
activate(n) {
return Math.log(n / (1 - n));
}
},
spiking: class SpikingLayer extends Layer {
typename() {
return 'spiking';
}
constructor(next, name = null, nodes) {
super(next, name);
this.data = nodes;
}
process(vec) {
let res = new Array(this.data.length).fill(0);
this.data.forEach((node, ni) => {
if ((node.power += Math.max(new Vector(node.weights).multiplyVec(vec).sum(), 0)) > node.limit) {
node.power = 0;
res[ni] = node.output;
}
});
return new Vector(res);
}
mutate(amount = null) {
function _mut(x) {
if (amount != null) return x + 2 * amount * (Math.random() - 0.5);else return x + _logit(0.25 + 0.5 * Math.random());
}
this.data = this.data.map(n => ({
power: n.power,
output: n.output,
limit: _mut(n.limit),
weights: n.weights.map(_mut)
}));
}
breed(layer2) {
return this.remake(this.data.map((node, ni) => ({
power: choice([node.power, layer2.data[ni].power]),
output: choice([node.output, layer2.data[ni].output]),
limit: choice([node.limit, layer2.data[ni].limit]),
weights: node.weights.map((x, xi) => Math.random() > 0.5 ? x : layer2.data[ni].weights[xi])
})));
}
applyStep(layer2, fitness) {
return this.remake(this.data.map((node, ni) => ({
power: stepInterp(node.power, layer2.data[ni].power, fitness),
output: stepInterp(node.output, layer2.data[ni].output, fitness),
limit: stepInterp(node.limit, layer2.data[ni].limit, fitness),
weights: node.weights.map((x, xi) => stepInterp(x, layer2.data[ni].weights[xi], fitness))
})));
}
},
square: class SquareLayer extends Layer {
typename() {
return 'square';
}
constructor(next, name = null, nodes) {
super(next, name);
this.data = nodes;
}
process(vec) {
return new Vector(this.data.map(n => {
return new Vector(n.weights.linear).multiplyVec(vec).add(new Vector(n.weights.square).multiplyVec(vec.pow(2))).sum() + n.offset;
}));
}
mutate(amount = null) {
function _mut(x) {
if (amount != null) return x + 2 * amount * (Math.random() - 0.5);else return x + _logit(0.25 + 0.5 * Math.random());
}
this.data = this.data.map(l => ({
weights: {
linear: l.weights.linear.map(_mut),
square: l.weights.square.map(_mut)
},
offset: _mut(l.offset)
}));
}
breed(layer2) {
return this.remake(this.data.map((n, ni) => ({
offset: choice([n.offset, layer2.data[ni].offset]),
weights: {
linear: n.weights.linear.map((x, xi) => Math.random() > 0.5 ? x : layer2.data[ni].weights.linear[xi]),
square: n.weights.square.map((x, xi) => Math.random() > 0.5 ? x : layer2.data[ni].weights.square[xi])
}
})));
}
applyStep(layer2, fitness) {
return this.remake(this.data.map((n, ni) => ({
offset: choice([n.offset, layer2.data[ni].offset]),
weights: {
linear: n.weights.linear.map((x, xi) => Math.random() > 0.5 ? x : layer2.data[ni].weights.linear[xi]),
square: n.weights.square.map((x, xi) => Math.random() > 0.5 ? x : layer2.data[ni].weights.square[xi])
}
})));
}
},
linear: class LinearLayer extends Layer {
typename() {
return 'linear';
}
constructor(next, name = null, nodes) {
super(next, name);
this.data = nodes;
}
process(vec) {
return new Vector(this.data.map(n => {
return new Vector(n.weights).multiplyVec(vec).sum() + n.offset;
}));
}
mutate(amount = null) {
function _mut(x) {
if (amount != null) return x + 2 * amount * (Math.random() - 0.5);else return x + _logit(0.25 + 0.5 * Math.random());
}
this.data = this.data.map(l => ({
weights: l.weights.map(_mut),
offset: _mut(l.offset)
}));
}
breed(layer2) {
return this.remake(this.data.map((n, ni) => ({
offset: choice([n.offset, layer2.data[ni].offset]),
weights: n.weights.map((x, xi) => Math.random() > 0.5 ? x : layer2.data[ni].weights[xi])
})));
}
applyStep(layer2, fitness) {
return this.remake(this.data.map((n, ni) => ({
offset: stepInterp(n.offset, layer2.data[ni].offset, fitness),
weights: n.weights.map((x, xi) => stepInterp(x, layer2.data[ni].weights[xi], fitness))
})));
}
},
lstm: LSTMLayer = class LSTMLayer extends Layer {
typename() {
return 'lstm';
}
static randomGates(lastSize, size) {
return {
input: {
weights: new Array(size).fill(0).map(() => Vector.random(lastSize).data),
hiddenWeights: new Array(size).fill(0).map(() => Vector.random(lastSize).data),
offset: Vector.random(size).data
},
output: {
weights: new Array(size).fill(0).map(() => Vector.random(lastSize).data),
hiddenWeights: new Array(size).fill(0).map(() => Vector.random(lastSize).data),
offset: Vector.random(size).data
},
forget: {
weights: new Array(size).fill(0).map(() => Vector.random(lastSize).data),
hiddenWeights: new Array(size).fill(0).map(() => Vector.random(lastSize).data),
offset: Vector.random(size).data
},
cell: {
weights: new Array(size).fill(0).map(() => Vector.random(lastSize).data),
hiddenWeights: new Array(size).fill(0).map(() => Vector.random(lastSize).data),
offset: Vector.random(size).data
}
};
}
static randomStates(size) {
return {
cell: Array.apply(null, Array(size)).map(Number.prototype.valueOf, 0),
hidden: Array.apply(null, Array(size)).map(Number.prototype.valueOf, 0)
};
}
constructor(next, name, gates, states, activation = 'sigmoid', cellActivation = 'tanh') {
super(next, name, {
gates: gates,
states: states,
activation: activation,
cellActivation: cellActivation
});
}
process(vec) {
vec = new Vector(vec);
let {
forget,
input,
output
} = this.data.gates;
let gCell = this.data.gates.cell;
let act = this.data.activation;
let cAct = this.data.cellActivation;
let sHidden = new Vector(this.data.states.hidden);
let sCell = new Vector(this.data.states.cell);
let gat = {
forget: {
weights: forget.weights.map(w => new Vector(w)),
hiddenWeights: forget.hiddenWeights.map(w => new Vector(w))
},
input: {
weights: input.weights.map(w => new Vector(w)),
hiddenWeights: input.hiddenWeights.map(w => new Vector(w))
},
output: {
weights: output.weights.map(w => new Vector(w)),
hiddenWeights: output.hiddenWeights.map(w => new Vector(w))
},
cell: {
weights: gCell.weights.map(w => new Vector(w)),
hiddenWeights: gCell.hiddenWeights.map(w => new Vector(w))
}
};
let forgVec = new Vector(gat.forget.weights.map((n, i) => greataptic.activate(act, n.multiplyVec(vec).sum() + gat.forget.hiddenWeights[i].multiplyVec(sHidden).sum() + forget.offset[i])));
let inpVec = new Vector(gat.input.weights.map((n, i) => greataptic.activate(act, n.multiplyVec(vec).sum() + gat.input.hiddenWeights[i].multiplyVec(sHidden).sum() + input.offset[i])));
let outVec = new Vector(gat.output.weights.map((n, i) => greataptic.activate(act, n.multiplyVec(vec).sum() + gat.output.hiddenWeights[i].multiplyVec(sHidden).sum() + output.offset[i])));
this.data.states.cell = forgVec.multiplyVec(sCell).add(inpVec.multiplyVec(gat.cell.weights.map((n, i) => greataptic.activate(cAct, n.multiplyVec(vec).sum() + gat.cell.hiddenWeights[i].multiplyVec(sHidden).sum() + gCell.offset[i])))).data;
this.data.states.hidden = outVec.multiplyVec(this.data.states.cell.map(x => greataptic.activate(cAct, x))).data;
return new Vector(this.data.states.hidden);
}
breedGate(g1, g2, choices) {
return {
weights: g1.weights.map((w, i) => choices[i] ? w : g2.weights[i]),
hiddenWeights: g1.hiddenWeights.map((w, i) => choices[i] ? w : g2.hiddenWeights[i]),
offset: g1.offset.map((o, i) => choices[i] ? o : g2.offset[i])
};
}
breedGates(g1, g2, choices) {
if (!choices) {
for (let i = 0; i < g1.hidden.weights.length; i++) choices.push(+(Math.random() > 0.5));
}
return {
hidden: this.breedGate(g1.hidden, g2.hidden, choices),
input: this.breedGate(g1.input, g2.input, choices),
output: this.breedGate(g1.output, g2.output, choices),
cell: this.breedGate(g1.cell, g2.cell, choices)
};
}
breedState(s1, s2, choices) {
return s1.map((x, i) => choices[i] ? x : s2[i]);
}
breedStates(s1, s2, choices) {
return {
cell: this.breedState(s1.cell, s2.cell, choices),
hidden: this.breedState(s1.hidden, s2.hidden, choices)
};
}
breed(layer2) {
let choices = [];
let bred = new this.constructor(this.next, this.name, this.breedGates(this.data.gates, layer2.data.gates, choices), this.breedStates(this.data.states, layer2.data.states, choices), this.data.activation, this.data.cellActivation);
return bred;
}
stepGate(g1, g2, fit) {
return {
weights: g1.weights.map((w, i) => stepInterpList(w, g2.weights[i], fit)),
hiddenWeights: g1.hiddenWeights.map((w, i) => stepInterpList(w, g2.hiddenWeights[i], fit)),
offset: stepInterpList(g1.offset, g2.offset, fit)
};
}
stepGates(g1, g2, fit) {
return {
forget: this.stepGate(g1.forget, g2.forget, fit),
input: this.stepGate(g1.input, g2.input, fit),
output: this.stepGate(g1.output, g2.output, fit),
cell: this.stepGate(g1.cell, g2.cell, fit)
};
}
stepState(s1, s2, fit) {
return s1.map((x, i) => stepInterp(x, s2[i], fit));
}
stepStates(s1, s2, fit) {
return {
cell: this.stepState(s1.cell, s2.cell, fit),
hidden: this.stepState(s1.hidden, s2.hidden, fit)
};
}
applyStep(layer2, fit) {
let stepped = new this.constructor(this.next, this.name, this.stepGates(this.data.gates, layer2.data.gates, fit), this.stepStates(this.data.states, layer2.data.states, fit), this.data.activation, this.data.cellActivation);
stepped.name = this.name;
return stepped;
}
mutateGate(g1, amount) {
return {
weights: g1.weights.map(w => mutateList(w, amount)),
hiddenWeights: g1.hiddenWeights.map(w => mutateList(w, amount)),
offset: mutateList(g1.offset, amount)
};
}
mutateGates(g1, amount) {
g1.forget = this.mutateGate(g1.forget, amount);
g1.input = this.mutateGate(g1.input, amount);
g1.output = this.mutateGate(g1.output, amount);
g1.cell = this.mutateGate(g1.cell, amount);
}
mutateState(s1, amount) {
return mutateList(s1, amount);
}
mutateStates(s1, amount) {
s1.cell = this.mutateState(s1.cell, amount);
s1.hidden = this.mutateState(s1.hidden, amount);
}
mutate(amount = null) {
if (amount == null) amount = _logit(0.25 + 0.5 * Math.random());
this.mutateGates(this.data.gates, amount);
this.mutateStates(this.data.states, amount);
}
},
lstm_peephole: class LSTMPeepholLayer extends LSTMLayer {
typename() {
return 'lstm_peephole';
}
process(vec) {
let {
forget,
input,
output
} = this.data.gates;
let gCell = this.data.gates.cell;
let act = this.data.activation;
let cAct = this.data.cellActivation;
let sCell = new Vector(this.data.states.cell);
let gat = {
forget: {
weights: forget.weights.map(w => new Vector(w)),
hiddenWeights: forget.hiddenWeights.map(w => new Vector(w))
},
input: {
weights: input.weights.map(w => new Vector(w)),
hiddenWeights: input.hiddenWeights.map(w => new Vector(w))
},
output: {
weights: output.weights.map(w => new Vector(w)),
hiddenWeights: output.hiddenWeights.map(w => new Vector(w))
},
cell: {
weights: gCell.weights.map(w => new Vector(w)),
hiddenWeights: gCell.hiddenWeights.map(w => new Vector(w))
}
};
let forgVec = new Vector(gat.forget.weights.map((n, i) => greataptic.activate(act, n.multiplyVec(vec).sum() + gat.forget.hiddenWeights[i].multiplyVec(sCell).sum() + forget.offset[i])));
let inpVec = new Vector(gat.input.weights.map((n, i) => greataptic.activate(act, n.multiplyVec(vec).sum() + gat.input.hiddenWeights[i].multiplyVec(sCell).sum() + input.offset[i])));
let outVec = new Vector(gat.output.weights.map((n, i) => greataptic.activate(act, n.multiplyVec(vec).sum() + gat.output.hiddenWeights[i].multiplyVec(sCell).sum() + output.offset[i])));
this.data.states.cell = forgVec.multiplyVec(sCell).add(inpVec.multiplyVec(gat.cell.weights.map((n, i) => greataptic.activate(cAct, n.multiplyVec(vec).sum() + gCell.offset[i])))).data;
this.data.states.hidden = outVec.multiplyVec(this.data.states.cell.map(x => greataptic.activate(cAct, x))).data;
return new Vector(this.data.states.hidden);
}
}
};
greataptic.layerTypes = types;
greataptic.isNetworkData = function (n) {
return !!(n && n.layers && n.first != null);
};
function choice(l) {
return l[Math.floor(l.length * Math.random())];
}
greataptic.breed = function breed(nets) {
let res = nets[0].clone();
let newLayers = {};
Object.keys(res.data.layers).forEach(i => {
let l = res.data.layers[i];
let n2 = choice(nets.slice(1));
let l2 = n2.data.layers[i];
if (n2 !== nets[0] && l2.type === l.type && types[l.type].breed) l = types[l.type].breed(l, l2);
newLayers[i] = l;
});
res.data.layers = newLayers;
return res;
};
let $net = greataptic.$net = function (data) {
return new NeuralNetwork(data);
};
let NeuralNetwork = greataptic.NeuralNetwork = class NeuralNetwork {
constructor(net) {
if (!greataptic.isNetworkData(net)) throw new Error(`The net parameter passed to NeuralNetwork's constructor (${util.inspect(net)}) is invalid!`);
this.data = net;
this.id = new Array(5).fill(0).map(() => choice(words)).join('-') + '-' + Math.ceil(Math.random() * 10000);
}
json() {
let lays = {};
Object.entries(this.data.layers).forEach(l => {
let [id, lay] = l;
lays[id] = lay.save();
});
return JSON