Skip to content

Commit b057d4c

Browse files
Merge pull request #121 from BrainJS/102-gpu-exploding
Fix for #102 gpu exploding
2 parents 3aa950a + 8b834b2 commit b057d4c

File tree

8 files changed

+262
-314
lines changed

8 files changed

+262
-314
lines changed

browser.js

Lines changed: 79 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* license: MIT (http://opensource.org/licenses/MIT)
77
* author: Heather Arthur <[email protected]>
88
* homepage: https://github.com/brainjs/brain.js#readme
9-
* version: 1.0.0
9+
* version: 1.0.1
1010
*
1111
* acorn:
1212
* license: MIT (http://opensource.org/licenses/MIT)
@@ -451,15 +451,14 @@ var NeuralNetworkGPU = function (_NeuralNetwork) {
451451

452452
/**
453453
*
454-
* @param {} sizes
455-
* @param {Boolean} keepNetworkIntact
454+
* @param {Number[]} sizes
456455
*/
457456

458457

459458
_createClass(NeuralNetworkGPU, [{
460459
key: 'initialize',
461-
value: function initialize(sizes, keepNetworkIntact) {
462-
_get(NeuralNetworkGPU.prototype.__proto__ || Object.getPrototypeOf(NeuralNetworkGPU.prototype), 'initialize', this).call(this, sizes, keepNetworkIntact);
460+
value: function initialize(sizes) {
461+
_get(NeuralNetworkGPU.prototype.__proto__ || Object.getPrototypeOf(NeuralNetworkGPU.prototype), 'initialize', this).call(this, sizes);
463462
this.buildRunInput();
464463
this.buildCalculateDeltas();
465464
this.buildGetChanges();
@@ -514,14 +513,13 @@ var NeuralNetworkGPU = function (_NeuralNetwork) {
514513
}
515514

516515
for (var layer = 1; layer <= this.outputLayer; layer++) {
517-
var kernel = this.gpu.createKernelMap({ weightedSum: _gpu2.default.alias('weightedSum', weightedSum) }, function (weights, biases, inputs) {
518-
return weightedSum(weights, biases, this.thread.x, inputs);
519-
}, {
516+
this.forwardPropagate[layer] = this.gpu.createKernel(weightedSum, {
517+
output: [this.sizes[layer]],
518+
outputToTexture: true,
520519
constants: {
521520
size: this.sizes[layer - 1]
522521
}
523-
}).setOutput([this.sizes[layer]]).setOutputToTexture(true);
524-
this.forwardPropagate[layer] = kernel;
522+
});
525523
}
526524
}
527525

@@ -537,7 +535,7 @@ var NeuralNetworkGPU = function (_NeuralNetwork) {
537535
var output = void 0;
538536
this.outputs[0] = input;
539537
for (var layer = 1; layer <= this.outputLayer; layer++) {
540-
this.outputs[layer] = this.forwardPropagate[layer](this.weights[layer], this.biases[layer], input).result;
538+
this.outputs[layer] = this.forwardPropagate[layer](this.weights[layer], this.biases[layer], input);
541539

542540
output = input = this.outputs[layer];
543541
}
@@ -567,29 +565,30 @@ var NeuralNetworkGPU = function (_NeuralNetwork) {
567565

568566
for (var layer = this.outputLayer; layer > 0; layer--) {
569567
if (layer === this.outputLayer) {
570-
var kernel = this.gpu.createKernelMap({
571-
error: _gpu2.default.alias('calcError', calcError),
568+
this.backwardPropagate[layer] = this.gpu.createKernelMap({
569+
error: _gpu2.default.alias('calcErrorOutput', calcErrorOutput),
572570
deltas: _gpu2.default.alias('calcDeltas', calcDeltas)
573-
}, function (outputs, target) {
571+
}, function (outputs, targets) {
574572
var output = outputs[this.thread.x];
575-
return calcDeltas(calcError(output, target), output);
576-
}).setOutput([this.sizes[layer]]).setOutputToTexture(true);
577-
578-
this.backwardPropagate[layer] = kernel;
573+
return calcDeltas(calcErrorOutput(output, targets), output);
574+
}, {
575+
output: [this.sizes[layer]],
576+
outputToTexture: true
577+
});
579578
} else {
580-
var _kernel = this.gpu.createKernelMap({
581-
error: _gpu2.default.alias('calcErrorOutput', calcErrorOutput),
579+
this.backwardPropagate[layer] = this.gpu.createKernelMap({
580+
error: _gpu2.default.alias('calcError', calcError),
582581
deltas: _gpu2.default.alias('calcDeltas', calcDeltas)
583582
}, function (nextWeights, outputs, nextDeltas) {
584583
var output = outputs[this.thread.x];
585-
return calcDeltas(calcErrorOutput(nextWeights, nextDeltas), output);
584+
return calcDeltas(calcError(nextWeights, nextDeltas), output);
586585
}, {
586+
output: [this.sizes[layer]],
587+
outputToTexture: true,
587588
constants: {
588589
size: this.deltas[layer + 1].length
589590
}
590-
}).setOutput([this.sizes[layer]]).setOutputToTexture(true);
591-
592-
this.backwardPropagate[layer] = _kernel;
591+
});
593592
}
594593
}
595594
}
@@ -604,27 +603,28 @@ var NeuralNetworkGPU = function (_NeuralNetwork) {
604603
output = this.backwardPropagate[layer](this.weights[layer + 1], this.outputs[layer], this.deltas[layer + 1]);
605604
}
606605

607-
this.deltas[layer] = output.result;
606+
this.deltas[layer] = output.deltas;
608607
this.errors[layer] = output.error;
609608
}
610609
}
611610
}, {
612611
key: 'buildGetChanges',
613612
value: function buildGetChanges() {
614613
for (var layer = 1; layer <= this.outputLayer; layer++) {
615-
var kernel = this.gpu.createKernelMap({
616-
addWeights: addWeights, calcChanges: calcChanges }, function (previousOutputs, deltas, weights, changes, learningRate, momentum) {
617-
var delta = deltas[this.thread.y];
618-
var change = calcChanges(changes, delta, previousOutputs, learningRate, momentum, this.thread.x, this.thread.y);
614+
this.changesPropagate[layer] = this.gpu.createKernelMap({
615+
weights: _gpu2.default.alias('addWeights', addWeights),
616+
changes: _gpu2.default.alias('calcChanges', calcChanges)
617+
}, function (previousOutputs, deltas, weights, changes, learningRate, momentum) {
618+
var change = calcChanges(changes, deltas, previousOutputs, learningRate, momentum);
619619

620-
return addWeights(change, weights, this.thread.x, this.thread.y);
620+
return addWeights(change, weights);
621621
}, {
622+
output: [this.sizes[layer - 1], this.sizes[layer]],
623+
outputToTexture: true,
622624
constants: {
623625
size: this.outputs[layer - 1].length
624626
}
625-
}).setOutput([this.sizes[layer - 1], this.sizes[layer]]).setOutputToTexture(true);
626-
627-
this.changesPropagate[layer] = kernel;
627+
});
628628
}
629629
}
630630
}, {
@@ -633,41 +633,36 @@ var NeuralNetworkGPU = function (_NeuralNetwork) {
633633
for (var layer = 1; layer <= this.outputLayer; layer++) {
634634
var output = this.changesPropagate[layer](this.outputs[layer - 1], this.deltas[layer], this.weights[layer], this.changes[layer], learningRate, this.momentum);
635635

636-
this.changes[layer] = output.calcChanges;
637-
this.weights[layer] = output.result;
636+
this.changes[layer] = output.changes;
637+
this.weights[layer] = output.weights;
638638
}
639639
}
640640
}, {
641641
key: 'buildChangeBiases',
642642
value: function buildChangeBiases() {
643643
for (var layer = 1; layer <= this.outputLayer; layer++) {
644-
var kernel = this.gpu.createKernelMap({
645-
addBiases: addBiases
646-
}, function (biases, deltas, learningRate) {
647-
return addBiases(biases, deltas, learningRate, this.thread.x);
648-
}).setOutput([this.sizes[layer]]).setOutputToTexture(true);
649-
650-
this.biasesPropagate[layer] = kernel;
644+
this.biasesPropagate[layer] = this.gpu.createKernel(addBiases, {
645+
output: [this.sizes[layer]],
646+
outputToTexture: true
647+
});
651648
}
652649
}
653650
}, {
654651
key: 'changeBiases',
655652
value: function changeBiases(learningRate) {
656653
for (var layer = 1; layer <= this.outputLayer; layer++) {
657-
var output = this.biasesPropagate[layer](this.biases[layer], this.deltas[layer], learningRate);
658-
this.biases[layer] = output.result;
654+
this.biases[layer] = this.biasesPropagate[layer](this.biases[layer], this.deltas[layer], learningRate);
659655
}
660656
}
661657
}, {
662658
key: 'buildGetMSE',
663659
value: function buildGetMSE() {
664-
var kernel = this.gpu.createKernel(mse, {
660+
this.getMSE = this.gpu.createKernel(mse, {
665661
output: [1],
666662
constants: {
667663
size: this.outputLayer
668664
}
669665
});
670-
this.getMSE = kernel;
671666
}
672667

673668
/**
@@ -747,44 +742,44 @@ var NeuralNetworkGPU = function (_NeuralNetwork) {
747742
exports.default = NeuralNetworkGPU;
748743

749744

750-
function weightedSumSigmoid(weights, biases, x, inputs) {
751-
var sum = biases[x];
745+
function weightedSumSigmoid(weights, biases, inputs) {
746+
var sum = biases[this.thread.x];
752747
for (var k = 0; k < this.constants.size; k++) {
753-
sum += weights[x][k] * inputs[k];
748+
sum += weights[this.thread.x][k] * inputs[k];
754749
}
755750
//sigmoid
756751
return 1 / (1 + Math.exp(-sum));
757752
}
758753

759-
function weightedSumRelu(weights, biases, x, inputs) {
760-
var sum = biases[x];
754+
function weightedSumRelu(weights, biases, inputs) {
755+
var sum = biases[this.thread.x];
761756
for (var k = 0; k < this.constants.size; k++) {
762-
sum += weights[x][k] * inputs[k];
757+
sum += weights[this.thread.x][k] * inputs[k];
763758
}
764759
//relu
765760
return sum < 0 ? 0 : sum;
766761
}
767762

768-
function weightedSumLeakyRelu(weights, biases, x, inputs) {
769-
var sum = biases[x];
763+
function weightedSumLeakyRelu(weights, biases, inputs) {
764+
var sum = biases[this.thread.x];
770765
for (var k = 0; k < this.constants.size; k++) {
771-
sum += weights[x][k] * inputs[k];
766+
sum += weights[this.thread.x][k] * inputs[k];
772767
}
773768
//leaky relu
774769
return sum < 0 ? 0 : 0.01 * sum;
775770
}
776771

777-
function weightedSumTanh(weights, biases, x, inputs) {
778-
var sum = biases[x];
772+
function weightedSumTanh(weights, biases, inputs) {
773+
var sum = biases[this.thread.x];
779774
for (var k = 0; k < this.constants.size; k++) {
780-
sum += weights[x][k] * inputs[k];
775+
sum += weights[this.thread.x][k] * inputs[k];
781776
}
782777
//tanh
783778
return Math.tanh(sum);
784779
}
785780

786-
function calcError(outputs, target) {
787-
return target[this.thread.x] - outputs;
781+
function calcErrorOutput(output, targets) {
782+
return targets[this.thread.x] - output;
788783
}
789784

790785
function calcDeltasSigmoid(error, output) {
@@ -807,28 +802,24 @@ function calcDeltasTanh(error, output) {
807802
return (1 - output * output) * error;
808803
}
809804

810-
function calcErrorOutput(nextWeights, nextDeltas) {
805+
function calcError(nextWeights, nextDeltas) {
811806
var error = 0;
812807
for (var k = 0; k < this.constants.size; k++) {
813808
error += nextDeltas[k] * nextWeights[k][this.thread.x];
814809
}
815810
return error;
816811
}
817812

818-
function calcChanges(previousChange, deltas, previousOutputs, learningRate, momentum, x, y) {
819-
var sum = 0;
820-
for (var i = 0; i < this.constants.size; i++) {
821-
sum += learningRate * deltas * previousOutputs[x] + momentum * previousChange[y][i];
822-
}
823-
return sum;
813+
function calcChanges(previousChanges, deltas, previousOutputs, learningRate, momentum) {
814+
return learningRate * deltas[this.thread.y] * previousOutputs[this.thread.x] + momentum * previousChanges[this.thread.y][this.thread.x];
824815
}
825816

826-
function addWeights(change, weights, x, y) {
827-
return change + weights[y][x];
817+
function addWeights(change, weights) {
818+
return change + weights[this.thread.y][this.thread.x];
828819
}
829820

830-
function addBiases(biases, deltas, learningRate, x) {
831-
return biases[x] + deltas[x] * learningRate;
821+
function addBiases(biases, deltas, learningRate) {
822+
return biases[this.thread.x] + deltas[this.thread.x] * learningRate;
832823
}
833824

834825
// mean squared error, reimplemented for GPU
@@ -947,7 +938,7 @@ var NeuralNetwork = function () {
947938

948939
/**
949940
*
950-
* @param {} sizes
941+
* @param {Number[]} sizes
951942
*/
952943

953944

@@ -1559,7 +1550,13 @@ var NeuralNetwork = function () {
15591550
}
15601551
}
15611552
}
1562-
return { layers: layers, outputLookup: !!this.outputLookup, inputLookup: !!this.inputLookup, activation: this.activation };
1553+
return {
1554+
sizes: this.sizes,
1555+
layers: layers,
1556+
outputLookup: !!this.outputLookup,
1557+
inputLookup: !!this.inputLookup,
1558+
activation: this.activation
1559+
};
15631560
}
15641561

15651562
/**
@@ -1571,13 +1568,7 @@ var NeuralNetwork = function () {
15711568
}, {
15721569
key: 'fromJSON',
15731570
value: function fromJSON(json) {
1574-
var size = json.layers.length;
1575-
this.outputLayer = size - 1;
1576-
1577-
this.sizes = new Array(size);
1578-
this.weights = new Array(size);
1579-
this.biases = new Array(size);
1580-
this.outputs = new Array(size);
1571+
this.initialize(json.sizes);
15811572

15821573
for (var i = 0; i <= this.outputLayer; i++) {
15831574
var layer = json.layers[i];
@@ -1586,17 +1577,14 @@ var NeuralNetwork = function () {
15861577
} else if (i === this.outputLayer && (!layer[0] || json.outputLookup)) {
15871578
this.outputLookup = _lookup2.default.lookupFromHash(layer);
15881579
}
1589-
1590-
var nodes = Object.keys(layer);
1591-
this.sizes[i] = nodes.length;
1592-
this.weights[i] = [];
1593-
this.biases[i] = [];
1594-
this.outputs[i] = [];
1595-
1596-
for (var j in nodes) {
1597-
var node = nodes[j];
1598-
this.biases[i][j] = layer[node].bias;
1599-
this.weights[i][j] = (0, _toArray2.default)(layer[node].weights);
1580+
if (layer > 0) {
1581+
var nodes = Object.keys(layer);
1582+
this.sizes[i] = nodes.length;
1583+
for (var j in nodes) {
1584+
var node = nodes[j];
1585+
this.biases[i] = layer[node].bias;
1586+
this.weights[i][j] = (0, _toArray2.default)(layer[node].weights);
1587+
}
16001588
}
16011589
}
16021590

0 commit comments

Comments
 (0)