Last active
August 29, 2015 13:56
-
-
Save adrianseeley/9332610 to your computer and use it in GitHub Desktop.
GATO - WEIGHTED GENETIC FOLDER
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//<html><script> | |
function weighted_genetic_folder (number_of_inputs, number_of_nearest_neighbours) { | |
var identity_weights = []; | |
for (var i = 0; i < number_of_inputs; i++) | |
identity_weights.push(1); | |
var ret = { | |
number_of_nearest_neighbours: number_of_nearest_neighbours, | |
weights: identity_weights, | |
genetic_folds: [], | |
neighbourhood: [], | |
fitness: null, | |
fitness: function (training_list, weights, genetic_folds, neighbourhood) { | |
var errors = 0; | |
for (var t = 0; t < training_list.length; t++) | |
if (ret.classify(training_list[t].inputs, weights, genetic_folds, neighbourhood) != training_list[t].class) | |
errors++; | |
return errors; | |
}, | |
clone: function (populus) { | |
return JSON.parse(JSON.stringify(populus)); | |
}, | |
mutate: function (populus, weight_point_mutation_rate, weight_point_mutation_amount, add_genetic_fold_rate, remove_point_genetic_fold_rate, genetic_fold_point_mutation_rate, genetic_fold_point_mutation_amount) { | |
for (var w = 0; w < populus.weights.length; w++) | |
if (Math.random() < weight_point_mutation_rate) | |
populus.weights[w] += Math.random() * ((populus.weights[w] * weight_point_mutation_amount) - (populus.weights[w] * -weight_point_mutation_amount)) + (populus.weights[w] * -weight_point_mutation_amount); | |
if (Math.random() < add_genetic_fold_rate) | |
populus.genetic_folds.push(populus.neighbourhood[Math.floor(Math.random() * populus.neighbourhood.length)].value); | |
for (var g = populus.genetic_folds.length - 1; g >= 0; g--) { | |
if (Math.random() < remove_point_genetic_fold_rate) { | |
populus.genetic_folds.splice(g, 1); | |
continue; | |
} | |
if (Math.random() < genetic_fold_point_mutation_rate) | |
populus.genetic_folds[g].fold_point += Math.random() * ((populus.genetic_folds[g].fold_point * genetic_fold_point_mutation_amount) - (populus.genetic_folds[g].fold_point * -genetic_fold_point_mutation_amount)) + (populus.genetic_folds[g].fold_point * -genetic_fold_point_mutation_amount); | |
} | |
return populus; | |
}, | |
fold: function (fold_point, output_sum) { | |
if (output_sum > fold_point) return fold_point - (output_sum - fold_point); | |
return output_sum; | |
}, | |
train: function (training_list, training_list_error_threshold, iteration_threshold, maximum_population, nerf_rate, weight_point_mutation_rate, weight_point_mutation_amount, add_genetic_fold_rate, remove_point_genetic_fold_rate, genetic_fold_point_mutation_rate, genetic_fold_point_mutation_amount) { | |
var population = [{weights: ret.weights, genetic_folds: ret.genetic_folds, neighbourhood: ret.build_neighbourhood(training_list, ret.weights, ret.genetic_folds)}]; | |
population[0].fitness = ret.fitness(training_list, population[0].weights, population[0].genetic_folds, population[0].neighbourhood); | |
population[0].nerf = 1.0; | |
for (var i = 0; i < iteration_threshold && population[0].fitness > training_list_error_threshold; i++) { | |
//trace | |
for (var p = 0; p < population.length && p < 20; p++) | |
console.log('iter: ' + i, 'fit: ' + population[p].fitness, 'nerf: ' + population[p].nerf, 'folds: ' + population[p].genetic_folds.length, 'weights: ' + population[p].weights.join(', ')); | |
console.log(); | |
//trace | |
for (var p = population.length - 1; p >= 0; p--) { | |
population.push(ret.mutate(ret.clone(population[p]), weight_point_mutation_rate, weight_point_mutation_amount, add_genetic_fold_rate, remove_point_genetic_fold_rate, genetic_fold_point_mutation_rate, genetic_fold_point_mutation_amount)); | |
population[population.length - 1].neighbourhood = ret.build_neighbourhood(training_list, population[population.length - 1].weights, population[population.length - 1].genetic_folds); | |
population[population.length - 1].fitness = ret.fitness(training_list, population[p].weights, population[p].genetic_folds, population[p].neighbourhood); | |
population[population.length - 1].nerf = 1.0; | |
if (population[p].fitness <= population[population.length - 1].fitness) | |
population[p].nerf *= nerf_rate; | |
} | |
population.sort(function (a, b) { return (a.fitness * a.nerf) - (b.fitness * b.nerf) || a.genetic_folds.length - b.genetic_folds.length; }); | |
while (population.length > maximum_population) | |
population.pop(); | |
} | |
ret.weights = population[0].weights; | |
ret.genetic_folds = population[0].genetic_folds; | |
ret.neighbourhood = population[0].neighbourhood; | |
ret.fitness = population[0].fitness; | |
}, | |
build_neighbourhood: function (training_list, weights, genetic_folds) { | |
var neighbourhood = []; | |
for (var t = 0; t < training_list.length; t++) | |
neighbourhood.push({class: training_list[t].class, value: ret.express(training_list[t].inputs, weights, genetic_folds)}); | |
return neighbourhood; | |
}, | |
express: function (inputs, weights, genetic_folds) { | |
if (!weights) weights = ret.weights; | |
if (!genetic_folds) genetic_folds = ret.genetic_folds; | |
var weighted_inputs = []; | |
for (var i = 0; i < inputs.length; i++) | |
weighted_inputs.push(inputs[i] * weights[i]); | |
var output_sum = 0; | |
for (var w = 0; w < weighted_inputs.length; w++) | |
output_sum += weighted_inputs[w]; | |
for (var g = 0; g < genetic_folds.length; g++) | |
output_sum = ret.fold(genetic_folds[g], output_sum); | |
return output_sum; | |
}, | |
knearestneighbour: function (output_sum, neighbourhood) { | |
if (!neighbourhood) neighbourhood = ret.neighbourhood; | |
var neighbour_distances = []; | |
for (var n = 0; n < neighbourhood.length; n++) | |
neighbour_distances.push({class: neighbourhood[n].class, distance: Math.abs(neighbourhood[n].value - output_sum)}); | |
neighbour_distances.sort(function (a, b) { return a.distance - b.distance; }); | |
var nearest_neighbours = {}; | |
for (var n = 0; n < neighbour_distances.length && n < ret.number_of_nearest_neighbours; n++) { | |
if (!nearest_neighbours.hasOwnProperty(neighbour_distances[n].class)) | |
nearest_neighbours[neighbour_distances[n].class] = 0; | |
nearest_neighbours[neighbour_distances[n].class]++; | |
} | |
var most_voted_class = null; | |
var most_votes = null; | |
for (var n in nearest_neighbours) | |
if (most_votes == null || nearest_neighbours[n] > most_votes) { | |
most_voted_class = n; | |
most_votes = nearest_neighbours[n]; | |
} | |
return most_voted_class; | |
}, | |
classify: function (inputs, weights, genetic_folds, neighbourhood) { | |
return ret.knearestneighbour(ret.express(inputs, weights, genetic_folds), neighbourhood); | |
} | |
}; | |
return ret; | |
}; | |
var test_list = [{inputs: [5.1,3.5,1.4,0.2], class: 'Iris-setosa'}, | |
{inputs: [4.9,3.0,1.4,0.2], class: 'Iris-setosa'}, | |
{inputs: [4.7,3.2,1.3,0.2], class: 'Iris-setosa'}, | |
{inputs: [4.6,3.1,1.5,0.2], class: 'Iris-setosa'}, | |
{inputs: [5.0,3.6,1.4,0.2], class: 'Iris-setosa'}, | |
{inputs: [5.4,3.9,1.7,0.4], class: 'Iris-setosa'}, | |
{inputs: [4.6,3.4,1.4,0.3], class: 'Iris-setosa'}, | |
{inputs: [5.0,3.4,1.5,0.2], class: 'Iris-setosa'}, | |
{inputs: [4.4,2.9,1.4,0.2], class: 'Iris-setosa'}, | |
{inputs: [4.9,3.1,1.5,0.1], class: 'Iris-setosa'}, | |
{inputs: [5.4,3.7,1.5,0.2], class: 'Iris-setosa'}, | |
{inputs: [4.8,3.4,1.6,0.2], class: 'Iris-setosa'}, | |
{inputs: [4.8,3.0,1.4,0.1], class: 'Iris-setosa'}, | |
{inputs: [4.3,3.0,1.1,0.1], class: 'Iris-setosa'}, | |
{inputs: [5.8,4.0,1.2,0.2], class: 'Iris-setosa'}, | |
{inputs: [5.7,4.4,1.5,0.4], class: 'Iris-setosa'}, | |
{inputs: [5.4,3.9,1.3,0.4], class: 'Iris-setosa'}, | |
{inputs: [5.1,3.5,1.4,0.3], class: 'Iris-setosa'}, | |
{inputs: [5.7,3.8,1.7,0.3], class: 'Iris-setosa'}, | |
{inputs: [5.1,3.8,1.5,0.3], class: 'Iris-setosa'}, | |
{inputs: [5.4,3.4,1.7,0.2], class: 'Iris-setosa'}, | |
{inputs: [5.1,3.7,1.5,0.4], class: 'Iris-setosa'}, | |
{inputs: [4.6,3.6,1.0,0.2], class: 'Iris-setosa'}, | |
{inputs: [5.1,3.3,1.7,0.5], class: 'Iris-setosa'}, | |
{inputs: [4.8,3.4,1.9,0.2], class: 'Iris-setosa'}, | |
{inputs: [5.0,3.0,1.6,0.2], class: 'Iris-setosa'}, | |
{inputs: [5.0,3.4,1.6,0.4], class: 'Iris-setosa'}, | |
{inputs: [5.2,3.5,1.5,0.2], class: 'Iris-setosa'}, | |
{inputs: [5.2,3.4,1.4,0.2], class: 'Iris-setosa'}, | |
{inputs: [4.7,3.2,1.6,0.2], class: 'Iris-setosa'}, | |
{inputs: [4.8,3.1,1.6,0.2], class: 'Iris-setosa'}, | |
{inputs: [5.4,3.4,1.5,0.4], class: 'Iris-setosa'}, | |
{inputs: [5.2,4.1,1.5,0.1], class: 'Iris-setosa'}, | |
{inputs: [5.5,4.2,1.4,0.2], class: 'Iris-setosa'}, | |
{inputs: [4.9,3.1,1.5,0.1], class: 'Iris-setosa'}, | |
{inputs: [5.0,3.2,1.2,0.2], class: 'Iris-setosa'}, | |
{inputs: [5.5,3.5,1.3,0.2], class: 'Iris-setosa'}, | |
{inputs: [4.9,3.1,1.5,0.1], class: 'Iris-setosa'}, | |
{inputs: [4.4,3.0,1.3,0.2], class: 'Iris-setosa'}, | |
{inputs: [5.1,3.4,1.5,0.2], class: 'Iris-setosa'}, | |
{inputs: [5.0,3.5,1.3,0.3], class: 'Iris-setosa'}, | |
{inputs: [4.5,2.3,1.3,0.3], class: 'Iris-setosa'}, | |
{inputs: [4.4,3.2,1.3,0.2], class: 'Iris-setosa'}, | |
{inputs: [5.0,3.5,1.6,0.6], class: 'Iris-setosa'}, | |
{inputs: [5.1,3.8,1.9,0.4], class: 'Iris-setosa'}, | |
{inputs: [4.8,3.0,1.4,0.3], class: 'Iris-setosa'}, | |
{inputs: [5.1,3.8,1.6,0.2], class: 'Iris-setosa'}, | |
{inputs: [4.6,3.2,1.4,0.2], class: 'Iris-setosa'}, | |
{inputs: [5.3,3.7,1.5,0.2], class: 'Iris-setosa'}, | |
{inputs: [5.0,3.3,1.4,0.2], class: 'Iris-setosa'}, | |
{inputs: [7.0,3.2,4.7,1.4], class: 'Iris-versicolor'}, | |
{inputs: [6.4,3.2,4.5,1.5], class: 'Iris-versicolor'}, | |
{inputs: [6.9,3.1,4.9,1.5], class: 'Iris-versicolor'}, | |
{inputs: [5.5,2.3,4.0,1.3], class: 'Iris-versicolor'}, | |
{inputs: [6.5,2.8,4.6,1.5], class: 'Iris-versicolor'}, | |
{inputs: [5.7,2.8,4.5,1.3], class: 'Iris-versicolor'}, | |
{inputs: [6.3,3.3,4.7,1.6], class: 'Iris-versicolor'}, | |
{inputs: [4.9,2.4,3.3,1.0], class: 'Iris-versicolor'}, | |
{inputs: [6.6,2.9,4.6,1.3], class: 'Iris-versicolor'}, | |
{inputs: [5.2,2.7,3.9,1.4], class: 'Iris-versicolor'}, | |
{inputs: [5.0,2.0,3.5,1.0], class: 'Iris-versicolor'}, | |
{inputs: [5.9,3.0,4.2,1.5], class: 'Iris-versicolor'}, | |
{inputs: [6.0,2.2,4.0,1.0], class: 'Iris-versicolor'}, | |
{inputs: [6.1,2.9,4.7,1.4], class: 'Iris-versicolor'}, | |
{inputs: [5.6,2.9,3.6,1.3], class: 'Iris-versicolor'}, | |
{inputs: [6.7,3.1,4.4,1.4], class: 'Iris-versicolor'}, | |
{inputs: [5.6,3.0,4.5,1.5], class: 'Iris-versicolor'}, | |
{inputs: [5.8,2.7,4.1,1.0], class: 'Iris-versicolor'}, | |
{inputs: [6.2,2.2,4.5,1.5], class: 'Iris-versicolor'}, | |
{inputs: [5.6,2.5,3.9,1.1], class: 'Iris-versicolor'}, | |
{inputs: [5.9,3.2,4.8,1.8], class: 'Iris-versicolor'}, | |
{inputs: [6.1,2.8,4.0,1.3], class: 'Iris-versicolor'}, | |
{inputs: [6.3,2.5,4.9,1.5], class: 'Iris-versicolor'}, | |
{inputs: [6.1,2.8,4.7,1.2], class: 'Iris-versicolor'}, | |
{inputs: [6.4,2.9,4.3,1.3], class: 'Iris-versicolor'}, | |
{inputs: [6.6,3.0,4.4,1.4], class: 'Iris-versicolor'}, | |
{inputs: [6.8,2.8,4.8,1.4], class: 'Iris-versicolor'}, | |
{inputs: [6.7,3.0,5.0,1.7], class: 'Iris-versicolor'}, | |
{inputs: [6.0,2.9,4.5,1.5], class: 'Iris-versicolor'}, | |
{inputs: [5.7,2.6,3.5,1.0], class: 'Iris-versicolor'}, | |
{inputs: [5.5,2.4,3.8,1.1], class: 'Iris-versicolor'}, | |
{inputs: [5.5,2.4,3.7,1.0], class: 'Iris-versicolor'}, | |
{inputs: [5.8,2.7,3.9,1.2], class: 'Iris-versicolor'}, | |
{inputs: [6.0,2.7,5.1,1.6], class: 'Iris-versicolor'}, | |
{inputs: [5.4,3.0,4.5,1.5], class: 'Iris-versicolor'}, | |
{inputs: [6.0,3.4,4.5,1.6], class: 'Iris-versicolor'}, | |
{inputs: [6.7,3.1,4.7,1.5], class: 'Iris-versicolor'}, | |
{inputs: [6.3,2.3,4.4,1.3], class: 'Iris-versicolor'}, | |
{inputs: [5.6,3.0,4.1,1.3], class: 'Iris-versicolor'}, | |
{inputs: [5.5,2.5,4.0,1.3], class: 'Iris-versicolor'}, | |
{inputs: [5.5,2.6,4.4,1.2], class: 'Iris-versicolor'}, | |
{inputs: [6.1,3.0,4.6,1.4], class: 'Iris-versicolor'}, | |
{inputs: [5.8,2.6,4.0,1.2], class: 'Iris-versicolor'}, | |
{inputs: [5.0,2.3,3.3,1.0], class: 'Iris-versicolor'}, | |
{inputs: [5.6,2.7,4.2,1.3], class: 'Iris-versicolor'}, | |
{inputs: [5.7,3.0,4.2,1.2], class: 'Iris-versicolor'}, | |
{inputs: [5.7,2.9,4.2,1.3], class: 'Iris-versicolor'}, | |
{inputs: [6.2,2.9,4.3,1.3], class: 'Iris-versicolor'}, | |
{inputs: [5.1,2.5,3.0,1.1], class: 'Iris-versicolor'}, | |
{inputs: [5.7,2.8,4.1,1.3], class: 'Iris-versicolor'}, | |
{inputs: [6.3,3.3,6.0,2.5], class: 'Iris-virginica'}, | |
{inputs: [5.8,2.7,5.1,1.9], class: 'Iris-virginica'}, | |
{inputs: [7.1,3.0,5.9,2.1], class: 'Iris-virginica'}, | |
{inputs: [6.3,2.9,5.6,1.8], class: 'Iris-virginica'}, | |
{inputs: [6.5,3.0,5.8,2.2], class: 'Iris-virginica'}, | |
{inputs: [7.6,3.0,6.6,2.1], class: 'Iris-virginica'}, | |
{inputs: [4.9,2.5,4.5,1.7], class: 'Iris-virginica'}, | |
{inputs: [7.3,2.9,6.3,1.8], class: 'Iris-virginica'}, | |
{inputs: [6.7,2.5,5.8,1.8], class: 'Iris-virginica'}, | |
{inputs: [7.2,3.6,6.1,2.5], class: 'Iris-virginica'}, | |
{inputs: [6.5,3.2,5.1,2.0], class: 'Iris-virginica'}, | |
{inputs: [6.4,2.7,5.3,1.9], class: 'Iris-virginica'}, | |
{inputs: [6.8,3.0,5.5,2.1], class: 'Iris-virginica'}, | |
{inputs: [5.7,2.5,5.0,2.0], class: 'Iris-virginica'}, | |
{inputs: [5.8,2.8,5.1,2.4], class: 'Iris-virginica'}, | |
{inputs: [6.4,3.2,5.3,2.3], class: 'Iris-virginica'}, | |
{inputs: [6.5,3.0,5.5,1.8], class: 'Iris-virginica'}, | |
{inputs: [7.7,3.8,6.7,2.2], class: 'Iris-virginica'}, | |
{inputs: [7.7,2.6,6.9,2.3], class: 'Iris-virginica'}, | |
{inputs: [6.0,2.2,5.0,1.5], class: 'Iris-virginica'}, | |
{inputs: [6.9,3.2,5.7,2.3], class: 'Iris-virginica'}, | |
{inputs: [5.6,2.8,4.9,2.0], class: 'Iris-virginica'}, | |
{inputs: [7.7,2.8,6.7,2.0], class: 'Iris-virginica'}, | |
{inputs: [6.3,2.7,4.9,1.8], class: 'Iris-virginica'}, | |
{inputs: [6.7,3.3,5.7,2.1], class: 'Iris-virginica'}, | |
{inputs: [7.2,3.2,6.0,1.8], class: 'Iris-virginica'}, | |
{inputs: [6.2,2.8,4.8,1.8], class: 'Iris-virginica'}, | |
{inputs: [6.1,3.0,4.9,1.8], class: 'Iris-virginica'}, | |
{inputs: [6.4,2.8,5.6,2.1], class: 'Iris-virginica'}, | |
{inputs: [7.2,3.0,5.8,1.6], class: 'Iris-virginica'}, | |
{inputs: [7.4,2.8,6.1,1.9], class: 'Iris-virginica'}, | |
{inputs: [7.9,3.8,6.4,2.0], class: 'Iris-virginica'}, | |
{inputs: [6.4,2.8,5.6,2.2], class: 'Iris-virginica'}, | |
{inputs: [6.3,2.8,5.1,1.5], class: 'Iris-virginica'}, | |
{inputs: [6.1,2.6,5.6,1.4], class: 'Iris-virginica'}, | |
{inputs: [7.7,3.0,6.1,2.3], class: 'Iris-virginica'}, | |
{inputs: [6.3,3.4,5.6,2.4], class: 'Iris-virginica'}, | |
{inputs: [6.4,3.1,5.5,1.8], class: 'Iris-virginica'}, | |
{inputs: [6.0,3.0,4.8,1.8], class: 'Iris-virginica'}, | |
{inputs: [6.9,3.1,5.4,2.1], class: 'Iris-virginica'}, | |
{inputs: [6.7,3.1,5.6,2.4], class: 'Iris-virginica'}, | |
{inputs: [6.9,3.1,5.1,2.3], class: 'Iris-virginica'}, | |
{inputs: [5.8,2.7,5.1,1.9], class: 'Iris-virginica'}, | |
{inputs: [6.8,3.2,5.9,2.3], class: 'Iris-virginica'}, | |
{inputs: [6.7,3.3,5.7,2.5], class: 'Iris-virginica'}, | |
{inputs: [6.7,3.0,5.2,2.3], class: 'Iris-virginica'}, | |
{inputs: [6.3,2.5,5.0,1.9], class: 'Iris-virginica'}, | |
{inputs: [6.5,3.0,5.2,2.0], class: 'Iris-virginica'}, | |
{inputs: [6.2,3.4,5.4,2.3], class: 'Iris-virginica'}, | |
{inputs: [5.9,3.0,5.1,1.8], class: 'Iris-virginica'}]; | |
var wgf = weighted_genetic_folder(test_list[0].inputs.length, 10); | |
wgf.train(test_list, | |
0, // training_list_error_threshold | |
1000, // iteration_threshold | |
100, // maximum_population | |
1.01, // nerf_rate | |
0.05, // weight_point_mutation_rate | |
0.05, // weight_point_mutation_amount | |
0.05, // add_genetic_fold_rate | |
0.05, // remove_point_genetic_fold_rate | |
0.05, // genetic_fold_point_mutation_rate | |
0.05 // genetic_fold_point_mutation_amount | |
); | |
for (var t = 0; t < test_list.length; t++) | |
console.log(JSON.stringify(test_list[t]) + '->' + wgf.classify(test_list[t].inputs)); | |
//</script></html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment