Skip to content

Instantly share code, notes, and snippets.

@adrianseeley
Last active November 9, 2017 06:42
Show Gist options
  • Save adrianseeley/9582220 to your computer and use it in GitHub Desktop.
Save adrianseeley/9582220 to your computer and use it in GitHub Desktop.
Code Used To Generate: Neural Genetic Adaptation of the Iris Dataset (GATO-2014)
function gnn (cases, wide, tall, population, iterations, error_fn, error_thresh) {
var inputs = cases[0][0].length;
var outputs = cases[0][1].length;
// declare net, provide input layer
var net = [new Array(inputs)];
// create input neurons in input layer
for (var i = 0; i < inputs; i++)
net[0][i] = {output: 0}
// create hidden layers
for (var x = 0; x < wide; x++) {
var hidden_layer = [];
// create hidden neurons
for (var y = 0; y < tall; y++) {
// create weights from length of previous layer in net
var weights = [];
for (var w = 0; w < net[net.length - 1].length; w++)
weights.push(0);
var hidden_node = {weights: weights, bias: 0, output: 0}
hidden_layer.push(hidden_node);
}
net.push(hidden_layer);
}
// create output layer
var output_layer = [];
for (var o = 0; o < outputs; o++) {
var weights = [];
for (var w = 0; w < net[net.length - 1].length; w++)
weights.push(0);
output_layer.push({weights: weights, bias: 0, output: 0});
}
net.push(output_layer);
// declare population and fill
var pop = [];
while(pop.length < population)
pop.push(JSON.parse(JSON.stringify(net)));
// declare snaps
var snaps = [-32, -16, -8, -4, -2, -1, -0.5, -0.25, 0, 0.25, 0.5, 1, 2, 4, 8, 16, 32];
// declare breeding cap
var breeding_cap = Math.ceil(population * 0.05);
// provide starting fitness
pop[0].fitness = error_fn(pop[0], cases);
// begin genetic cycle
for (var i = 0; i < iterations && pop[0].fitness > error_thresh; i++) {
var muta = (Math.sin(i * (1 / (10 + (i / 100)))) + 1) / 2;
console.log(i, pop[0].fitness, muta);
// fill breeding room
for (var dest = breeding_cap; dest < pop.length; dest = dest /*NOOP*/) {
for (var host_left = 0; host_left < breeding_cap && dest < pop.length; host_left++) {
for (var host_right = 0; host_right < breeding_cap && dest < pop.length; host_right++) {
for (var layer = 1; layer < pop[host_left].length; layer++) {
for (var neuron = 0; neuron < pop[host_left][layer].length; neuron++) {
// weights
for (var weight = 0; weight < pop[host_left][layer][neuron].weights.length; weight++) {
// perform snapping (choose new component from snaps)
if (Math.random() < muta) {
pop[dest][layer][neuron].weights[weight] = snaps[Math.floor(Math.random() * snaps.length)];
// perform full crossover (copy right component)
} else if (Math.random() < muta) {
pop[dest][layer][neuron].weights[weight] = pop[host_right][layer][neuron].weights[weight];
// perform average crossover (add left and right components then divide by 2)
} else if (Math.random() < muta) {
pop[dest][layer][neuron].weights[weight] = (pop[host_left][layer][neuron].weights[weight] + pop[host_right][layer][neuron].weights[weight]) / 2;
// copy left component (full left crossover)
} else {
pop[dest][layer][neuron].weights[weight] = pop[host_left][layer][neuron].weights[weight];
}
// perform mutation independtanly (so crossover or snap then muta is possible)
if (Math.random() < muta) {
pop[dest][layer][neuron].weights[weight] += muta * ((Math.random() * 2) - 1);
}
}
// bias
// perform snapping (choose new bias from snaps)
if (Math.random() < muta) {
pop[dest][layer][neuron].bias = snaps[Math.floor(Math.random() * snaps.length)];
// perform full crossover (copy right bias)
} else if (Math.random() < muta) {
pop[dest][layer][neuron].bias = pop[host_right][layer][neuron].bias;
// perform average crossover (add left and right bias then divide by 2)
} else if (Math.random() < muta) {
pop[dest][layer][neuron].bias = (pop[host_left][layer][neuron].bias + pop[host_right][layer][neuron].bias) / 2;
// copy left bias (full left crossover)
} else {
pop[dest][layer][neuron].bias = pop[host_left][layer][neuron].bias;
}
// perform mutation independtanly (so crossover or snap then muta is possible)
if (Math.random() < muta) {
pop[dest][layer][neuron].bias += muta * ((Math.random() * 2) - 1);
}
}
}
dest++;
}
}
}
// provide fitness to new networks
for (var dest = breeding_cap; dest < pop.length; dest++) {
pop[dest].fitness = error_fn(pop[dest], cases);
}
// sort pop
pop.sort(function (a, b) { return a.fitness - b.fitness; });
}
return pop[0];
};
function run (nn, inputs) {
// provide input values to input neurons
for (var i = 0; i < inputs.length; i++)
nn[0][i].output = inputs[i];
// resolve network
for (var x = 1; x < nn.length; x++)
for (var y = 0; y < nn[x].length; y++) {
// transfer
nn[x][y].output = nn[x][y].bias;
for (var y2 = 0; y2 < nn[x - 1].length; y2++)
nn[x][y].output += nn[x - 1][y2].output * nn[x][y].weights[y2];
// activate
nn[x][y].output = 1 / (1 + Math.exp(-nn[x][y].output));
}
// gather outputs
var outputs = [];
for (var o = 0; o < nn[nn.length - 1].length; o++)
outputs.push(nn[nn.length - 1][o].output);
return outputs;
};
function error_rmse (nn, cases) {
var se_overall = 0;
for (var c = 0; c < cases.length; c++) {
var outputs = run(nn, cases[c][0]);
var se_per_case = 0;
for (var o = 0; o < outputs.length; o++)
se_per_case += Math.pow(outputs[o] - cases[c][1][o], 2);
se_overall += Math.sqrt(se_per_case / outputs.length);
}
return Math.sqrt(se_overall / cases.length);
};
var iris = [
[[5.1, 3.5, 1.4, 0.2], [0]],
[[4.9, 3.0, 1.4, 0.2], [0]],
[[4.7, 3.2, 1.3, 0.2], [0]],
[[4.6, 3.1, 1.5, 0.2], [0]],
[[5.0, 3.6, 1.4, 0.2], [0]],
[[5.4, 3.9, 1.7, 0.4], [0]],
[[4.6, 3.4, 1.4, 0.3], [0]],
[[5.0, 3.4, 1.5, 0.2], [0]],
[[4.4, 2.9, 1.4, 0.2], [0]],
[[4.9, 3.1, 1.5, 0.1], [0]],
[[5.4, 3.7, 1.5, 0.2], [0]],
[[4.8, 3.4, 1.6, 0.2], [0]],
[[4.8, 3.0, 1.4, 0.1], [0]],
[[4.3, 3.0, 1.1, 0.1], [0]],
[[5.8, 4.0, 1.2, 0.2], [0]],
[[5.7, 4.4, 1.5, 0.4], [0]],
[[5.4, 3.9, 1.3, 0.4], [0]],
[[5.1, 3.5, 1.4, 0.3], [0]],
[[5.7, 3.8, 1.7, 0.3], [0]],
[[5.1, 3.8, 1.5, 0.3], [0]],
[[5.4, 3.4, 1.7, 0.2], [0]],
[[5.1, 3.7, 1.5, 0.4], [0]],
[[4.6, 3.6, 1.0, 0.2], [0]],
[[5.1, 3.3, 1.7, 0.5], [0]],
[[4.8, 3.4, 1.9, 0.2], [0]],
[[5.0, 3.0, 1.6, 0.2], [0]],
[[5.0, 3.4, 1.6, 0.4], [0]],
[[5.2, 3.5, 1.5, 0.2], [0]],
[[5.2, 3.4, 1.4, 0.2], [0]],
[[4.7, 3.2, 1.6, 0.2], [0]],
[[4.8, 3.1, 1.6, 0.2], [0]],
[[5.4, 3.4, 1.5, 0.4], [0]],
[[5.2, 4.1, 1.5, 0.1], [0]],
[[5.5, 4.2, 1.4, 0.2], [0]],
[[4.9, 3.1, 1.5, 0.2], [0]],
[[5.0, 3.2, 1.2, 0.2], [0]],
[[5.5, 3.5, 1.3, 0.2], [0]],
[[4.9, 3.6, 1.4, 0.1], [0]],
[[4.4, 3.0, 1.3, 0.2], [0]],
[[5.1, 3.4, 1.5, 0.2], [0]],
[[5.0, 3.5, 1.3, 0.3], [0]],
[[4.5, 2.3, 1.3, 0.3], [0]],
[[4.4, 3.2, 1.3, 0.2], [0]],
[[5.0, 3.5, 1.6, 0.6], [0]],
[[5.1, 3.8, 1.9, 0.4], [0]],
[[4.8, 3.0, 1.4, 0.3], [0]],
[[5.1, 3.8, 1.6, 0.2], [0]],
[[4.6, 3.2, 1.4, 0.2], [0]],
[[5.3, 3.7, 1.5, 0.2], [0]],
[[5.0, 3.3, 1.4, 0.2], [0]],
[[7.0, 3.2, 4.7, 1.4], [0.5]],
[[6.4, 3.2, 4.5, 1.5], [0.5]],
[[6.9, 3.1, 4.9, 1.5], [0.5]],
[[5.5, 2.3, 4.0, 1.3], [0.5]],
[[6.5, 2.8, 4.6, 1.5], [0.5]],
[[5.7, 2.8, 4.5, 1.3], [0.5]],
[[6.3, 3.3, 4.7, 1.6], [0.5]],
[[4.9, 2.4, 3.3, 1.0], [0.5]],
[[6.6, 2.9, 4.6, 1.3], [0.5]],
[[5.2, 2.7, 3.9, 1.4], [0.5]],
[[5.0, 2.0, 3.5, 1.0], [0.5]],
[[5.9, 3.0, 4.2, 1.5], [0.5]],
[[6.0, 2.2, 4.0, 1.0], [0.5]],
[[6.1, 2.9, 4.7, 1.4], [0.5]],
[[5.6, 2.9, 3.6, 1.3], [0.5]],
[[6.7, 3.1, 4.4, 1.4], [0.5]],
[[5.6, 3.0, 4.5, 1.5], [0.5]],
[[5.8, 2.7, 4.1, 1.0], [0.5]],
[[6.2, 2.2, 4.5, 1.5], [0.5]],
[[5.6, 2.5, 3.9, 1.1], [0.5]],
[[5.9, 3.2, 4.8, 1.8], [0.5]],
[[6.1, 2.8, 4.0, 1.3], [0.5]],
[[6.3, 2.5, 4.9, 1.5], [0.5]],
[[6.1, 2.8, 4.7, 1.2], [0.5]],
[[6.4, 2.9, 4.3, 1.3], [0.5]],
[[6.6, 3.0, 4.4, 1.4], [0.5]],
[[6.8, 2.8, 4.8, 1.4], [0.5]],
[[6.7, 3.0, 5.0, 1.7], [0.5]],
[[6.0, 2.9, 4.5, 1.5], [0.5]],
[[5.7, 2.6, 3.5, 1.0], [0.5]],
[[5.5, 2.4, 3.8, 1.1], [0.5]],
[[5.5, 2.4, 3.7, 1.0], [0.5]],
[[5.8, 2.7, 3.9, 1.2], [0.5]],
[[6.0, 2.7, 5.1, 1.6], [0.5]],
[[5.4, 3.0, 4.5, 1.5], [0.5]],
[[6.0, 3.4, 4.5, 1.6], [0.5]],
[[6.7, 3.1, 4.7, 1.5], [0.5]],
[[6.3, 2.3, 4.4, 1.3], [0.5]],
[[5.6, 3.0, 4.1, 1.3], [0.5]],
[[5.5, 2.5, 4.0, 1.3], [0.5]],
[[5.5, 2.6, 4.4, 1.2], [0.5]],
[[6.1, 3.0, 4.6, 1.4], [0.5]],
[[5.8, 2.6, 4.0, 1.2], [0.5]],
[[5.0, 2.3, 3.3, 1.0], [0.5]],
[[5.6, 2.7, 4.2, 1.3], [0.5]],
[[5.7, 3.0, 4.2, 1.2], [0.5]],
[[5.7, 2.9, 4.2, 1.3], [0.5]],
[[6.2, 2.9, 4.3, 1.3], [0.5]],
[[5.1, 2.5, 3.0, 1.1], [0.5]],
[[5.7, 2.8, 4.1, 1.3], [0.5]],
[[6.3, 3.3, 6.0, 2.5], [1]],
[[5.8, 2.7, 5.1, 1.9], [1]],
[[7.1, 3.0, 5.9, 2.1], [1]],
[[6.3, 2.9, 5.6, 1.8], [1]],
[[6.5, 3.0, 5.8, 2.2], [1]],
[[7.6, 3.0, 6.6, 2.1], [1]],
[[4.9, 2.5, 4.5, 1.7], [1]],
[[7.3, 2.9, 6.3, 1.8], [1]],
[[6.7, 2.5, 5.8, 1.8], [1]],
[[7.2, 3.6, 6.1, 2.5], [1]],
[[6.5, 3.2, 5.1, 2.0], [1]],
[[6.4, 2.7, 5.3, 1.9], [1]],
[[6.8, 3.0, 5.5, 2.1], [1]],
[[5.7, 2.5, 5.0, 2.0], [1]],
[[5.8, 2.8, 5.1, 2.4], [1]],
[[6.4, 3.2, 5.3, 2.3], [1]],
[[6.5, 3.0, 5.5, 1.8], [1]],
[[7.7, 3.8, 6.7, 2.2], [1]],
[[7.7, 2.6, 6.9, 2.3], [1]],
[[6.0, 2.2, 5.0, 1.5], [1]],
[[6.9, 3.2, 5.7, 2.3], [1]],
[[5.6, 2.8, 4.9, 2.0], [1]],
[[7.7, 2.8, 6.7, 2.0], [1]],
[[6.3, 2.7, 4.9, 1.8], [1]],
[[6.7, 3.3, 5.7, 2.1], [1]],
[[7.2, 3.2, 6.0, 1.8], [1]],
[[6.2, 2.8, 4.8, 1.8], [1]],
[[6.1, 3.0, 4.9, 1.8], [1]],
[[6.4, 2.8, 5.6, 2.1], [1]],
[[7.2, 3.0, 5.8, 1.6], [1]],
[[7.4, 2.8, 6.1, 1.9], [1]],
[[7.9, 3.8, 6.4, 2.0], [1]],
[[6.4, 2.8, 5.6, 2.2], [1]],
[[6.3, 2.8, 5.1, 1.5], [1]],
[[6.1, 2.6, 5.6, 1.4], [1]],
[[7.7, 3.0, 6.1, 2.3], [1]],
[[6.3, 3.4, 5.6, 2.4], [1]],
[[6.4, 3.1, 5.5, 1.8], [1]],
[[6.0, 3.0, 4.8, 1.8], [1]],
[[6.9, 3.1, 5.4, 2.1], [1]],
[[6.7, 3.1, 5.6, 2.4], [1]],
[[6.9, 3.1, 5.1, 2.3], [1]],
[[5.8, 2.7, 5.1, 1.9], [1]],
[[6.8, 3.2, 5.9, 2.3], [1]],
[[6.7, 3.3, 5.7, 2.5], [1]],
[[6.7, 3.0, 5.2, 2.3], [1]],
[[6.3, 2.5, 5.0, 1.9], [1]],
[[6.5, 3.0, 5.2, 2.0], [1]],
[[6.2, 3.4, 5.4, 2.3], [1]],
[[5.9, 3.0, 5.1, 1.8], [1]]
];
var nn = gnn(iris, 1, 20, 1000, Infinity, error_rmse, 0.00);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment