From 9614692a4f274795594578d6ff1bf3d460dae7bc Mon Sep 17 00:00:00 2001 From: Engine Feeder Date: Sat, 10 Mar 2018 18:56:18 +0100 Subject: [PATCH 1/3] Adding crossover function This commit adds crossover functions to the Matrix and NeuralNetwork class. It defaults to a uniform crossover (ratio = 0.5), but this is customizable (third parameter). You can use it as such: ```javascript let mom = new NeuralNetwork(2, 4, 1); let dad = new NeuralNetwork(2, 4, 1); let child = NeuralNetwork.crossover(mom, dad); ``` --- lib/matrix.js | 6 ++++++ lib/nn.js | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/lib/matrix.js b/lib/matrix.js index 34b2d97..29e24a2 100644 --- a/lib/matrix.js +++ b/lib/matrix.js @@ -18,6 +18,12 @@ class Matrix { return m; } + static crossover(a, b, ratio = 0.5) { + let m = a.copy(); + m.map((value, i, j) => Math.random() < ratio ? value : b.data[i][j]) + return m; + } + static fromArray(arr) { return new Matrix(arr.length, 1).map((e, i) => arr[i]); } diff --git a/lib/nn.js b/lib/nn.js index 0260280..8514d5d 100644 --- a/lib/nn.js +++ b/lib/nn.js @@ -175,6 +175,14 @@ class NeuralNetwork { this.bias_o.map(mutate); } + static crossover(a, b, ratio = 0.5) { + let nn = a.copy(); + nn.weights_ih = Matrix.crossover(a.weights_ih, b.weights_ih, ratio); + nn.weights_ho = Matrix.crossover(a.weights_ho, b.weights_ho, ratio); + nn.bias_h = Matrix.crossover(a.bias_h, b.bias_h, ratio); + nn.bias_o = Matrix.crossover(a.bias_o, b.bias_o, ratio); + return nn; + } } From 515100c07e067eafc833e51948e55ca5d72b79a2 Mon Sep 17 00:00:00 2001 From: Engine Feeder Date: Thu, 15 Mar 2018 21:06:33 +0100 Subject: [PATCH 2/3] Fixed missing semicolon There was a semicolon missing after the `map()` function. --- lib/matrix.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matrix.js b/lib/matrix.js index 29e24a2..d9347fe 100644 --- a/lib/matrix.js +++ b/lib/matrix.js @@ -20,7 +20,7 @@ class Matrix { static crossover(a, b, ratio = 0.5) { let m = a.copy(); - m.map((value, i, j) => Math.random() < ratio ? value : b.data[i][j]) + m.map((value, i, j) => Math.random() < ratio ? value : b.data[i][j]); return m; } From 3a76ec9dc982520f3c25afe20a07ce31c631c359 Mon Sep 17 00:00:00 2001 From: Engine Feeder Date: Thu, 15 Mar 2018 22:40:34 +0100 Subject: [PATCH 3/3] Add type checking and size checking to crossover functions This commit adds a check to the `crossover()` functions (both Matrix and NeuralNetwork) that does not allow to crossover between different breeds. In other words, only if two NeuralNetwork have the same number of nodes thay can crossover. Otherwise undefined is returned. Same for the Matrix crossover function. --- lib/matrix.js | 5 +++++ lib/nn.js | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/lib/matrix.js b/lib/matrix.js index d9347fe..f83475e 100644 --- a/lib/matrix.js +++ b/lib/matrix.js @@ -19,6 +19,11 @@ class Matrix { } static crossover(a, b, ratio = 0.5) { + if (!a instanceof this || !b instanceof this || a.rows !== b.rows || a.cols !== b.cols) { + console.log('Columns and Rows of A must match Columns and Rows of B.'); + return; + } + let m = a.copy(); m.map((value, i, j) => Math.random() < ratio ? value : b.data[i][j]); return m; diff --git a/lib/nn.js b/lib/nn.js index 8514d5d..8895f03 100644 --- a/lib/nn.js +++ b/lib/nn.js @@ -176,6 +176,11 @@ class NeuralNetwork { } static crossover(a, b, ratio = 0.5) { + if (!a instanceof this || !b instanceof this || a.input_nodes !== b.input_nodes || a.hidden_nodes !== b.hidden_nodes || a.output_nodes !== b.output_nodes) { + console.error('Only NeuralNetworks of the same breed can generate offspring.'); + return; + } + let nn = a.copy(); nn.weights_ih = Matrix.crossover(a.weights_ih, b.weights_ih, ratio); nn.weights_ho = Matrix.crossover(a.weights_ho, b.weights_ho, ratio);