Skip to content

Commit 031d746

Browse files
authored
Merge pull request #540 from BrainJS/proper-error-messages
Better error messages
2 parents 7b73a89 + ffbcec4 commit 031d746

File tree

10 files changed

+922
-646
lines changed

10 files changed

+922
-646
lines changed

.eslintrc.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
},
1212
"root": true,
1313
"rules": {
14+
"arrow-parens": "off",
1415
"class-methods-use-this": "off",
1516
"linebreak-style": "off",
1617
"max-classes-per-file": "off",
@@ -19,6 +20,7 @@
1920
"no-param-reassign": "off",
2021
"no-plusplus": "off",
2122
"no-prototype-builtins": "off",
23+
"no-restricted-globals": "off",
2224
"no-underscore-dangle": "off",
2325
"semi": "error"
2426
}

.prettierrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"semi": true,
33
"singleQuote": true,
4-
"trailingComma": "none"
4+
"trailingComma": "es5"
55
}

__tests__/.eslintrc.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"no-param-reassign": "off",
2323
"no-plusplus": "off",
2424
"no-prototype-builtins": "off",
25+
"no-restricted-globals": "off",
2526
"no-underscore-dangle": "off",
2627
"semi": "error"
2728
}

src/feed-forward.js

Lines changed: 79 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ class FeedForward {
2929
inputLayer: null,
3030
outputLayer: null,
3131
praxisOpts: null,
32-
praxis: (layer, settings) => praxis.momentumRootMeanSquaredPropagation({ ...layer }, layer.praxisOpts || settings),
32+
praxis: (layer, settings) =>
33+
praxis.momentumRootMeanSquaredPropagation(
34+
{ ...layer },
35+
layer.praxisOpts || settings
36+
),
3337
};
3438
}
3539

@@ -40,21 +44,19 @@ class FeedForward {
4044
*/
4145
static _validateTrainingOptions(options) {
4246
const validations = {
43-
iterations: val => typeof val === 'number' && val > 0,
44-
errorThresh: val => typeof val === 'number' && val > 0 && val < 1,
45-
log: val => typeof val === 'function' || typeof val === 'boolean',
46-
logPeriod: val => typeof val === 'number' && val > 0,
47-
learningRate: val => typeof val === 'number' && val > 0 && val < 1,
48-
callback: val => typeof val === 'function' || val === null,
49-
callbackPeriod: val => typeof val === 'number' && val > 0,
50-
timeout: val => typeof val === 'number' && val > 0,
47+
iterations: (val) => typeof val === 'number' && val > 0,
48+
errorThresh: (val) => typeof val === 'number' && val > 0 && val < 1,
49+
log: (val) => typeof val === 'function' || typeof val === 'boolean',
50+
logPeriod: (val) => typeof val === 'number' && val > 0,
51+
learningRate: (val) => typeof val === 'number' && val > 0 && val < 1,
52+
callback: (val) => typeof val === 'function' || val === null,
53+
callbackPeriod: (val) => typeof val === 'number' && val > 0,
54+
timeout: (val) => typeof val === 'number' && val > 0,
5155
};
52-
Object.keys(FeedForward.trainDefaults).forEach(key => {
56+
Object.keys(FeedForward.trainDefaults).forEach((key) => {
5357
if (validations.hasOwnProperty(key) && !validations[key](options[key])) {
5458
throw new Error(
55-
`[${key}, ${
56-
options[key]
57-
}] is out of normal training range, your network will probably not train.`
59+
`[${key}, ${options[key]}] is out of normal training range, your network will probably not train.`
5860
);
5961
}
6062
});
@@ -72,7 +74,7 @@ class FeedForward {
7274
this.trainOpts.log = log;
7375
} else if (log) {
7476
// eslint-disable-next-line
75-
this.trainOpts.log = console.log
77+
this.trainOpts.log = console.log;
7678
} else {
7779
this.trainOpts.log = false;
7880
}
@@ -86,15 +88,20 @@ class FeedForward {
8688
* learningRate: (number)
8789
*/
8890
_updateTrainingOptions(opts) {
89-
Object.keys(this.constructor.trainDefaults).forEach(opt => {
91+
Object.keys(this.constructor.trainDefaults).forEach((opt) => {
9092
this.trainOpts[opt] = opts.hasOwnProperty(opt)
9193
? opts[opt]
9294
: this.trainOpts[opt];
9395
});
9496
this.constructor._validateTrainingOptions(this.trainOpts);
9597
this._setLogMethod(opts.log || this.trainOpts.log);
96-
if (this.trainOpts.callback && this.trainOpts.callbackPeriod !== this.trainOpts.errorCheckInterval) {
97-
console.warn(`options.callbackPeriod with value of ${ this.trainOpts.callbackPeriod } does not match options.errorCheckInterval with value of ${ this.trainOpts.errorCheckInterval }, if logging error, it will repeat. These values may need to match`);
98+
if (
99+
this.trainOpts.callback &&
100+
this.trainOpts.callbackPeriod !== this.trainOpts.errorCheckInterval
101+
) {
102+
console.warn(
103+
`options.callbackPeriod with value of ${this.trainOpts.callbackPeriod} does not match options.errorCheckInterval with value of ${this.trainOpts.errorCheckInterval}, if logging error, it will repeat. These values may need to match`
104+
);
98105
}
99106
}
100107

@@ -121,9 +128,10 @@ class FeedForward {
121128
this.praxis = null;
122129
Object.assign(this, this.constructor.defaults, options);
123130
this.trainOpts = {};
124-
this._updateTrainingOptions(
125-
Object.assign({}, this.constructor.trainDefaults, options)
126-
);
131+
this._updateTrainingOptions({
132+
...this.constructor.trainDefaults,
133+
...options,
134+
});
127135
Object.assign(this, this.constructor.structure);
128136
this._inputLayer = null;
129137
this._hiddenLayers = null;
@@ -159,15 +167,19 @@ class FeedForward {
159167
initialize() {
160168
this._connectLayers();
161169
this.initializeLayers(this.layers);
162-
this._model = this.layers.filter(l => l instanceof Model);
170+
this._model = this.layers.filter((l) => l instanceof Model);
163171
}
164172

165173
initializeLayers(layers) {
166174
for (let i = 0; i < layers.length; i++) {
167175
const layer = layers[i];
168176
// TODO: optimize for when training or just running
169177
layer.setupKernels(true);
170-
if (layer instanceof Model && layer.hasOwnProperty('praxis') && layer.praxis === null) {
178+
if (
179+
layer instanceof Model &&
180+
layer.hasOwnProperty('praxis') &&
181+
layer.praxis === null
182+
) {
171183
layer.praxis = this.praxis(layer, layer.praxisOpts || this.praxisOpts);
172184
layer.praxis.setupKernels();
173185
}
@@ -386,11 +398,7 @@ class FeedForward {
386398
adjustWeights() {
387399
const { _model } = this;
388400
for (let i = 0; i < _model.length; i++) {
389-
_model[i].learn(
390-
null,
391-
null,
392-
this.trainOpts.learningRate
393-
);
401+
_model[i].learn(null, null, this.trainOpts.learningRate);
394402
}
395403
}
396404

@@ -409,43 +417,57 @@ class FeedForward {
409417

410418
// turn sparse hash input into arrays with 0s as filler
411419
const inputDatumCheck = data[0].input;
412-
if (!Array.isArray(inputDatumCheck) && !(inputDatumCheck instanceof Float32Array)) {
420+
if (
421+
!Array.isArray(inputDatumCheck) &&
422+
!(inputDatumCheck instanceof Float32Array)
423+
) {
413424
if (!this.inputLookup) {
414-
this.inputLookup = lookup.buildLookup(data.map(value => value.input));
425+
this.inputLookup = lookup.buildLookup(data.map((value) => value.input));
415426
}
416-
data = data.map(datumParam => {
427+
data = data.map((datumParam) => {
417428
const array = lookup.toArray(this.inputLookup, datumParam.input);
418-
return Object.assign({}, datumParam, { input: array });
429+
return { ...datumParam, input: array };
419430
}, this);
420431
}
421432

422433
const outputDatumCheck = data[0].output;
423-
if (!Array.isArray(outputDatumCheck) && !(outputDatumCheck instanceof Float32Array)) {
434+
if (
435+
!Array.isArray(outputDatumCheck) &&
436+
!(outputDatumCheck instanceof Float32Array)
437+
) {
424438
if (!this.outputLookup) {
425-
this.outputLookup = lookup.buildLookup(data.map(value => value.output));
439+
this.outputLookup = lookup.buildLookup(
440+
data.map((value) => value.output)
441+
);
426442
}
427-
data = data.map(datumParam => {
443+
data = data.map((datumParam) => {
428444
const array = lookup.toArray(this.outputLookup, datumParam.output);
429-
return Object.assign({}, datumParam, { output: array });
445+
return { ...datumParam, output: array };
430446
}, this);
431447
}
432448
return data;
433449
}
434450

435451
transferData(formattedData) {
436452
const transferredData = new Array(formattedData.length);
437-
const transferInput = makeKernel(function(value) {
438-
return value[this.thread.x];
439-
}, {
440-
output: [formattedData[0].input.length],
441-
immutable: true,
442-
});
443-
const transferOutput = makeKernel(function(value) {
444-
return value[this.thread.x];
445-
}, {
446-
output: [formattedData[0].output.length],
447-
immutable: true,
448-
});
453+
const transferInput = makeKernel(
454+
function (value) {
455+
return value[this.thread.x];
456+
},
457+
{
458+
output: [formattedData[0].input.length],
459+
immutable: true,
460+
}
461+
);
462+
const transferOutput = makeKernel(
463+
function (value) {
464+
return value[this.thread.x];
465+
},
466+
{
467+
output: [formattedData[0].output.length],
468+
immutable: true,
469+
}
470+
);
449471

450472
for (let i = 0; i < formattedData.length; i++) {
451473
const formattedDatum = formattedData[i];
@@ -497,7 +519,7 @@ class FeedForward {
497519
return {
498520
type: this.constructor.name,
499521
sizes: [this._inputLayer.height]
500-
.concat(this._hiddenLayers.map(l => l.height))
522+
.concat(this._hiddenLayers.map((l) => l.height))
501523
.concat([this._outputLayer.height]),
502524
layers: jsonLayers,
503525
};
@@ -525,19 +547,23 @@ class FeedForward {
525547
);
526548
} else {
527549
if (!jsonLayer.hasOwnProperty('inputLayer1Index'))
528-
throw new Error('inputLayer1Index not defined');
550+
throw new Error(
551+
'Cannot create network from provided JOSN. inputLayer1Index not defined.'
552+
);
529553
if (!jsonLayer.hasOwnProperty('inputLayer2Index'))
530-
throw new Error('inputLayer2Index not defined');
554+
throw new Error(
555+
'Cannot create network from provided JOSN. inputLayer2Index not defined.'
556+
);
531557
const inputLayer1 = layers[jsonLayer.inputLayer1Index];
532558
const inputLayer2 = layers[jsonLayer.inputLayer2Index];
533559

534560
if (inputLayer1 === undefined)
535561
throw new Error(
536-
`layer of index ${jsonLayer.inputLayer1Index} not found`
562+
`Cannot create network from provided JOSN. layer of index ${jsonLayer.inputLayer1Index} not found.`
537563
);
538564
if (inputLayer2 === undefined)
539565
throw new Error(
540-
`layer of index ${jsonLayer.inputLayer2Index} not found`
566+
`Cannot create network from provided JOSN. layer of index ${jsonLayer.inputLayer2Index} not found.`
541567
);
542568

543569
layers.push(
@@ -575,5 +601,5 @@ class FeedForward {
575601
}
576602

577603
module.exports = {
578-
FeedForward
604+
FeedForward,
579605
};

src/likely.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@
55
* @returns {*}
66
*/
77
module.exports = function likely(input, net) {
8+
if (!net) {
9+
throw new TypeError(
10+
`Required parameter 'net' is of type ${typeof net}. Must be of type 'brain.NeuralNetwork'`
11+
);
12+
}
13+
814
const output = net.run(input);
915
let maxProp = null;
1016
let maxValue = -1;
1117

12-
Object.keys(output).forEach(key => {
18+
Object.keys(output).forEach((key) => {
1319
const value = output[key];
1420
if (value > maxValue) {
1521
maxProp = key;

0 commit comments

Comments
 (0)