tfjs-evolution 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,61 @@
1
+ import { NeuroEvolution } from "./neuro-evolution";
2
+ import { TeachableMobileNet } from "../models/teachable-evolution";
3
+ export class GeneticAlgorithm extends NeuroEvolution {
4
+ /**
5
+ * Implementatin abstract methods
6
+ */
7
+ crossover() {
8
+ // console.log("Applying crossover on Genetic Algorithms...")
9
+ const selected = this.select_parents_by_rollet_wheels();
10
+ const individual_1 = selected[0];
11
+ const individual_2 = selected[1];
12
+ // console.log("Individual 1: ")
13
+ // individual_1.individual.getHead().summary();
14
+ let individual_3 = { individual: new TeachableMobileNet };
15
+ const alfa = Math.random();
16
+ individual_3.individual.getHead().layers.forEach((layer, index) => {
17
+ individual_3.individual.getHead().layers[index].setWeights(individual_1.individual.getHead().layers[index].getWeights()
18
+ .map((elem, index_2) => elem.mul(alfa)
19
+ .add(individual_2.individual.getHead().layers[index]
20
+ .getWeights()[index_2]
21
+ .mul(1 - alfa))));
22
+ });
23
+ // this.population.push(individual_3);
24
+ // console.log("Population: ", this.population.length);
25
+ return individual_3;
26
+ } //end of crossover
27
+ mutation(offspring) {
28
+ const multation_rate = 1;
29
+ offspring.forEach((elem) => {
30
+ elem.individual.getHead().setWeights(elem.individual.getHead().getWeights().map((elem_2) => {
31
+ return elem_2.add(elem_2.mul(multation_rate * Math.random()));
32
+ }));
33
+ });
34
+ }
35
+ selection() {
36
+ const selected_individuals = this.select_parents_by_rollet_wheels(this.population_size);
37
+ // const selected_individuals_copy: any=[];
38
+ // selected_individuals.forEach(async (elem)=>{
39
+ // const aux: Individual= {individual: new TeachableMobileNet()};
40
+ // // await this.copyModel(elem.individual.getHead(), aux.individual.getHead());
41
+ // // aux.individual.getHead().summary();
42
+ // selected_individuals_copy.push({individual: aux, accuracy: elem.accuracy});
43
+ // });
44
+ // console.log("Memory before cleaning: ", tf.memory().numBytes);
45
+ //Cleaning memory
46
+ // this.population.forEach((elem)=> elem.individual.getHead().dispose())
47
+ // this.population=[];
48
+ //The best will enter on the population by elitism
49
+ const best = this.getTheBest();
50
+ this.population = [];
51
+ this.population = selected_individuals;
52
+ //Adding one extra individual by elitism
53
+ // this.population.push(best);
54
+ console.log("Best accuracy (elitism): ", best.accuracy);
55
+ // console.log("Current population length: ", this.population.length);
56
+ // console.log("Current population: ", this.population);
57
+ // console.log("After selection: ", this.population[0])
58
+ // console.log("Memory before cleaning: ", tf.memory().numBytes);
59
+ }
60
+ }
61
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXRpYy1hbGdvcml0aG0uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90ZmpzLWV2b2x1dGlvbi9zcmMvbGliL0NsYXNzZXMvZ2VuZXRpYy1hbGdvcml0aG0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ25ELE9BQU8sRUFBQyxrQkFBa0IsRUFBQyxNQUFNLCtCQUErQixDQUFBO0FBZWhFLE1BQU0sT0FBTyxnQkFBaUIsU0FBUSxjQUFjO0lBSWhEOztPQUVHO0lBRU0sU0FBUztRQUNkLDZEQUE2RDtRQUU3RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsK0JBQStCLEVBQUUsQ0FBQztRQUV4RCxNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDakMsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRWpDLGdDQUFnQztRQUNoQywrQ0FBK0M7UUFFL0MsSUFBSSxZQUFZLEdBQWMsRUFBQyxVQUFVLEVBQUUsSUFBSSxrQkFBa0IsRUFBQyxDQUFDO1FBRW5FLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUUzQixZQUFZLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFDLEVBQUU7WUFDN0QsWUFBWSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsVUFBVSxDQUN0RCxZQUFZLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxVQUFVLEVBQUU7aUJBQzNELEdBQUcsQ0FBQyxDQUFDLElBQVMsRUFBRSxPQUFZLEVBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDO2lCQUM5QyxHQUFHLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDO2lCQUNuRCxVQUFVLEVBQUUsQ0FBQyxPQUFPLENBQUM7aUJBQ3JCLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQ2pCLENBQUMsQ0FBQyxDQUFBO1FBQ1AsQ0FBQyxDQUFDLENBQUE7UUFFRixzQ0FBc0M7UUFDdEMseURBQXlEO1FBRXpELE9BQU8sWUFBWSxDQUFDO0lBRXhCLENBQUMsQ0FBQSxrQkFBa0I7SUFFVixRQUFRLENBQUMsU0FBdUI7UUFFckMsTUFBTSxjQUFjLEdBQUMsQ0FBQyxDQUFDO1FBRXZCLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUMsRUFBRTtZQUN0QixJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDLFVBQVUsQ0FDaEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUMsRUFBRTtnQkFDbkQsT0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsY0FBYyxHQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUE7WUFDN0QsQ0FBQyxDQUFDLENBQ0gsQ0FBQztRQUNSLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQztJQUVRLFNBQVM7UUFFZCxNQUFNLG9CQUFvQixHQUFFLElBQUksQ0FBQywrQkFBK0IsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7UUFFdkYsMkNBQTJDO1FBRTNDLCtDQUErQztRQUUvQyxxRUFBcUU7UUFFckUsb0ZBQW9GO1FBRXBGLDZDQUE2QztRQUU3QyxrRkFBa0Y7UUFDbEYsTUFBTTtRQUdOLGlFQUFpRTtRQUVqRSxpQkFBaUI7UUFDakIsd0VBQXdFO1FBQ3hFLHNCQUFzQjtRQUV0QixrREFBa0Q7UUFDbEQsTUFBTSxJQUFJLEdBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBRTlCLElBQUksQ0FBQyxVQUFVLEdBQUMsRUFBRSxDQUFDO1FBRW5CLElBQUksQ0FBQyxVQUFVLEdBQUMsb0JBQW9CLENBQUM7UUFFckMsaURBQWlEO1FBQ2pELDhCQUE4QjtRQUU5QixPQUFPLENBQUMsR0FBRyxDQUFDLDJCQUEyQixFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUd4RCxzRUFBc0U7UUFDdEUsd0RBQXdEO1FBR3hELHVEQUF1RDtRQUN2RCxpRUFBaUU7SUFDckUsQ0FBQztDQUNKIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTmV1cm9Fdm9sdXRpb24gfSBmcm9tIFwiLi9uZXVyby1ldm9sdXRpb25cIjtcclxuaW1wb3J0IHtUZWFjaGFibGVNb2JpbGVOZXR9IGZyb20gXCIuLi9tb2RlbHMvdGVhY2hhYmxlLWV2b2x1dGlvblwiXHJcbmltcG9ydCAqIGFzIHRmIGZyb20gJ0B0ZW5zb3JmbG93L3RmanMnO1xyXG5cclxuLyoqXHJcbiAqIEVhY2ggaW5kaXZpZHVhbCBvZiB0aGUgcG9wdWxhdGlvbiB3aWxsIGJlIG1hZGUgb2YgXHJcbiAqIGFuIGFycmF5LCBjb3JyZXNwb2RlbnQgdG8gdGhlIG5ldXJhbCBuZXR3b3JrIHdlaWdodHMgYW5kXHJcbiAqIGFuIGV2YWx1YXRpb24sIGl0cyByZXNwZWN0aXZlIGFjY3VyYWN5IG9uIHRoZSBkYXRhc2V0IGdpdmVuLlxyXG4gKiBcclxuICovXHJcbmludGVyZmFjZSBJbmRpdmlkdWFsIHtcclxuICAgIGluZGl2aWR1YWw6IFRlYWNoYWJsZU1vYmlsZU5ldCxcclxuICAgIGFjY3VyYWN5PzogbnVtYmVyXHJcbn1cclxuXHJcblxyXG5leHBvcnQgY2xhc3MgR2VuZXRpY0FsZ29yaXRobSBleHRlbmRzIE5ldXJvRXZvbHV0aW9uIHsgXHJcbiAgICBcclxuICAgIFxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW1wbGVtZW50YXRpbiBhYnN0cmFjdCBtZXRob2RzXHJcbiAgICAgKi9cclxuXHJcbiAgICBvdmVycmlkZSBjcm9zc292ZXIoKTogSW5kaXZpZHVhbCB7XHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJBcHBseWluZyBjcm9zc292ZXIgb24gR2VuZXRpYyBBbGdvcml0aG1zLi4uXCIpXHJcblxyXG4gICAgICAgIGNvbnN0IHNlbGVjdGVkID0gdGhpcy5zZWxlY3RfcGFyZW50c19ieV9yb2xsZXRfd2hlZWxzKCk7XHJcblxyXG4gICAgICAgIGNvbnN0IGluZGl2aWR1YWxfMSA9IHNlbGVjdGVkWzBdO1xyXG4gICAgICAgIGNvbnN0IGluZGl2aWR1YWxfMiA9IHNlbGVjdGVkWzFdO1xyXG5cclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkluZGl2aWR1YWwgMTogXCIpXHJcbiAgICAgICAgLy8gaW5kaXZpZHVhbF8xLmluZGl2aWR1YWwuZ2V0SGVhZCgpLnN1bW1hcnkoKTtcclxuXHJcbiAgICAgICAgbGV0IGluZGl2aWR1YWxfMzogSW5kaXZpZHVhbD0ge2luZGl2aWR1YWw6IG5ldyBUZWFjaGFibGVNb2JpbGVOZXR9O1xyXG5cclxuICAgICAgICBjb25zdCBhbGZhID0gTWF0aC5yYW5kb20oKTtcclxuXHJcbiAgICAgICAgaW5kaXZpZHVhbF8zLmluZGl2aWR1YWwuZ2V0SGVhZCgpLmxheWVycy5mb3JFYWNoKChsYXllciwgaW5kZXgpPT57XHJcbiAgICAgICAgICAgIGluZGl2aWR1YWxfMy5pbmRpdmlkdWFsLmdldEhlYWQoKS5sYXllcnNbaW5kZXhdLnNldFdlaWdodHMoXHJcbiAgICAgICAgICAgICAgICBpbmRpdmlkdWFsXzEuaW5kaXZpZHVhbC5nZXRIZWFkKCkubGF5ZXJzW2luZGV4XS5nZXRXZWlnaHRzKClcclxuICAgICAgICAgICAgICAgIC5tYXAoKGVsZW06IGFueSwgaW5kZXhfMjogYW55KT0+IGVsZW0ubXVsKGFsZmEpXHJcbiAgICAgICAgICAgICAgICAuYWRkKGluZGl2aWR1YWxfMi5pbmRpdmlkdWFsLmdldEhlYWQoKS5sYXllcnNbaW5kZXhdXHJcbiAgICAgICAgICAgICAgICAuZ2V0V2VpZ2h0cygpW2luZGV4XzJdXHJcbiAgICAgICAgICAgICAgICAubXVsKDEgLSBhbGZhKVxyXG4gICAgICAgICAgICApKSlcclxuICAgICAgICB9KVxyXG5cclxuICAgICAgICAvLyB0aGlzLnBvcHVsYXRpb24ucHVzaChpbmRpdmlkdWFsXzMpO1xyXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKFwiUG9wdWxhdGlvbjogXCIsIHRoaXMucG9wdWxhdGlvbi5sZW5ndGgpOyAgXHJcbiAgICAgICAgXHJcbiAgICAgICAgcmV0dXJuIGluZGl2aWR1YWxfMzsgICAgICAgIFxyXG4gICAgXHJcbiAgICB9Ly9lbmQgb2YgY3Jvc3NvdmVyXHJcblxyXG4gICAgb3ZlcnJpZGUgbXV0YXRpb24ob2Zmc3ByaW5nOiBJbmRpdmlkdWFsW10pOiB2b2lkIHtcclxuXHJcbiAgICAgICAgY29uc3QgbXVsdGF0aW9uX3JhdGU9MTtcclxuXHJcbiAgICAgICAgb2Zmc3ByaW5nLmZvckVhY2goKGVsZW0pPT57XHJcbiAgICAgICAgICAgIGVsZW0uaW5kaXZpZHVhbC5nZXRIZWFkKCkuc2V0V2VpZ2h0cyhcclxuICAgICAgICAgICAgICAgIGVsZW0uaW5kaXZpZHVhbC5nZXRIZWFkKCkuZ2V0V2VpZ2h0cygpLm1hcCgoZWxlbV8yKT0+IHsgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgcmV0dXJuIGVsZW1fMi5hZGQoZWxlbV8yLm11bChtdWx0YXRpb25fcmF0ZSpNYXRoLnJhbmRvbSgpKSkgICAgIFxyXG4gICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgICApO1xyXG4gICAgICAgIH0pXHJcbiAgICB9XHJcblxyXG4gICAgb3ZlcnJpZGUgc2VsZWN0aW9uKCk6IHZvaWQge1xyXG5cclxuICAgICAgICBjb25zdCBzZWxlY3RlZF9pbmRpdmlkdWFscz0gdGhpcy5zZWxlY3RfcGFyZW50c19ieV9yb2xsZXRfd2hlZWxzKHRoaXMucG9wdWxhdGlvbl9zaXplKTtcclxuXHJcbiAgICAgICAgLy8gY29uc3Qgc2VsZWN0ZWRfaW5kaXZpZHVhbHNfY29weTogYW55PVtdO1xyXG5cclxuICAgICAgICAvLyBzZWxlY3RlZF9pbmRpdmlkdWFscy5mb3JFYWNoKGFzeW5jIChlbGVtKT0+e1xyXG5cclxuICAgICAgICAvLyAgICAgY29uc3QgYXV4OiBJbmRpdmlkdWFsPSB7aW5kaXZpZHVhbDogbmV3IFRlYWNoYWJsZU1vYmlsZU5ldCgpfTtcclxuXHJcbiAgICAgICAgLy8gICAgIC8vIGF3YWl0IHRoaXMuY29weU1vZGVsKGVsZW0uaW5kaXZpZHVhbC5nZXRIZWFkKCksIGF1eC5pbmRpdmlkdWFsLmdldEhlYWQoKSk7XHJcblxyXG4gICAgICAgIC8vICAgICAvLyBhdXguaW5kaXZpZHVhbC5nZXRIZWFkKCkuc3VtbWFyeSgpO1xyXG5cclxuICAgICAgICAvLyAgICAgc2VsZWN0ZWRfaW5kaXZpZHVhbHNfY29weS5wdXNoKHtpbmRpdmlkdWFsOiBhdXgsIGFjY3VyYWN5OiBlbGVtLmFjY3VyYWN5fSk7XHJcbiAgICAgICAgLy8gfSk7XHJcblxyXG4gICAgICAgIFxyXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKFwiTWVtb3J5IGJlZm9yZSBjbGVhbmluZzogXCIsIHRmLm1lbW9yeSgpLm51bUJ5dGVzKTtcclxuICAgICAgICBcclxuICAgICAgICAvL0NsZWFuaW5nIG1lbW9yeVxyXG4gICAgICAgIC8vIHRoaXMucG9wdWxhdGlvbi5mb3JFYWNoKChlbGVtKT0+IGVsZW0uaW5kaXZpZHVhbC5nZXRIZWFkKCkuZGlzcG9zZSgpKVxyXG4gICAgICAgIC8vIHRoaXMucG9wdWxhdGlvbj1bXTtcclxuXHJcbiAgICAgICAgLy9UaGUgYmVzdCB3aWxsIGVudGVyIG9uIHRoZSBwb3B1bGF0aW9uIGJ5IGVsaXRpc21cclxuICAgICAgICBjb25zdCBiZXN0PSB0aGlzLmdldFRoZUJlc3QoKTtcclxuXHJcbiAgICAgICAgdGhpcy5wb3B1bGF0aW9uPVtdO1xyXG5cclxuICAgICAgICB0aGlzLnBvcHVsYXRpb249c2VsZWN0ZWRfaW5kaXZpZHVhbHM7XHJcblxyXG4gICAgICAgIC8vQWRkaW5nIG9uZSBleHRyYSBpbmRpdmlkdWFsIGJ5IGVsaXRpc20gICAgICAgICBcclxuICAgICAgICAvLyB0aGlzLnBvcHVsYXRpb24ucHVzaChiZXN0KTtcclxuXHJcbiAgICAgICAgY29uc29sZS5sb2coXCJCZXN0IGFjY3VyYWN5IChlbGl0aXNtKTogXCIsIGJlc3QuYWNjdXJhY3kpO1xyXG4gICAgICAgIFxyXG4gICAgICAgIFxyXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKFwiQ3VycmVudCBwb3B1bGF0aW9uIGxlbmd0aDogXCIsIHRoaXMucG9wdWxhdGlvbi5sZW5ndGgpO1xyXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKFwiQ3VycmVudCBwb3B1bGF0aW9uOiBcIiwgdGhpcy5wb3B1bGF0aW9uKTtcclxuXHJcblxyXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKFwiQWZ0ZXIgc2VsZWN0aW9uOiBcIiwgdGhpcy5wb3B1bGF0aW9uWzBdKVxyXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKFwiTWVtb3J5IGJlZm9yZSBjbGVhbmluZzogXCIsIHRmLm1lbW9yeSgpLm51bUJ5dGVzKTtcclxuICAgIH1cclxufVxyXG4iXX0=
@@ -0,0 +1,199 @@
1
+ import { TeachableMobileNet } from "../models/teachable-evolution";
2
+ import * as tf from '@tensorflow/tfjs';
3
+ export class NeuroEvolution {
4
+ constructor() {
5
+ /**
6
+ This is the population. I have decided to create a population of just weights.
7
+ I had to change my mind. Working with weights is tricky.
8
+ I have decided to sacrifice memory to make my life easiser.
9
+ Tensors has their inner methods, it helps on the operators.
10
+ I have to pay attention to memory manegement.
11
+ Working with memory in tensors is tricky.
12
+ */
13
+ this.population = [];
14
+ this._population_size = 30;
15
+ }
16
+ /**Setters and Getters */
17
+ set population_size(population_size) {
18
+ this._population_size = population_size;
19
+ }
20
+ get population_size() {
21
+ return this._population_size;
22
+ }
23
+ /**
24
+ * Methods with implementation
25
+ */
26
+ async evaluate() {
27
+ return this.population.forEach(async (elem) => {
28
+ elem.accuracy = await elem.individual.evaluate();
29
+ });
30
+ }
31
+ start_population() {
32
+ for (let i = 0; i < this.population_size; i++) {
33
+ this.population.push({ individual: new TeachableMobileNet() });
34
+ }
35
+ // console.log("Population length: ", this.population.length);
36
+ // console.log("Memory after population iniialization: ", tf.memory().numBytes);
37
+ }
38
+ async apply_evolution(iteration) {
39
+ for (let i = 0; i < iteration; i++) {
40
+ console.log("Interation: ", i);
41
+ console.log("Memory: ", tf.memory().numBytes);
42
+ console.log("Tensors in memory: ", tf.memory().numTensors);
43
+ console.log("Population length: ", this.population.length);
44
+ await this.evolution();
45
+ }
46
+ }
47
+ /**
48
+ * This method will apply the evolution
49
+ */
50
+ async evolution() {
51
+ //Update the accuracy
52
+ await this.evaluate();
53
+ const offspring = [];
54
+ /**First step is crossover, for creating offspring */
55
+ for (let i = 0; i < this.population.length; i++) {
56
+ //The population will double in size
57
+ offspring.push(this.crossover());
58
+ }
59
+ //Mutation on the offspring
60
+ // console.log("Weight before mutation: ", offspring[0].individual.getHead().layers[0].getWeights()[0].dataSync());
61
+ this.mutation(offspring);
62
+ //Joining parents and offspring into the same pool for selection
63
+ this.population = [...this.population, ...offspring];
64
+ //Update the accuracy
65
+ await this.evaluate();
66
+ //selection
67
+ this.selection();
68
+ console.log("Best accuracy: ", this.getTheBest().accuracy);
69
+ console.log("Worst accuracy: ", this.getTheWorst().accuracy);
70
+ }
71
+ /**Helpers */
72
+ getTheBest() {
73
+ let index_best = 0;
74
+ let best = 0;
75
+ this.population.forEach((elem, index) => {
76
+ if (elem.accuracy > best) {
77
+ best = elem.accuracy;
78
+ index_best = index;
79
+ }
80
+ });
81
+ return this.population[index_best];
82
+ }
83
+ getTheWorst() {
84
+ let index_worst = 0;
85
+ let worst = 1;
86
+ this.population.forEach((elem, index) => {
87
+ if (elem.accuracy < worst) {
88
+ worst = elem.accuracy;
89
+ index_worst = index;
90
+ }
91
+ });
92
+ return this.population[index_worst];
93
+ }
94
+ /**
95
+ * Selecting individuals by elitism
96
+ */
97
+ select_parents_by_rollet_wheels_v2(selection_number = 2) {
98
+ // console.log("Selecting parents by rollet wheels...");
99
+ const share = [];
100
+ let total = 0;
101
+ // console.log("Population length...", this.population.length);
102
+ //This will create an overall accuracy
103
+ this.population.forEach((elem) => total += elem.accuracy);
104
+ let pointer = 0;
105
+ this.population.forEach((elem, index) => {
106
+ // console.log("Accuracy...", elem.accuracy);
107
+ share.push({
108
+ index: index,
109
+ share: elem.accuracy / total,
110
+ min: pointer,
111
+ max: pointer + (elem.accuracy / total)
112
+ });
113
+ pointer += elem.accuracy / total;
114
+ });
115
+ // console.log("Shares: ", share);
116
+ const aux_selection = [];
117
+ //Selecting two individuals using roulette wheels
118
+ let counter = 0;
119
+ const indexes_aux = [];
120
+ while (counter < selection_number) {
121
+ //Random pointer, used to randomly select an individual
122
+ const aux_index = Math.random();
123
+ share.forEach((elem) => {
124
+ if ((elem.min < aux_index) && (elem.max > aux_index)) {
125
+ const aux = { individual: new TeachableMobileNet(), accuracy: this.population[elem.index].accuracy };
126
+ // console.log("Individual just created (weigth): ", aux.individual.getHead().layers[0].getWeights()[0].dataSync());
127
+ // console.log("Individual original: ", this.population[elem.index].individual.getHead().layers[0].getWeights()[0].dataSync());
128
+ // // Original Recipient
129
+ // this.copyModel(this.population[elem.index].individual.getHead(),aux.individual.getHead())
130
+ // this.population[elem.index].individual.getHead().dispose();
131
+ // console.log("Individual just created (weigtht, copied): ", aux.individual.getHead().layers[0].getWeights()[0].dataSync());
132
+ counter++;
133
+ aux_selection.push(this.population[elem.index]);
134
+ // indexes_aux.push(elem.index)
135
+ }
136
+ });
137
+ }
138
+ // this.population.forEach((elem, index)=>{
139
+ // if(!indexes_aux.includes(index)){
140
+ // console.log("Disposed...")
141
+ // elem.individual.getHead().dispose();
142
+ // }
143
+ // })
144
+ // this.population=[];
145
+ return aux_selection;
146
+ }
147
+ /**
148
+ * Selecting individuals by elitism
149
+ */
150
+ select_parents_by_rollet_wheels(selection_number = 2) {
151
+ // console.log
152
+ // ("Selecting parents by rollet wheels...");
153
+ const share = [];
154
+ let total = 0;
155
+ // console.log("Population length...", this.population.length);
156
+ //This will create an overall accuracy
157
+ this.population.forEach((elem) => total += elem.accuracy);
158
+ let pointer = 0;
159
+ this.population.forEach((elem, index) => {
160
+ // console.log("Accuracy...", elem.accuracy);
161
+ share.push({
162
+ index: index,
163
+ share: elem.accuracy / total,
164
+ min: pointer,
165
+ max: pointer + (elem.accuracy / total)
166
+ });
167
+ pointer += elem.accuracy / total;
168
+ });
169
+ // console.log("Shares: ", share);
170
+ const aux_selection = [];
171
+ //Selecting two individuals using roulette wheels
172
+ let counter = 0;
173
+ while (counter < selection_number) {
174
+ //Random pointer, used to randomly select an individual
175
+ const aux_index = Math.random();
176
+ share.forEach((elem) => {
177
+ if ((elem.min < aux_index) && (elem.max > aux_index)) {
178
+ counter++;
179
+ aux_selection.push(this.population[elem.index]);
180
+ }
181
+ });
182
+ }
183
+ return aux_selection;
184
+ }
185
+ /**
186
+ * This function will make a copy of a model on the weight level
187
+ * This is an attempt to avoid influencing the new model when the old one
188
+ * is eliminated.
189
+ *
190
+ * @param originalModel - the model to be copied
191
+ * @param recipient - the new model
192
+ */
193
+ async copyModel(originalModel, recipient) {
194
+ originalModel.layers.forEach((layer, index) => {
195
+ recipient.layers[index].setWeights(layer.getWeights());
196
+ });
197
+ }
198
+ }
199
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV1cm8tZXZvbHV0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGZqcy1ldm9sdXRpb24vc3JjL2xpYi9DbGFzc2VzL25ldXJvLWV2b2x1dGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUMsa0JBQWtCLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQTtBQUNoRSxPQUFPLEtBQUssRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBYXZDLE1BQU0sT0FBZ0IsY0FBYztJQUFwQztRQUVROzs7Ozs7O09BT0Q7UUFFSCxlQUFVLEdBQWUsRUFBRSxDQUFDO1FBQ3BCLHFCQUFnQixHQUFTLEVBQUUsQ0FBQztJQXdSeEMsQ0FBQztJQXRSRyx5QkFBeUI7SUFDekIsSUFBVyxlQUFlLENBQUMsZUFBdUI7UUFDOUMsSUFBSSxDQUFDLGdCQUFnQixHQUFDLGVBQWUsQ0FBQztJQUMxQyxDQUFDO0lBQ0QsSUFBVyxlQUFlO1FBQ3RCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDO0lBQ2pDLENBQUM7SUFFSDs7T0FFRztJQUVGLEtBQUssQ0FBQyxRQUFRO1FBQ1osT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFDLEVBQUU7WUFDMUMsSUFBSSxDQUFDLFFBQVEsR0FBRSxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDcEQsQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDO0lBRUMsZ0JBQWdCO1FBRVosS0FBSSxJQUFJLENBQUMsR0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFDLElBQUksQ0FBQyxlQUFlLEVBQUMsQ0FBQyxFQUFFLEVBQUM7WUFDcEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBQyxVQUFVLEVBQUUsSUFBSSxrQkFBa0IsRUFBRSxFQUFDLENBQUMsQ0FBQTtTQUMvRDtRQUNELDhEQUE4RDtRQUM5RCxn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LENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQTtRQUMxRCxDQUFDLENBQUMsQ0FBQTtJQUNOLENBQUM7Q0FFQSIsInNvdXJjZXNDb250ZW50IjpbIlxyXG5pbXBvcnQge1RlYWNoYWJsZU1vYmlsZU5ldH0gZnJvbSBcIi4uL21vZGVscy90ZWFjaGFibGUtZXZvbHV0aW9uXCJcclxuaW1wb3J0ICogYXMgdGYgZnJvbSAnQHRlbnNvcmZsb3cvdGZqcyc7XHJcblxyXG4vKipcclxuICogRWFjaCBpbmRpdmlkdWFsIG9mIHRoZSBwb3B1bGF0aW9uIHdpbGwgYmUgbWFkZSBvZiBcclxuICogYW4gYXJyYXksIGNvcnJlc3BvZGVudCB0byB0aGUgbmV1cmFsIG5ldHdvcmsgd2VpZ2h0cyBhbmRcclxuICogYW4gZXZhbHVhdGlvbiwgaXRzIHJlc3BlY3RpdmUgYWNjdXJhY3kgb24gdGhlIGRhdGFzZXQgZ2l2ZW4uXHJcbiAqIFxyXG4gKi9cclxuaW50ZXJmYWNlIEluZGl2aWR1YWwge1xyXG4gICAgaW5kaXZpZHVhbDogVGVhY2hhYmxlTW9iaWxlTmV0LFxyXG4gICAgYWNjdXJhY3k/OiBudW1iZXJcclxufVxyXG5cclxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIE5ldXJvRXZvbHV0aW9uIHtcclxuXHJcbiAgICAgICAgLyoqICAgICBcclxuICAgIFRoaXMgaXMgdGhlIHBvcHVsYXRpb24uIEkgaGF2ZSBkZWNpZGVkIHRvIGNyZWF0ZSBhIHBvcHVsYXRpb24gb2YganVzdCB3ZWlnaHRzLlxyXG4gICAgSSBoYWQgdG8gY2hhbmdlIG15IG1pbmQuIFdvcmtpbmcgd2l0aCB3ZWlnaHRzIGlzIHRyaWNreS4gXHJcbiAgICBJIGhhdmUgZGVjaWRlZCB0byBzYWNyaWZpY2UgbWVtb3J5IHRvIG1ha2UgbXkgbGlmZSBlYXNpc2VyLlxyXG4gICAgVGVuc29ycyBoYXMgdGhlaXIgaW5uZXIgbWV0aG9kcywgaXQgaGVscHMgb24gdGhlIG9wZXJhdG9ycy5cclxuICAgIEkgaGF2ZSB0byBwYXkgYXR0ZW50aW9uIHRvIG1lbW9yeSBtYW5lZ2VtZW50LlxyXG4gICAgV29ya2luZyB3aXRoIG1lbW9yeSBpbiB0ZW5zb3JzIGlzIHRyaWNreS4gICAgIFxyXG4gICAgICovXHJcblxyXG4gICAgcG9wdWxhdGlvbjogSW5kaXZpZHVhbFtdPVtdO1xyXG4gICAgcHJpdmF0ZSBfcG9wdWxhdGlvbl9zaXplOiBudW1iZXI9MzA7XHJcbiAgICBcclxuICAgIC8qKlNldHRlcnMgYW5kIEdldHRlcnMgKi9cclxuICAgIHB1YmxpYyBzZXQgcG9wdWxhdGlvbl9zaXplKHBvcHVsYXRpb25fc2l6ZTogbnVtYmVyKXtcclxuICAgICAgICB0aGlzLl9wb3B1bGF0aW9uX3NpemU9cG9wdWxhdGlvbl9zaXplO1xyXG4gICAgfVxyXG4gICAgcHVibGljIGdldCBwb3B1bGF0aW9uX3NpemUoKXtcclxuICAgICAgICByZXR1cm4gdGhpcy5fcG9wdWxhdGlvbl9zaXplO1xyXG4gICAgfVxyXG5cclxuICAvKipcclxuICAgKiBNZXRob2RzIHdpdGggaW1wbGVtZW50YXRpb25cclxuICAgKi9cclxuXHJcbiAgIGFzeW5jIGV2YWx1YXRlKCl7XHJcbiAgICAgcmV0dXJuIHRoaXMucG9wdWxhdGlvbi5mb3JFYWNoKGFzeW5jIChlbGVtKT0+e1xyXG4gICAgICAgIGVsZW0uYWNjdXJhY3k9IGF3YWl0IGVsZW0uaW5kaXZpZHVhbC5ldmFsdWF0ZSgpOyAgICAgICAgXHJcbiAgICB9KVxyXG4gIH1cclxuXHJcbiAgICBzdGFydF9wb3B1bGF0aW9uKCl7XHJcblxyXG4gICAgICAgIGZvcihsZXQgaT0wOyBpPHRoaXMucG9wdWxhdGlvbl9zaXplO2krKyl7ICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIHRoaXMucG9wdWxhdGlvbi5wdXNoKHtpbmRpdmlkdWFsOiBuZXcgVGVhY2hhYmxlTW9iaWxlTmV0KCl9KVxyXG4gICAgICAgIH1cclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlBvcHVsYXRpb24gbGVuZ3RoOiBcIiwgdGhpcy5wb3B1bGF0aW9uLmxlbmd0aCk7XHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJNZW1vcnkgYWZ0ZXIgcG9wdWxhdGlvbiBpbmlpYWxpemF0aW9uOiBcIiwgdGYubWVtb3J5KCkubnVtQnl0ZXMpO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGFwcGx5X2V2b2x1dGlvbihpdGVyYXRpb246IG51bWJlcil7XHJcblxyXG4gICAgICAgIGZvcihsZXQgaT0wO2k8aXRlcmF0aW9uO2krKyl7XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkludGVyYXRpb246IFwiLGkpXHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiTWVtb3J5OiBcIiwgdGYubWVtb3J5KCkubnVtQnl0ZXMpO1xyXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIlRlbnNvcnMgaW4gbWVtb3J5OiBcIiwgdGYubWVtb3J5KCkubnVtVGVuc29ycyk7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiUG9wdWxhdGlvbiBsZW5ndGg6IFwiLCB0aGlzLnBvcHVsYXRpb24ubGVuZ3RoKTtcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5ldm9sdXRpb24oKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgfVxyXG4gXHJcbiAgICAvKipcclxuICAgICAqIFRoaXMgbWV0aG9kIHdpbGwgYXBwbHkgdGhlIGV2b2x1dGlvblxyXG4gICAgICovXHJcbiAgICBhc3luYyBldm9sdXRpb24oKXtcclxuXHJcbiAgICAgICAgXHJcbiAgICAgICAgXHJcbiAgICAgICAgLy9VcGRhdGUgdGhlIGFjY3VyYWN5XHJcbiAgICAgICAgYXdhaXQgdGhpcy5ldmFsdWF0ZSgpO1xyXG5cclxuICAgICAgICBjb25zdCBvZmZzcHJpbmc9W107XHJcblxyXG4gICAgICAgIC8qKkZpcnN0IHN0ZXAgaXMgY3Jvc3NvdmVyLCBmb3IgY3JlYXRpbmcgb2Zmc3ByaW5nICovXHJcbiAgICAgICAgZm9yKGxldCBpPTA7IGk8dGhpcy5wb3B1bGF0aW9uLmxlbmd0aDtpKyspXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIC8vVGhlIHBvcHVsYXRpb24gd2lsbCBkb3VibGUgaW4gc2l6ZVxyXG4gICAgICAgICAgICAgICAgb2Zmc3ByaW5nLnB1c2godGhpcy5jcm9zc292ZXIoKSk7IFxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgLy9NdXRhdGlvbiBvbiB0aGUgb2Zmc3ByaW5nXHJcbiAgICAvLyAgICBjb25zb2xlLmxvZyhcIldlaWdodCBiZWZvcmUgbXV0YXRpb246IFwiLCBvZmZzcHJpbmdbMF0uaW5kaXZpZHVhbC5nZXRIZWFkKCkubGF5ZXJzWzBdLmdldFdlaWdodHMoKVswXS5kYXRhU3luYygpKTtcclxuXHJcbiAgICAgICB0aGlzLm11dGF0aW9uKG9mZnNwcmluZykgICBcclxuXHJcbiAgICAgICAgLy9Kb2luaW5nIHBhcmVudHMgYW5kIG9mZnNwcmluZyBpbnRvIHRoZSBzYW1lIHBvb2wgZm9yIHNlbGVjdGlvblxyXG4gICAgICAgIHRoaXMucG9wdWxhdGlvbj1bLi4udGhpcy5wb3B1bGF0aW9uLCAuLi5vZmZzcHJpbmddO1xyXG5cclxuICAgICAgICAvL1VwZGF0ZSB0aGUgYWNjdXJhY3lcclxuICAgICAgICAgYXdhaXQgdGhpcy5ldmFsdWF0ZSgpO1xyXG5cclxuXHJcbiAgICAgICAgIC8vc2VsZWN0aW9uXHJcbiAgICAgICAgIHRoaXMuc2VsZWN0aW9uKCk7XHJcbiAgICAgICAgY29uc29sZS5sb2coXCJCZXN0IGFjY3VyYWN5OiBcIiwgdGhpcy5nZXRUaGVCZXN0KCkuYWNjdXJhY3kpXHJcbiAgICAgICAgY29uc29sZS5sb2coXCJXb3JzdCBhY2N1cmFjeTogXCIsIHRoaXMuZ2V0VGhlV29yc3QoKS5hY2N1cmFjeSkgICAgICAgIFxyXG5cclxuICAgIH1cclxuXHJcbiAgICAvKipBYnN0cmFjdCBtZXRob2RzLlxyXG4gICAgICogU2hvdWxkIGJlIGltcGxlbWVudGVkIGJ5IGVhY2ggdmFyaWF0aW9uIG9mIGV2b2x1dGlvbmFyeSBhbGdvcml0aG1zXHJcbiAgICAgKi9cclxuXHJcbiAgICBhYnN0cmFjdCBjcm9zc292ZXIoKTogSW5kaXZpZHVhbDtcclxuICAgIGFic3RyYWN0IG11dGF0aW9uKG9mZnNwcmluZzogSW5kaXZpZHVhbFtdKTogdm9pZDtcclxuICAgIGFic3RyYWN0IHNlbGVjdGlvbigpOiB2b2lkO1xyXG5cclxuXHJcbiAgICAvKipIZWxwZXJzICovXHJcblxyXG4gICAgZ2V0VGhlQmVzdCgpOiBJbmRpdmlkdWFse1xyXG4gICAgICAgIGxldCBpbmRleF9iZXN0OiBudW1iZXI9MDtcclxuICAgICAgICBsZXQgYmVzdD0wO1xyXG5cclxuICAgICAgICB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaCgoZWxlbTogYW55LCBpbmRleDogbnVtYmVyKT0+e1xyXG5cclxuICAgICAgICAgICAgaWYoZWxlbS5hY2N1cmFjeT5iZXN0KXtcclxuICAgICAgICAgICAgICAgIGJlc3Q9ZWxlbS5hY2N1cmFjeTtcclxuICAgICAgICAgICAgICAgIGluZGV4X2Jlc3Q9aW5kZXhcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgfSlcclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXMucG9wdWxhdGlvbltpbmRleF9iZXN0XTtcclxuICAgIH1cclxuXHJcblxyXG4gICAgZ2V0VGhlV29yc3QoKTogSW5kaXZpZHVhbHtcclxuICAgICAgICBsZXQgaW5kZXhfd29yc3Q6IG51bWJlcj0wO1xyXG4gICAgICAgIGxldCB3b3JzdD0xO1xyXG5cclxuICAgICAgICB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaCgoZWxlbTogYW55LCBpbmRleDogbnVtYmVyKT0+e1xyXG5cclxuICAgICAgICAgICAgaWYoZWxlbS5hY2N1cmFjeTx3b3JzdCl7XHJcbiAgICAgICAgICAgICAgICB3b3JzdD1lbGVtLmFjY3VyYWN5O1xyXG4gICAgICAgICAgICAgICAgaW5kZXhfd29yc3Q9aW5kZXhcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgfSlcclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXMucG9wdWxhdGlvbltpbmRleF93b3JzdF07XHJcbiAgICB9XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICogU2VsZWN0aW5nIGluZGl2aWR1YWxzIGJ5IGVsaXRpc21cclxuICAgICAqL1xyXG4gICAgc2VsZWN0X3BhcmVudHNfYnlfcm9sbGV0X3doZWVsc192MihzZWxlY3Rpb25fbnVtYmVyPTIpOiBJbmRpdmlkdWFsW117XHJcblxyXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlNlbGVjdGluZyBwYXJlbnRzIGJ5IHJvbGxldCB3aGVlbHMuLi5cIik7XHJcbiAgICBcclxuICAgICAgICAgICAgY29uc3Qgc2hhcmU6IGFueT1bXTtcclxuICAgIFxyXG4gICAgICAgICAgICBsZXQgdG90YWw6IGFueT0wO1xyXG4gICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlBvcHVsYXRpb24gbGVuZ3RoLi4uXCIsIHRoaXMucG9wdWxhdGlvbi5sZW5ndGgpO1xyXG4gICAgXHJcbiAgICAgICAgICAgIC8vVGhpcyB3aWxsIGNyZWF0ZSBhbiBvdmVyYWxsIGFjY3VyYWN5XHJcbiAgICAgICAgICAgIHRoaXMucG9wdWxhdGlvbi5mb3JFYWNoKChlbGVtKT0+dG90YWwrPWVsZW0uYWNjdXJhY3kpO1xyXG4gICAgXHJcbiAgICAgICAgICAgIGxldCBwb2ludGVyPTA7XHJcbiAgICBcclxuICAgICAgICAgICAgdGhpcy5wb3B1bGF0aW9uLmZvckVhY2goKGVsZW06YW55LCBpbmRleCk9PntcclxuICAgIFxyXG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJBY2N1cmFjeS4uLlwiLCBlbGVtLmFjY3VyYWN5KTtcclxuICAgIFxyXG4gICAgICAgICAgICAgICAgc2hhcmUucHVzaChcclxuICAgICAgICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgICAgICBpbmRleDogaW5kZXgsXHJcbiAgICAgICAgICAgICAgICAgICAgICBzaGFyZTogIGVsZW0uYWNjdXJhY3kvdG90YWwsXHJcbiAgICAgICAgICAgICAgICAgICAgICBtaW46IHBvaW50ZXIsXHJcbiAgICAgICAgICAgICAgICAgICAgICBtYXg6IHBvaW50ZXIgKyAoZWxlbS5hY2N1cmFjeS90b3RhbClcclxuICAgICAgICAgICAgICAgICAgfSlcclxuICAgIFxyXG4gICAgICAgICAgICAgICAgICBwb2ludGVyKz1lbGVtLmFjY3VyYWN5L3RvdGFsO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgIFxyXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlNoYXJlczogXCIsIHNoYXJlKTtcclxuICAgIFxyXG4gICAgICAgICAgICBjb25zdCBhdXhfc2VsZWN0aW9uOiBhbnkgPVtdO1xyXG4gICAgXHJcbiAgICAgICAgICAgICAgLy9TZWxlY3RpbmcgdHdvIGluZGl2aWR1YWxzIHVzaW5nIHJvdWxldHRlIHdoZWVsc1xyXG4gICAgICAgICAgICBsZXQgY291bnRlcj0wO1xyXG5cclxuICAgICAgICAgICAgY29uc3QgaW5kZXhlc19hdXg6IG51bWJlcltdPVtdO1xyXG5cclxuICAgICAgICAgICAgd2hpbGUoY291bnRlcjxzZWxlY3Rpb25fbnVtYmVyKXtcclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgLy9SYW5kb20gcG9pbnRlciwgdXNlZCB0byByYW5kb21seSBzZWxlY3QgYW4gaW5kaXZpZHVhbFxyXG4gICAgICAgICAgICAgICAgY29uc3QgYXV4X2luZGV4PSBNYXRoLnJhbmRvbSgpO1xyXG4gICAgXHJcbiAgICAgICAgICAgICAgICBzaGFyZS5mb3JFYWNoKChlbGVtOiBhbnkpPT57XHJcbiAgICBcclxuICAgICAgICAgICAgICAgICAgICBpZigoZWxlbS5taW48YXV4X2luZGV4KSYmKGVsZW0ubWF4PmF1eF9pbmRleCkpe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXV4OiBJbmRpdmlkdWFsID0ge2luZGl2aWR1YWw6IG5ldyBUZWFjaGFibGVNb2JpbGVOZXQoKSwgYWNjdXJhY3k6IHRoaXMucG9wdWxhdGlvbltlbGVtLmluZGV4XS5hY2N1cmFjeSB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkluZGl2aWR1YWwganVzdCBjcmVhdGVkICh3ZWlndGgpOiBcIiwgYXV4LmluZGl2aWR1YWwuZ2V0SGVhZCgpLmxheWVyc1swXS5nZXRXZWlnaHRzKClbMF0uZGF0YVN5bmMoKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkluZGl2aWR1YWwgb3JpZ2luYWw6IFwiLCB0aGlzLnBvcHVsYXRpb25bZWxlbS5pbmRleF0uaW5kaXZpZHVhbC5nZXRIZWFkKCkubGF5ZXJzWzBdLmdldFdlaWdodHMoKVswXS5kYXRhU3luYygpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgICAgICAgICAgICAvLyBPcmlnaW5hbCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSZWNpcGllbnRcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhpcy5jb3B5TW9kZWwodGhpcy5wb3B1bGF0aW9uW2VsZW0uaW5kZXhdLmluZGl2aWR1YWwuZ2V0SGVhZCgpLGF1eC5pbmRpdmlkdWFsLmdldEhlYWQoKSlcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoaXMucG9wdWxhdGlvbltlbGVtLmluZGV4XS5pbmRpdmlkdWFsLmdldEhlYWQoKS5kaXNwb3NlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkluZGl2aWR1YWwganVzdCBjcmVhdGVkICh3ZWlndGh0LCBjb3BpZWQpOiBcIiwgYXV4LmluZGl2aWR1YWwuZ2V0SGVhZCgpLmxheWVyc1swXS5nZXRXZWlnaHRzKClbMF0uZGF0YVN5bmMoKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudGVyKys7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGF1eF9zZWxlY3Rpb24ucHVzaCh0aGlzLnBvcHVsYXRpb25bZWxlbS5pbmRleF0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5kZXhlc19hdXgucHVzaChlbGVtLmluZGV4KVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIHRoaXMucG9wdWxhdGlvbi5mb3JFYWNoKChlbGVtLCBpbmRleCk9PntcclxuICAgICAgICAgICAgLy8gICAgIGlmKCFpbmRleGVzX2F1eC5pbmNsdWRlcyhpbmRleCkpe1xyXG4gICAgICAgICAgICAvLyAgICAgICAgIGNvbnNvbGUubG9nKFwiRGlzcG9zZWQuLi5cIilcclxuICAgICAgICAgICAgLy8gICAgICAgICBlbGVtLmluZGl2aWR1YWwuZ2V0SGVhZCgpLmRpc3Bvc2UoKTtcclxuICAgICAgICAgICAgLy8gICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gfSlcclxuXHJcbiAgICAgICAgICAgIC8vIHRoaXMucG9wdWxhdGlvbj1bXTtcclxuXHJcbiAgICAgICAgICAgIHJldHVybiBhdXhfc2VsZWN0aW9uO1xyXG4gICAgICAgIH1cclxuICAgIFxyXG4gICAgLyoqXHJcbiAgICAgKiBTZWxlY3RpbmcgaW5kaXZpZHVhbHMgYnkgZWxpdGlzbVxyXG4gICAgICovXHJcbiAgICBzZWxlY3RfcGFyZW50c19ieV9yb2xsZXRfd2hlZWxzKHNlbGVjdGlvbl9udW1iZXI9Mik6IEluZGl2aWR1YWxbXXtcclxuXHJcbiAgICAgICAgLy8gY29uc29sZS5sb2dcclxuICAgICAgICAvLyAoXCJTZWxlY3RpbmcgcGFyZW50cyBieSByb2xsZXQgd2hlZWxzLi4uXCIpO1xyXG5cclxuICAgICAgICBjb25zdCBzaGFyZTogYW55PVtdO1xyXG5cclxuICAgICAgICBsZXQgdG90YWw6IGFueT0wO1xyXG4gICAgICAgICAgXHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJQb3B1bGF0aW9uIGxlbmd0aC4uLlwiLCB0aGlzLnBvcHVsYXRpb24ubGVuZ3RoKTtcclxuXHJcbiAgICAgICAgLy9UaGlzIHdpbGwgY3JlYXRlIGFuIG92ZXJhbGwgYWNjdXJhY3lcclxuICAgICAgICB0aGlzLnBvcHVsYXRpb24uZm9yRWFjaCgoZWxlbSk9PnRvdGFsKz1lbGVtLmFjY3VyYWN5KTtcclxuXHJcbiAgICAgICAgbGV0IHBvaW50ZXI9MDtcclxuXHJcbiAgICAgICAgdGhpcy5wb3B1bGF0aW9uLmZvckVhY2goKGVsZW06YW55LCBpbmRleCk9PntcclxuXHJcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiQWNjdXJhY3kuLi5cIiwgZWxlbS5hY2N1cmFjeSk7XHJcblxyXG4gICAgICAgICAgICBzaGFyZS5wdXNoKFxyXG4gICAgICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgICBpbmRleDogaW5kZXgsXHJcbiAgICAgICAgICAgICAgICAgIHNoYXJlOiAgZWxlbS5hY2N1cmFjeS90b3RhbCxcclxuICAgICAgICAgICAgICAgICAgbWluOiBwb2ludGVyLFxyXG4gICAgICAgICAgICAgICAgICBtYXg6IHBvaW50ZXIgKyAoZWxlbS5hY2N1cmFjeS90b3RhbClcclxuICAgICAgICAgICAgICB9KVxyXG5cclxuICAgICAgICAgICAgICBwb2ludGVyKz1lbGVtLmFjY3VyYWN5L3RvdGFsO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlNoYXJlczogXCIsIHNoYXJlKTtcclxuXHJcbiAgICAgICAgY29uc3QgYXV4X3NlbGVjdGlvbjogYW55ID1bXTtcclxuXHJcbiAgICAgICAgICAvL1NlbGVjdGluZyB0d28gaW5kaXZpZHVhbHMgdXNpbmcgcm91bGV0dGUgd2hlZWxzXHJcbiAgICAgICAgbGV0IGNvdW50ZXI9MDtcclxuICAgICAgICB3aGlsZShjb3VudGVyPHNlbGVjdGlvbl9udW1iZXIpe1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy9SYW5kb20gcG9pbnRlciwgdXNlZCB0byByYW5kb21seSBzZWxlY3QgYW4gaW5kaXZpZHVhbFxyXG4gICAgICAgICAgICBjb25zdCBhdXhfaW5kZXg9IE1hdGgucmFuZG9tKCk7XHJcblxyXG4gICAgICAgICAgICBzaGFyZS5mb3JFYWNoKChlbGVtOiBhbnkpPT57XHJcblxyXG4gICAgICAgICAgICAgICAgaWYoKGVsZW0ubWluPGF1eF9pbmRleCkmJihlbGVtLm1heD5hdXhfaW5kZXgpKXtcclxuICAgICAgICAgICAgICAgICAgICBjb3VudGVyKys7XHJcbiAgICAgICAgICAgICAgICAgICAgYXV4X3NlbGVjdGlvbi5wdXNoKHRoaXMucG9wdWxhdGlvbltlbGVtLmluZGV4XSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBhdXhfc2VsZWN0aW9uO1xyXG4gICAgfVxyXG5cclxuLyoqXHJcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBtYWtlIGEgY29weSBvZiBhIG1vZGVsIG9uIHRoZSB3ZWlnaHQgbGV2ZWxcclxuICogVGhpcyBpcyBhbiBhdHRlbXB0IHRvIGF2b2lkIGluZmx1ZW5jaW5nIHRoZSBuZXcgbW9kZWwgd2hlbiB0aGUgb2xkIG9uZVxyXG4gKiBpcyBlbGltaW5hdGVkLiBcclxuICogXHJcbiAqIEBwYXJhbSBvcmlnaW5hbE1vZGVsIC0gdGhlIG1vZGVsIHRvIGJlIGNvcGllZCBcclxuICogQHBhcmFtIHJlY2lwaWVudCAtIHRoZSBuZXcgbW9kZWxcclxuICovXHJcbmFzeW5jIGNvcHlNb2RlbCAob3JpZ2luYWxNb2RlbDogdGYuTGF5ZXJzTW9kZWwsIHJlY2lwaWVudDogdGYuTGF5ZXJzTW9kZWwpICB7XHJcblxyXG4gICAgb3JpZ2luYWxNb2RlbC5sYXllcnMuZm9yRWFjaCgobGF5ZXI6IGFueSwgaW5kZXg6IGFueSk9PntcclxuICAgICAgICByZWNpcGllbnQubGF5ZXJzW2luZGV4XS5zZXRXZWlnaHRzKGxheWVyLmdldFdlaWdodHMoKSlcclxuICAgIH0pXHJcbn0gICAgXHJcblxyXG59XHJcbiJdfQ==
@@ -5,4 +5,5 @@ export * from './lib/tfjs-evolution.service';
5
5
  export * from './lib/tfjs-evolution.component';
6
6
  export * from './lib/components/display-panel/display-panel.component';
7
7
  export * from './lib/models/teachable-evolution';
8
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL3RmanMtZXZvbHV0aW9uL3NyYy9wdWJsaWMtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyw4QkFBOEIsQ0FBQztBQUM3QyxjQUFjLGdDQUFnQyxDQUFDO0FBRS9DLGNBQWMsd0RBQXdELENBQUM7QUFFdkUsY0FBYyxrQ0FBa0MsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXHJcbiAqIFB1YmxpYyBBUEkgU3VyZmFjZSBvZiB0ZmpzLWV2b2x1dGlvblxyXG4gKi9cclxuXHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL3RmanMtZXZvbHV0aW9uLnNlcnZpY2UnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi90ZmpzLWV2b2x1dGlvbi5jb21wb25lbnQnO1xyXG5cclxuZXhwb3J0ICogZnJvbSAnLi9saWIvY29tcG9uZW50cy9kaXNwbGF5LXBhbmVsL2Rpc3BsYXktcGFuZWwuY29tcG9uZW50JztcclxuXHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGVscy90ZWFjaGFibGUtZXZvbHV0aW9uJztcclxuIl19
8
+ export * from './lib/Classes/genetic-algorithm';
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL3RmanMtZXZvbHV0aW9uL3NyYy9wdWJsaWMtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyw4QkFBOEIsQ0FBQztBQUM3QyxjQUFjLGdDQUFnQyxDQUFDO0FBRS9DLGNBQWMsd0RBQXdELENBQUM7QUFFdkUsY0FBYyxrQ0FBa0MsQ0FBQztBQUVqRCxjQUFjLGlDQUFpQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcclxuICogUHVibGljIEFQSSBTdXJmYWNlIG9mIHRmanMtZXZvbHV0aW9uXHJcbiAqL1xyXG5cclxuZXhwb3J0ICogZnJvbSAnLi9saWIvdGZqcy1ldm9sdXRpb24uc2VydmljZSc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL3RmanMtZXZvbHV0aW9uLmNvbXBvbmVudCc7XHJcblxyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9jb21wb25lbnRzL2Rpc3BsYXktcGFuZWwvZGlzcGxheS1wYW5lbC5jb21wb25lbnQnO1xyXG5cclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWxzL3RlYWNoYWJsZS1ldm9sdXRpb24nO1xyXG5cclxuZXhwb3J0ICogZnJvbSAnLi9saWIvQ2xhc3Nlcy9nZW5ldGljLWFsZ29yaXRobSc7XHJcbiJdfQ==
@@ -880,6 +880,262 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImpor
880
880
  args: [{ selector: 'neuroevolution-display-panel', standalone: true, imports: [CommonModule], template: "<div *ngFor=\"let class of classes; index as i\">\r\n <h1>{{class.name}}</h1>\r\n <img *ngFor=\"let item of class.images; index as i\" [src]=\"item\" width=\"224\" height=\"224\" [id]=\"'class-' + class.name + '-' + i\" crossorigin=\"anonymous\" >\r\n</div>\r\n" }]
881
881
  }] });
882
882
 
883
+ class NeuroEvolution {
884
+ constructor() {
885
+ /**
886
+ This is the population. I have decided to create a population of just weights.
887
+ I had to change my mind. Working with weights is tricky.
888
+ I have decided to sacrifice memory to make my life easiser.
889
+ Tensors has their inner methods, it helps on the operators.
890
+ I have to pay attention to memory manegement.
891
+ Working with memory in tensors is tricky.
892
+ */
893
+ this.population = [];
894
+ this._population_size = 30;
895
+ }
896
+ /**Setters and Getters */
897
+ set population_size(population_size) {
898
+ this._population_size = population_size;
899
+ }
900
+ get population_size() {
901
+ return this._population_size;
902
+ }
903
+ /**
904
+ * Methods with implementation
905
+ */
906
+ async evaluate() {
907
+ return this.population.forEach(async (elem) => {
908
+ elem.accuracy = await elem.individual.evaluate();
909
+ });
910
+ }
911
+ start_population() {
912
+ for (let i = 0; i < this.population_size; i++) {
913
+ this.population.push({ individual: new TeachableMobileNet() });
914
+ }
915
+ // console.log("Population length: ", this.population.length);
916
+ // console.log("Memory after population iniialization: ", tf.memory().numBytes);
917
+ }
918
+ async apply_evolution(iteration) {
919
+ for (let i = 0; i < iteration; i++) {
920
+ console.log("Interation: ", i);
921
+ console.log("Memory: ", tf.memory().numBytes);
922
+ console.log("Tensors in memory: ", tf.memory().numTensors);
923
+ console.log("Population length: ", this.population.length);
924
+ await this.evolution();
925
+ }
926
+ }
927
+ /**
928
+ * This method will apply the evolution
929
+ */
930
+ async evolution() {
931
+ //Update the accuracy
932
+ await this.evaluate();
933
+ const offspring = [];
934
+ /**First step is crossover, for creating offspring */
935
+ for (let i = 0; i < this.population.length; i++) {
936
+ //The population will double in size
937
+ offspring.push(this.crossover());
938
+ }
939
+ //Mutation on the offspring
940
+ // console.log("Weight before mutation: ", offspring[0].individual.getHead().layers[0].getWeights()[0].dataSync());
941
+ this.mutation(offspring);
942
+ //Joining parents and offspring into the same pool for selection
943
+ this.population = [...this.population, ...offspring];
944
+ //Update the accuracy
945
+ await this.evaluate();
946
+ //selection
947
+ this.selection();
948
+ console.log("Best accuracy: ", this.getTheBest().accuracy);
949
+ console.log("Worst accuracy: ", this.getTheWorst().accuracy);
950
+ }
951
+ /**Helpers */
952
+ getTheBest() {
953
+ let index_best = 0;
954
+ let best = 0;
955
+ this.population.forEach((elem, index) => {
956
+ if (elem.accuracy > best) {
957
+ best = elem.accuracy;
958
+ index_best = index;
959
+ }
960
+ });
961
+ return this.population[index_best];
962
+ }
963
+ getTheWorst() {
964
+ let index_worst = 0;
965
+ let worst = 1;
966
+ this.population.forEach((elem, index) => {
967
+ if (elem.accuracy < worst) {
968
+ worst = elem.accuracy;
969
+ index_worst = index;
970
+ }
971
+ });
972
+ return this.population[index_worst];
973
+ }
974
+ /**
975
+ * Selecting individuals by elitism
976
+ */
977
+ select_parents_by_rollet_wheels_v2(selection_number = 2) {
978
+ // console.log("Selecting parents by rollet wheels...");
979
+ const share = [];
980
+ let total = 0;
981
+ // console.log("Population length...", this.population.length);
982
+ //This will create an overall accuracy
983
+ this.population.forEach((elem) => total += elem.accuracy);
984
+ let pointer = 0;
985
+ this.population.forEach((elem, index) => {
986
+ // console.log("Accuracy...", elem.accuracy);
987
+ share.push({
988
+ index: index,
989
+ share: elem.accuracy / total,
990
+ min: pointer,
991
+ max: pointer + (elem.accuracy / total)
992
+ });
993
+ pointer += elem.accuracy / total;
994
+ });
995
+ // console.log("Shares: ", share);
996
+ const aux_selection = [];
997
+ //Selecting two individuals using roulette wheels
998
+ let counter = 0;
999
+ const indexes_aux = [];
1000
+ while (counter < selection_number) {
1001
+ //Random pointer, used to randomly select an individual
1002
+ const aux_index = Math.random();
1003
+ share.forEach((elem) => {
1004
+ if ((elem.min < aux_index) && (elem.max > aux_index)) {
1005
+ const aux = { individual: new TeachableMobileNet(), accuracy: this.population[elem.index].accuracy };
1006
+ // console.log("Individual just created (weigth): ", aux.individual.getHead().layers[0].getWeights()[0].dataSync());
1007
+ // console.log("Individual original: ", this.population[elem.index].individual.getHead().layers[0].getWeights()[0].dataSync());
1008
+ // // Original Recipient
1009
+ // this.copyModel(this.population[elem.index].individual.getHead(),aux.individual.getHead())
1010
+ // this.population[elem.index].individual.getHead().dispose();
1011
+ // console.log("Individual just created (weigtht, copied): ", aux.individual.getHead().layers[0].getWeights()[0].dataSync());
1012
+ counter++;
1013
+ aux_selection.push(this.population[elem.index]);
1014
+ // indexes_aux.push(elem.index)
1015
+ }
1016
+ });
1017
+ }
1018
+ // this.population.forEach((elem, index)=>{
1019
+ // if(!indexes_aux.includes(index)){
1020
+ // console.log("Disposed...")
1021
+ // elem.individual.getHead().dispose();
1022
+ // }
1023
+ // })
1024
+ // this.population=[];
1025
+ return aux_selection;
1026
+ }
1027
+ /**
1028
+ * Selecting individuals by elitism
1029
+ */
1030
+ select_parents_by_rollet_wheels(selection_number = 2) {
1031
+ // console.log
1032
+ // ("Selecting parents by rollet wheels...");
1033
+ const share = [];
1034
+ let total = 0;
1035
+ // console.log("Population length...", this.population.length);
1036
+ //This will create an overall accuracy
1037
+ this.population.forEach((elem) => total += elem.accuracy);
1038
+ let pointer = 0;
1039
+ this.population.forEach((elem, index) => {
1040
+ // console.log("Accuracy...", elem.accuracy);
1041
+ share.push({
1042
+ index: index,
1043
+ share: elem.accuracy / total,
1044
+ min: pointer,
1045
+ max: pointer + (elem.accuracy / total)
1046
+ });
1047
+ pointer += elem.accuracy / total;
1048
+ });
1049
+ // console.log("Shares: ", share);
1050
+ const aux_selection = [];
1051
+ //Selecting two individuals using roulette wheels
1052
+ let counter = 0;
1053
+ while (counter < selection_number) {
1054
+ //Random pointer, used to randomly select an individual
1055
+ const aux_index = Math.random();
1056
+ share.forEach((elem) => {
1057
+ if ((elem.min < aux_index) && (elem.max > aux_index)) {
1058
+ counter++;
1059
+ aux_selection.push(this.population[elem.index]);
1060
+ }
1061
+ });
1062
+ }
1063
+ return aux_selection;
1064
+ }
1065
+ /**
1066
+ * This function will make a copy of a model on the weight level
1067
+ * This is an attempt to avoid influencing the new model when the old one
1068
+ * is eliminated.
1069
+ *
1070
+ * @param originalModel - the model to be copied
1071
+ * @param recipient - the new model
1072
+ */
1073
+ async copyModel(originalModel, recipient) {
1074
+ originalModel.layers.forEach((layer, index) => {
1075
+ recipient.layers[index].setWeights(layer.getWeights());
1076
+ });
1077
+ }
1078
+ }
1079
+
1080
+ class GeneticAlgorithm extends NeuroEvolution {
1081
+ /**
1082
+ * Implementatin abstract methods
1083
+ */
1084
+ crossover() {
1085
+ // console.log("Applying crossover on Genetic Algorithms...")
1086
+ const selected = this.select_parents_by_rollet_wheels();
1087
+ const individual_1 = selected[0];
1088
+ const individual_2 = selected[1];
1089
+ // console.log("Individual 1: ")
1090
+ // individual_1.individual.getHead().summary();
1091
+ let individual_3 = { individual: new TeachableMobileNet };
1092
+ const alfa = Math.random();
1093
+ individual_3.individual.getHead().layers.forEach((layer, index) => {
1094
+ individual_3.individual.getHead().layers[index].setWeights(individual_1.individual.getHead().layers[index].getWeights()
1095
+ .map((elem, index_2) => elem.mul(alfa)
1096
+ .add(individual_2.individual.getHead().layers[index]
1097
+ .getWeights()[index_2]
1098
+ .mul(1 - alfa))));
1099
+ });
1100
+ // this.population.push(individual_3);
1101
+ // console.log("Population: ", this.population.length);
1102
+ return individual_3;
1103
+ } //end of crossover
1104
+ mutation(offspring) {
1105
+ const multation_rate = 1;
1106
+ offspring.forEach((elem) => {
1107
+ elem.individual.getHead().setWeights(elem.individual.getHead().getWeights().map((elem_2) => {
1108
+ return elem_2.add(elem_2.mul(multation_rate * Math.random()));
1109
+ }));
1110
+ });
1111
+ }
1112
+ selection() {
1113
+ const selected_individuals = this.select_parents_by_rollet_wheels(this.population_size);
1114
+ // const selected_individuals_copy: any=[];
1115
+ // selected_individuals.forEach(async (elem)=>{
1116
+ // const aux: Individual= {individual: new TeachableMobileNet()};
1117
+ // // await this.copyModel(elem.individual.getHead(), aux.individual.getHead());
1118
+ // // aux.individual.getHead().summary();
1119
+ // selected_individuals_copy.push({individual: aux, accuracy: elem.accuracy});
1120
+ // });
1121
+ // console.log("Memory before cleaning: ", tf.memory().numBytes);
1122
+ //Cleaning memory
1123
+ // this.population.forEach((elem)=> elem.individual.getHead().dispose())
1124
+ // this.population=[];
1125
+ //The best will enter on the population by elitism
1126
+ const best = this.getTheBest();
1127
+ this.population = [];
1128
+ this.population = selected_individuals;
1129
+ //Adding one extra individual by elitism
1130
+ // this.population.push(best);
1131
+ console.log("Best accuracy (elitism): ", best.accuracy);
1132
+ // console.log("Current population length: ", this.population.length);
1133
+ // console.log("Current population: ", this.population);
1134
+ // console.log("After selection: ", this.population[0])
1135
+ // console.log("Memory before cleaning: ", tf.memory().numBytes);
1136
+ }
1137
+ }
1138
+
883
1139
  /*
884
1140
  * Public API Surface of tfjs-evolution
885
1141
  */
@@ -888,5 +1144,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImpor
888
1144
  * Generated bundle index. Do not edit.
889
1145
  */
890
1146
 
891
- export { DisplayPanelComponent, TeachableMobileNet, TfjsEvolutionComponent, TfjsEvolutionService };
1147
+ export { DisplayPanelComponent, GeneticAlgorithm, TeachableMobileNet, TfjsEvolutionComponent, TfjsEvolutionService };
892
1148
  //# sourceMappingURL=tfjs-evolution.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"tfjs-evolution.mjs","sources":["../../../projects/tfjs-evolution/src/lib/tfjs-evolution.service.ts","../../../projects/tfjs-evolution/src/lib/tfjs-evolution.component.ts","../../../projects/tfjs-evolution/src/lib/models/custom-mobilenet.ts","../../../projects/tfjs-evolution/src/lib/utils/tf.ts","../../../projects/tfjs-evolution/src/lib/utils/util.ts","../../../projects/tfjs-evolution/src/lib/models/teachable-evolution.ts","../../../projects/tfjs-evolution/src/lib/components/display-panel/display-panel.component.ts","../../../projects/tfjs-evolution/src/lib/components/display-panel/display-panel.component.html","../../../projects/tfjs-evolution/src/public-api.ts","../../../projects/tfjs-evolution/src/tfjs-evolution.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class TfjsEvolutionService {\r\n\r\n constructor() { }\r\n}\r\n","import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'neuroevolution-tfjs-evolution',\r\n standalone: true,\r\n imports: [],\r\n template: `\r\n <p>\r\n tfjs-evolution works!\r\n </p>\r\n `,\r\n styles: ``\r\n})\r\nexport class TfjsEvolutionComponent {\r\n\r\n}\r\n","\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\nimport { SymbolicTensor } from '@tensorflow/tfjs';\r\n\r\n\r\nexport const IMAGE_SIZE = 224;\r\n\r\n\r\n/**\r\n * the metadata to describe the model's creation,\r\n * includes the labels associated with the classes\r\n * and versioning information from training.\r\n */\r\nexport interface Metadata {\r\n tfjsVersion: string;\r\n tmVersion?: string;\r\n packageVersion: string;\r\n packageName: string;\r\n modelName?: string;\r\n timeStamp?: string;\r\n labels: string[];\r\n userMetadata?: {};\r\n grayscale?: boolean;\r\n imageSize?: number;\r\n}\r\n\r\nexport interface ModelOptions {\r\n version?: number;\r\n checkpointUrl?: string;\r\n alpha?: number;\r\n trainingLayer?: string;\r\n}\r\n\r\nconst DEFAULT_MOBILENET_VERSION = 2;\r\nconst DEFAULT_TRAINING_LAYER_V1 = 'conv_pw_13_relu';\r\nconst DEFAULT_TRAINING_LAYER_V2 = \"out_relu\"; \r\nconst DEFAULT_ALPHA_V1_v2 = 0.35;\r\nconst DEFAULT_ALPHA_V1 = 0.25;//256\r\nconst DEFAULT_ALPHA_V2 = 0.5; //512\r\nconst DEFAULT_ALPHA_V3 = 0.75;//768 features\r\nconst DEFAULT_ALPHA_V4 = 1;//1024 features\r\nconst DEFAULT_ALPHA = 1;//1024 features\r\n\r\n// v2: 0.35, 0.50, 0.75 or 1.00.\r\n\r\nconst isAlphaValid = (version: number, alpha: number) => {\r\n if (version === 1) {\r\n if (alpha !== 0.25 && alpha !== 0.5 && alpha !== 0.75 && alpha !== 1) {\r\n console.warn(\"Invalid alpha. Options are: 0.25, 0.50, 0.75 or 1.00.\");\r\n console.log(\"Loading model with alpha: \", DEFAULT_ALPHA_V1.toFixed(2)); \r\n return DEFAULT_ALPHA_V1;\r\n }\r\n }\r\n else {\r\n if (alpha !== 0.35 && alpha !== 0.5 && alpha !== 0.75 && alpha !== 1) {\r\n console.warn(\"Invalid alpha. Options are: 0.35, 0.50, 0.75 or 1.00.\");\r\n console.log(\"Loading model with alpha: \", DEFAULT_ALPHA_V2.toFixed(2)); \r\n return DEFAULT_ALPHA_V2;\r\n }\r\n }\r\n\r\n return alpha;\r\n};\r\n\r\n\r\nconst parseModelOptions = (options?: ModelOptions) => {\r\n options = options || {}\r\n\r\n if (options.checkpointUrl && options.trainingLayer) {\r\n if (options.alpha || options.version){\r\n console.warn(\"Checkpoint URL passed to modelOptions, alpha options are ignored\");\r\n } \r\n return [options.checkpointUrl, options.trainingLayer];\r\n } else {\r\n options.version = options.version || DEFAULT_MOBILENET_VERSION;\r\n \r\n if(options.version === 1){\r\n options.alpha = options.alpha || DEFAULT_ALPHA_V4; \r\n options.alpha = isAlphaValid(options.version, options.alpha);\r\n\r\n console.log(`Loading mobilenet ${options.version} and alpha ${options.alpha}`);\r\n // exception is alpha o f 1 can only be 1.0\r\n let alphaString = options.alpha.toFixed(2);\r\n if (alphaString === \"1.00\") { alphaString = \"1.0\"; }\r\n\r\n console.log(\"Using the model: \", )\r\n\r\n return [\r\n // tslint:disable-next-line:max-line-length\r\n //They are loading MobileNet_v1 \r\n `https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_${alphaString}_${IMAGE_SIZE}/model.json`,\r\n DEFAULT_TRAINING_LAYER_V1\r\n ];\r\n }\r\n else if (options.version === 2){\r\n options.alpha = options.alpha || DEFAULT_ALPHA_V4; \r\n options.alpha = isAlphaValid(options.version, options.alpha);\r\n\r\n console.log(`Loading mobilenet ${options.version} and alpha ${options.alpha}`);\r\n console.log(`Loading mobilenet ${options.version} and alpha ${options.alpha}`);\r\n\r\n return [\r\n // tslint:disable-next-line:max-line-length \r\n `https://storage.googleapis.com/teachable-machine-models/mobilenet_v2_weights_tf_dim_ordering_tf_kernels_${options.alpha.toFixed(2)}_${IMAGE_SIZE}_no_top/model.json`,\r\n DEFAULT_TRAINING_LAYER_V2\r\n ];\r\n } else {\r\n throw new Error(`MobileNet V${options.version} doesn't exist`);\r\n } \r\n }\r\n};\r\n\r\n\r\n/**\r\n * load the base mobilenet model\r\n * @param modelOptions options determining what model to load\r\n */\r\nexport async function loadTruncatedMobileNet(modelOptions?: ModelOptions) {\r\n const [checkpointUrl, trainingLayer] = parseModelOptions(modelOptions);\r\n \r\n \r\n const mobilenet = await tf.loadLayersModel(checkpointUrl);\r\n\r\n if (modelOptions && modelOptions.version === 1){\r\n const layer = mobilenet.getLayer(trainingLayer);\r\n \r\n const truncatedModel = tf.model({ inputs: mobilenet.inputs, outputs: layer.output });\r\n console.log(\"Feature model loaded, memory: \", tf.memory().numBytes);\r\n\r\n \r\n const model = tf.sequential();\r\n model.add(truncatedModel);\r\n model.add(tf.layers.flatten()); \r\n \r\n \r\n return model;\r\n }\r\n else {\r\n const layer = mobilenet.getLayer(trainingLayer);\r\n const truncatedModel = tf.model({ inputs: mobilenet.inputs, outputs: layer.output });\r\n console.log(\"Feature model loaded, memory: \", tf.memory().numBytes);\r\n const model = tf.sequential();\r\n model.add(truncatedModel);\r\n model.add(tf.layers.globalAveragePooling2d({})); // go from shape [7, 7, 1280] to [1280]\r\n return model;\r\n }\r\n}\r\n\r\n\r\nexport class CustomMobileNet {\r\n /**\r\n * the truncated mobilenet model we will train on top of\r\n */\r\n protected truncatedModel!: tf.LayersModel;\r\n static truncatedModel: tf.Sequential;\r\n\r\nstatic getinputShape(){\r\n /**truncatedModel is the base model, the model used to apply transfer learning */\r\n const inputShape: any = this.truncatedModel.outputs[0].shape.slice(1); // [ 7 x 7 x 1280] (not sure about those dimensions)\r\n// console.log(\"Input Shape(complete): \", this.truncatedModel.outputs[0].shape);\r\n// console.log(\"Input Shape: \", inputShape);\r\n\r\n const inputSize = tf.util.sizeFromShape(inputShape);\r\n\r\n// console.log(\"Input Size: \", inputSize);\r\n\r\n return inputSize;\r\n}\r\n\r\n static get EXPECTED_IMAGE_SIZE() {\r\n return IMAGE_SIZE;\r\n }\r\n\r\n protected _metadata!: Metadata;\r\n\r\n public getMetadata() {\r\n return this._metadata;\r\n }\r\n\r\n constructor() {\r\n // this._metadata = fillMetadata(metadata);\r\n //Loading the truncated model\r\n // loadTruncatedMobileNet();\r\n // this.loadFeatureModel();\r\n\r\n }\r\n\r\n static async loadFeatureModel(){\r\n\r\n this.truncatedModel = await loadTruncatedMobileNet();\r\n\r\n }\r\n\r\n /**\r\n * get the total number of classes existing within model\r\n */\r\n // getTotalClasses() {\r\n // const output = this.model.output as SymbolicTensor;\r\n // const totalClasses = output.shape[1];\r\n // return totalClasses;\r\n // }\r\n\r\n /**\r\n * get the model labels\r\n */\r\n getClassLabels() {\r\n return this._metadata.labels;\r\n }\r\n\r\n /**\r\n * Given an image element, makes a prediction through mobilenet returning the\r\n * probabilities of the top K classes.\r\n * @param image the image to classify\r\n * @param maxPredictions the maximum number of classification predictions\r\n */\r\n // async predictTopK(image: ClassifierInputSource, maxPredictions = 10, flipped = false) {\r\n // const croppedImage = cropTo(image, this._metadata.imageSize, flipped);\r\n\r\n // const logits = tf.tidy(() => {\r\n // const captured = capture(croppedImage, this._metadata.grayscale);\r\n // return this.model.predict(captured);\r\n // });\r\n\r\n // // Convert logits to probabilities and class names.\r\n // const classes = await getTopKClasses(this._metadata.labels, logits as tf.Tensor<tf.Rank>, maxPredictions);\r\n // dispose(logits);\r\n\r\n // return classes;\r\n // }\r\n\r\n /**\r\n * Given an image element, makes a prediction through mobilenet returning the\r\n * probabilities for ALL classes.\r\n * @param image the image to classify\r\n * @param flipped whether to flip the image on X\r\n */\r\n // async predict(image: ClassifierInputSource, flipped = false) {\r\n // const croppedImage = cropTo(image, this._metadata.imageSize, flipped);\r\n\r\n // const logits = tf.tidy(() => {\r\n // const captured = capture(croppedImage, this._metadata.grayscale);\r\n // return this.model.predict(captured);\r\n // });\r\n\r\n // const values = await (logits as tf.Tensor<tf.Rank>).data();\r\n\r\n // const classes = [];\r\n // for (let i = 0; i < values.length; i++) {\r\n // classes.push({\r\n // className: this._metadata.labels[i],\r\n // probability: values[i]\r\n // });\r\n // }\r\n\r\n // dispose(logits);\r\n\r\n // return classes;\r\n // }\r\n\r\n public dispose() {\r\n this.truncatedModel.dispose();\r\n }\r\n}// end of CustomMobileNet\r\n","import * as tf from '@tensorflow/tfjs';\r\n\r\n/**\r\n * Receives an image and normalizes it between -1 and 1.\r\n * Returns a batched image (1 - element batch) of shape [1, w, h, c]\r\n * @param rasterElement the element with pixels to convert to a Tensor\r\n * @param grayscale optinal flag that changes the crop to [1, w, h, 1]\r\n */\r\nexport function capture(rasterElement: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement, grayscale?: boolean) {\r\n return tf.tidy(() => {\r\n // console.log(\"Not a tensor....\")\r\n const pixels = tf.browser.fromPixels(rasterElement);\r\n\r\n // crop the image so we're using the center square\r\n const cropped = cropTensor(pixels);\r\n\r\n // Expand the outer most dimension so we have a batch size of 1\r\n const batchedImage = cropped.expandDims(0);\r\n\r\n // Normalize the image between -1 and a1. The image comes in between 0-255\r\n // so we divide by 127 and subtract 1.\r\n return batchedImage.toFloat().div(tf.scalar(127)).sub(tf.scalar(1));\r\n });\r\n}\r\n\r\n\r\n\r\nexport function cropTensor( img: tf.Tensor3D ) : tf.Tensor3D {\r\n \r\n const size = Math.min(img.shape[0], img.shape[1]);\r\n const centerHeight = img.shape[0] / 2;\r\n const beginHeight = centerHeight - (size / 2);\r\n const centerWidth = img.shape[1] / 2;\r\n const beginWidth = centerWidth - (size / 2);\r\n \r\n\r\n return img.slice([beginHeight, beginWidth, 0], [size, size, 3]);\r\n}","\r\nimport {Class} from \"./class\"\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\n\r\nexport class Util {\r\n\r\n/**\r\n * Receives an image and normalizes it between -1 and 1.\r\n * Returns a batched image (1 - element batch) of shape [1, w, h, c]\r\n * @param rasterElement the element with pixels to convert to a Tensor\r\n * @param grayscale optinal flag that changes the crop to [1, w, h, 1]\r\n */\r\ncapture(rasterElement: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement, grayscale?: boolean) {\r\n return tf.tidy(() => {\r\n const pixels = tf.browser.fromPixels(rasterElement);\r\n\r\n // // crop the image so we're using the center square\r\n const cropped = this.cropTensor(pixels, grayscale);\r\n\r\n // // Expand the outer most dimension so we have a batch size of 1\r\n const batchedImage = cropped.expandDims(0);\r\n\r\n // // Normalize the image between -1 and a1. The image comes in between 0-255\r\n // // so we divide by 127 and subtract 1.\r\n return batchedImage.toFloat().div(tf.scalar(127)).sub(tf.scalar(1)); \r\n });\r\n} \r\n\r\n\r\ncropTensor( img: tf.Tensor3D, grayscaleModel?: boolean, grayscaleInput?: boolean ) : tf.Tensor3D {\r\n const size = Math.min(img.shape[0], img.shape[1]);\r\n const centerHeight = img.shape[0] / 2;\r\n const beginHeight = centerHeight - (size / 2);\r\n const centerWidth = img.shape[1] / 2;\r\n const beginWidth = centerWidth - (size / 2);\r\n \r\n if (grayscaleModel && !grayscaleInput) {\r\n //cropped rgb data\r\n let grayscale_cropped = img.slice([beginHeight, beginWidth, 0], [size, size, 3]);\r\n \r\n grayscale_cropped = grayscale_cropped.reshape([size * size, 1, 3])\r\n const rgb_weights = [0.2989, 0.5870, 0.1140]\r\n grayscale_cropped = tf.mul(grayscale_cropped, rgb_weights)\r\n grayscale_cropped = grayscale_cropped.reshape([size, size, 3]);\r\n \r\n grayscale_cropped = tf.sum(grayscale_cropped, -1)\r\n grayscale_cropped = tf.expandDims(grayscale_cropped, -1)\r\n\r\n return grayscale_cropped;\r\n }\r\n return img.slice([beginHeight, beginWidth, 0], [size, size, 3]);\r\n}\r\n\r\n\r\n\r\n\r\n/**\r\n * This function will make a copy of a model on the weight level\r\n * This is an attempt to avoid influencing the new mode when the old one\r\n * is eliminated. \r\n * \r\n * @param originalModel - the model to be copied \r\n * @param recipient - the new model\r\n */\r\nasync copyModel_v3 (originalModel: tf.Sequential, recipient: tf.Sequential) {\r\n\r\n originalModel.layers.forEach((layer, index)=>{\r\n recipient.layers[index].setWeights(layer.getWeights())\r\n })\r\n\r\n // originalModel.dispose();\r\n}\r\n \r\n/**\r\n * This function will make a copy of a TFJS model, as so it would be possible \r\n * to erase the original.\r\n * @param model - model to be copied\r\n * @returns - copy of the model\r\n */ \r\nasync copyModel_v2 (originalModel: tf.Sequential) {\r\n // Serialize the original model\r\n const modelTopology = originalModel.toJSON();\r\n\r\n // Load the serialized model into a new model\r\n const copiedModel = await tf.loadLayersModel(\r\n tf.io.fromMemory(modelTopology, undefined, undefined)\r\n );\r\n \r\n // Compile the copied model with the same settings as the original\r\n copiedModel.compile({\r\n loss: originalModel.loss,\r\n optimizer: originalModel.optimizer\r\n });\r\n \r\n return copiedModel;\r\n}\r\n\r\n/**\r\n * This function will make a copy of a TFJS model, as so it would be possible \r\n * to erase the original.\r\n * @param model - model to be copied\r\n * @returns - copy of the model\r\n */ \r\ncopyModel (model: tf.Sequential) {\r\n \r\n const copy = tf.sequential();`\r\n `\r\n model.layers.forEach(layer => {\r\n const aux =layer;\r\n // layer.dispose();\r\n copy.add(aux);\r\n });\r\n copy.compile({\r\n loss: model.loss,\r\n optimizer: model.optimizer\r\n });\r\n return copy;\r\n }\r\n\r\n\r\n removeElementByIndex(arr: any, index: number): number[] {\r\n // Check if the index is within bounds\r\n if (index >= 0 && index < arr.length) {\r\n // Remove the element at the specified index\r\n arr.splice(index, 1); \r\n }\r\n return arr;\r\n }\r\n\r\n removeElement(arr: any, element: any): number[] {\r\n // Remove all occurrences of the specified element from the array\r\n return arr.filter((item: any) => item !== element);\r\n }\r\n\r\nclean_array_of_tensors(tensors: tf.Sequential[]) {\r\n\r\n tensors.forEach((elem, index)=>{ \r\n // if(!index_selection.includes(index)) \r\n elem.dispose() \r\n });\r\n\r\n}\r\n\r\n getClassNameBySignature(classes: Class[], signature: number[]) { \r\n \r\n const class_name = classes.find(p => {\r\n let match = true;\r\n p.signature?.forEach ((elem,index)=>{ \r\n if(elem!==signature[index])\r\n match=false; \r\n })\r\n\r\n return match;\r\n });\r\n\r\n return class_name ? class_name.name : \"not found\";\r\n}\r\n\r\nidentityMatrix(n: number): number[][] {\r\n return Array.from({ length: n }, (_, i) => Array.from({ length: n }, (_, j) => (i === j ? 1 : 0)));\r\n} \r\n\r\n\r\nindexOfMax(arr: number[]): number {\r\n if (arr.length === 0) {\r\n return -1; // Return -1 for an empty array\r\n }\r\n \r\n let max = arr[0];\r\n let maxIndex = 0;\r\n \r\n for (let i = 1; i < arr.length; i++) {\r\n if (arr[i] > max) {\r\n maxIndex = i;\r\n max = arr[i];\r\n }\r\n }\r\n \r\n return maxIndex;\r\n }\r\n\r\n\r\nsuffle(array1:any, array2: any){\r\n // Shuffle the order of elements\r\n for (let i = array1.length - 1; i > 0; i--) {\r\n const j = Math.floor(Math.random() * (i + 1));\r\n\r\n // Swap elements in both arrays\r\n [array1[i], array1[j]] = [array1[j], array1[i]];\r\n [array2[i], array2[j]] = [array2[j], array2[i]];\r\n }\r\n \r\n \r\n }\r\n\r\n sortByValuePreservingIndex<T>(\r\n arr1: number[],\r\n arr2: any[]\r\n ): T[] {\r\n\r\n // console.log(\"Vector for organizing: \", arr1)\r\n // arr2[0].summary()\r\n\r\n // Create an array of objects with value, index from arr1, and original index\r\n const pairingArray = arr1.map((value, index) => ({\r\n value,\r\n index,\r\n originalIndex: index,\r\n elementFromArr2: arr2[index], // Preserve the corresponding element from arr2\r\n }));\r\n \r\n // Sort the pairing array by value (largest to smallest)\r\n pairingArray.sort((a, b) => b.value - a.value);\r\n\r\n \r\n \r\n // Extract the sorted elements from arr2 based on the original index\r\n const sortedElementsFromArr2 = pairingArray.map(pair => pair.elementFromArr2);\r\n \r\n return sortedElementsFromArr2;\r\n } \r\n \r\n}\r\n\r\n","import { CustomMobileNet, loadTruncatedMobileNet } from \"./custom-mobilenet\";\r\n\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\nimport { capture } from '../utils/tf';\r\nimport { Class } from '../utils/class';\r\nimport { Util } from \"../utils/util\";\r\n\r\nimport * as seedrandom from 'seedrandom';\r\n\r\nimport * as tfvis from '@tensorflow/tfjs-vis';\r\n\r\nimport { TensorContainer } from '@tensorflow/tfjs-core/dist/tensor_types';\r\n\r\nconst VALIDATION_FRACTION = 0.15;\r\n\r\n\r\n\r\n/**\r\n * the metadata to describe the model's creation,\r\n * includes the labels associated with the classes\r\n * and versioning information from training.\r\n */\r\nexport interface Metadata {\r\n tfjsVersion: string;\r\n tmVersion?: string;\r\n packageVersion: string;\r\n packageName: string;\r\n modelName?: string;\r\n timeStamp?: string;\r\n labels: string[];\r\n userMetadata?: {};\r\n grayscale?: boolean;\r\n imageSize?: number;\r\n}\r\n\r\n/**\r\n * Receives a Metadata object and fills in the optional fields such as timeStamp\r\n * @param data a Metadata object\r\n */\r\nconst fillMetadata = (data: Partial<Metadata>) => {\r\n // util.assert(typeof data.tfjsVersion === 'string', () => `metadata.tfjsVersion is invalid`);\r\n // data.packageVersion = data.packageVersion || version;\r\n data.packageName = data.packageName || '@teachablemachine/image';\r\n data.timeStamp = data.timeStamp || new Date().toISOString();\r\n data.userMetadata = data.userMetadata || {};\r\n data.modelName = data.modelName || 'untitled';\r\n data.labels = data.labels || [];\r\n // data.imageSize = data.imageSize || IMAGE_SIZE;\r\n return data as Metadata;\r\n};\r\n\r\nexport class TeachableMobileNet extends CustomMobileNet {\r\n\r\n // Array of all the examples collected.\r\n /**\r\n It is static since all the instance will share the same features, for saving memory and time.\r\n The idea is avoiding restoring the features individually and having the recalculate them for every new\r\n individuals.\r\n */\r\n public static examples: Float32Array[][] = [];\r\n\r\n // Number of total samples\r\n private static totalSamples = 0;\r\n\r\n classes: Class[]=[];\r\n\r\n static classes_names: string[]=[];\r\n\r\n static numClasses: number;\r\n\r\n /**\r\n * the training model for transfer learning\r\n */\r\n protected trainingModel!: tf.LayersModel;\r\n trainDataset: any;\r\n validationDataset: any;\r\n static trainDataset: any;\r\n static validationDataset: any;\r\n static numValidation: number;\r\n\r\n constructor(){\r\n super();\r\n this.createHead();\r\n }\r\n\r\n /**\r\n * This method will return the head, the trainable part, the part under evolution.\r\n */\r\n getHead(){\r\n return this.trainingModel;\r\n }\r\n\r\n /**\r\n * Create the head for transfer learning.\r\n * This is the trainable section of the transfer learning.\r\n */\r\n createHead(){\r\n\r\n const inputSize= TeachableMobileNet.getinputShape();\r\n\r\n this.trainingModel = tf.sequential({\r\n layers: [\r\n tf.layers.dense({\r\n inputShape: [inputSize],\r\n units:100,\r\n activation: 'relu', \r\n useBias: true\r\n }),\r\n tf.layers.dense({ \r\n useBias: false,\r\n activation: 'softmax',\r\n units: TeachableMobileNet.classes_names.length\r\n })\r\n ]\r\n });\r\n\r\n const optimizer = tf.train.adam();\r\n // const optimizer = tf.train.rmsprop(params.learningRate);\r\n\r\n this.trainingModel.compile({\r\n optimizer,\r\n // loss: 'binaryCrossentropy',\r\n loss: 'categoricalCrossentropy',\r\n metrics: ['accuracy']\r\n });\r\n }\r\n \r\n async train(){\r\n\r\n const trainingSurface = { name: 'Loss and MSE', tab: 'Training' };\r\n\r\n const dataset= TeachableMobileNet.convertToTfDataset();\r\n\r\n //Salving a copy of the validation dataset, for later\r\n TeachableMobileNet.validationDataset= dataset.validationDataset;\r\n\r\n // console.log(\"Dataset for training: \", dataset.trainDataset);\r\n\r\n const trainData = dataset.trainDataset.batch(30);\r\n const validationData = dataset.validationDataset.batch(10);\r\n\r\n // this.createHead();\r\n\r\n const callbacks= [\r\n // Show on a tfjs-vis visor the loss and accuracy values at the end of each epoch.\r\n tfvis.show.fitCallbacks(trainingSurface, ['loss', 'acc', \"val_loss\", \"val_acc\"],\r\n {\r\n callbacks: ['onEpochEnd'],\r\n }\r\n ),\r\n {},]\r\n\r\n const history: any = await this.trainingModel.fitDataset(trainData, {\r\n epochs: 100,\r\n validationData,\r\n callbacks\r\n}).then((info:any)=>{\r\n console.log('Precisão final', info.history.val_acc[info.history.acc.length-1]);\r\n});\r\n\r\n\r\n// await this.accuracy_per_class();\r\n\r\n\r\n// console.log(\"History: \", history.history.acc);\r\n // await this.trainingModel.fit(this.featureX, this.target, {})\r\n }\r\n\r\nasync accuracy_per_class(confusion_matrix_recipient: any){\r\n /**Calculating Accuracy per class */\r\nconst accuracyperclass: any = await this.calculateAccuracyPerClass(TeachableMobileNet.validationDataset);\r\n// console.log(\"Accuracy per class: \", accuracyperclass);\r\n\r\n//Confusion matrix\r\n// Calling tf.confusionMatrix() method \r\nconst output = tf.math.confusionMatrix( accuracyperclass.reference, accuracyperclass.predictions, TeachableMobileNet.classes_names.length); \r\n \r\n// Printing output \r\noutput.print()\r\nconst confusion_matrix= output.dataSync();\r\n\r\n// console.log(confusion_matrix);\r\n// console.log(confusion_matrix[TeachableMobileNet.classes_names.length + TeachableMobileNet.classes_names.length]);\r\n\r\nconst accuracy = [];\r\n\r\nfor(let i=0; i<TeachableMobileNet.classes_names.length;i++){\r\n\r\n accuracy.push(confusion_matrix[TeachableMobileNet.classes_names.length*i+ i]/TeachableMobileNet.numValidation)\r\n}\r\n\r\nconsole.log(\"Accuracy per class: \", accuracy);\r\n\r\nfor(let i=0; i<TeachableMobileNet.classes_names.length;i++){\r\n\r\n confusion_matrix_recipient.push([]);\r\n\r\n for(let j=0; j<TeachableMobileNet.classes_names.length;j++){\r\n confusion_matrix_recipient[i].push([]);\r\n\r\n confusion_matrix_recipient[i][j]= confusion_matrix[TeachableMobileNet.classes_names.length*i+ j]/TeachableMobileNet.numValidation\r\n confusion_matrix_recipient[i][j]=(confusion_matrix_recipient[i][j].toFixed(2))*100;\r\n }\r\n\r\n // accuracy.push(confusion_matrix[TeachableMobileNet.classes_names.length*i+ i]/TeachableMobileNet.numValidation)\r\n}\r\n\r\nconsole.log(\"Confusion matrix as a matrix\")\r\nconsole.log(confusion_matrix_recipient);\r\n\r\nreturn accuracy.map((elem: any)=>elem.toFixed(2)*100);\r\n}\r\n\r\n \r\n async loadImages(number_of_species: number, classes_names: string[], options: object){\r\n TeachableMobileNet.classes_names=classes_names;\r\n \r\n await this.add_species(number_of_species, options); \r\n\r\n}\r\n\r\nasync add_species(number_of_species: number, options: object){\r\n \r\n //Loading feature model, used to create features from images\r\n // await this.loadFeatureModel();\r\n\r\n for (let i = 0; i < TeachableMobileNet.classes_names.length; i++) {\r\n // this.add_images(this.classes_names[i], number_of_species, options);\r\n }\r\n}\r\n\r\n/**\r\n * \r\n * @param name - name of the class receiving an example\r\n * @param number_of_species - how many images to add\r\n * @param options - details on the location of the images\r\n */\r\nasync add_images(name: string, number_of_species: number, options: any){ \r\n\r\n const class_add: any= [];\r\n\r\n for (let i = 0; i < number_of_species; i++) { \r\n // class_add.push(`${options.base}/${name}/${options.file_name} ${i}.${options.file_extension}`);\r\n \r\n //Uploading images\r\n const cake = new Image(); \r\n // cake.src = `${options.base}/${name}/${options.file_name} ${i}.${options.file_extension}`;\r\n cake.height=224;\r\n cake.width=224;\r\n cake.src=\"./assets/dataset/Can%C3%A1rio-da-Terra/image%200.jpeg\"\r\n // console.log(\"Image location: \", cake.src )\r\n\r\n await new Promise<void>((resolve, reject) => {\r\n cake.onload = () => {\r\n\r\n //Finding the correspondent index of the class with name given\r\n const index= TeachableMobileNet.classes_names.findIndex((elem)=>elem===name)\r\n\r\n // this.addExample(index, cake);\r\n\r\n resolve();\r\n };\r\n \r\n cake.onerror = (error) => {\r\n // Handle error if the image fails to load\r\n reject(error);\r\n };\r\n });\r\n }\r\n\r\n // this.classes.push({name: name, images: class_add}) \r\n\r\n }\r\n\r\n\r\n\r\n \r\n/**\r\n * This method will transform images into tensors\r\n * @param number_of_classes - number of classes\r\n * @param classes_names - name of each class\r\n */\r\nasync createTensors(number_of_classes: number, classes_names: string[]) {\r\n\r\n let output: any = [];\r\n\r\n /** There is a function on TensorFlow.js that also does that */\r\n const signatures= new Util().identityMatrix(number_of_classes);\r\n\r\n for (let i = 0; i < number_of_classes; i++) {\r\n\r\n this.classes[i].signature=signatures[i];\r\n this.classes[i].name=classes_names[i];\r\n\r\n for (let j = 0; j < this.classes[i].images.length; j++) {\r\n\r\n\r\n }\r\n\r\n }\r\n}\r\n\r\n /**\r\n * Add a sample of data under the provided className\r\n * @param className the classification this example belongs to\r\n * @param sample the image / tensor that belongs in this classification\r\n */\r\n // public async addExample(className: number, sample: HTMLCanvasElement | tf.Tensor) {\r\npublic static async addExample(className: number, name: string, sample: HTMLImageElement | HTMLCanvasElement | tf.Tensor) {\r\n\r\n // console.log(\"Adding a new example...\") \r\n \r\n const cap = isTensor(sample) ? sample : capture(sample);\r\n \r\n \r\n //Getting the features\r\n const example = this.truncatedModel.predict(cap) as tf.Tensor;\r\n // console.log(\"Shape after feature extraction: \", example.shape) \r\n \r\n\r\n const activation = example.dataSync() as Float32Array;\r\n \r\n //Very important to clean the memory aftermath, it makes the difference\r\n cap.dispose();\r\n example.dispose();\r\n \r\n // //Accessing the instance variable, not the local ones\r\n // // save samples of each class separately \r\n \r\n if(!TeachableMobileNet.examples[className])\r\n //and an empty array, make sure there is not empty elements. \r\n //it will create issue when transforming to tensors\r\n TeachableMobileNet.examples[className]=[]\r\n\r\n\r\n if(!TeachableMobileNet.classes_names[className])\r\n //Saving the lable when it first appears\r\n TeachableMobileNet.classes_names[className]=name;\r\n\r\n TeachableMobileNet.examples[className].push(activation);\r\n \r\n // // increase our sample counter\r\n TeachableMobileNet.totalSamples++;\r\n }\r\n\r\n\r\n /**\r\n * process the current examples provided to calculate labels and format\r\n * into proper tf.data.Dataset\r\n */\r\n static prepare() {\r\n for (const classes in TeachableMobileNet.examples){\r\n if (classes.length === 0) {\r\n throw new Error('Add some examples before training');\r\n }\r\n }\r\n\r\n const datasets: any = this.convertToTfDataset();\r\n\r\n this.trainDataset = datasets.trainDataset;\r\n this.validationDataset = datasets.validationDataset;\r\n}\r\n\r\npublic prepareDataset() {\r\n for (let i = 0; i < TeachableMobileNet.numClasses; i++) {\r\n //Different from the original implementation of TM, mine is using example as static.\r\n //The goal is saving memory by using a single instance of the variable\r\n TeachableMobileNet.examples[i] = [];\r\n }\r\n}\r\n\r\n \r\n // Optional seed to make shuffling of data predictable\r\n static seed: seedrandom.prng;\r\n\r\n\r\n\r\n \r\n/**\r\n * Process the examples by first shuffling randomly per class, then adding\r\n * one-hot labels, then splitting into training/validation datsets, and finally\r\n * sorting one last time\r\n */\r\n \r\nstatic convertToTfDataset() {\r\n\r\n // first shuffle each class individually\r\n // TODO: we could basically replicate this by insterting randomly\r\n for (let i = 0; i < TeachableMobileNet.examples.length; i++) {\r\n TeachableMobileNet.examples[i] = fisherYates(TeachableMobileNet.examples[i], this.seed) as Float32Array[];\r\n }\r\n\r\n // then break into validation and test datasets\r\n let trainDataset: Sample[] = [];\r\n let validationDataset: Sample[] = [];\r\n\r\n // for each class, add samples to train and validation dataset\r\n for (let i = 0; i < TeachableMobileNet.examples.length; i++) {\r\n \r\n // console.log(\"Number of classes: \", TeachableMobileNet.classes_names.length);\r\n\r\n const y = flatOneHot(i, TeachableMobileNet.classes_names.length);\r\n\r\n const classLength = TeachableMobileNet.examples[i].length;\r\n\r\n // console.log(\"Number of elements per class: \", classLength);\r\n\r\n const numValidation = Math.ceil(VALIDATION_FRACTION * classLength);\r\n const numTrain = classLength - numValidation;\r\n\r\n this.numValidation=numValidation;\r\n \r\n /**It is visiting per class, thus, it is possible to fix y, the target label */\r\n \r\n const classTrain = this.examples[i].slice(0, numTrain).map((dataArray) => {\r\n return { data: dataArray, label: y };\r\n });\r\n\r\n const classValidation = this.examples[i].slice(numTrain).map((dataArray) => {\r\n return { data: dataArray, label: y };\r\n });\r\n\r\n trainDataset = trainDataset.concat(classTrain);\r\n validationDataset = validationDataset.concat(classValidation); \r\n\r\n\r\n }\r\n\r\n // console.log(\"Training element: \", trainDataset[trainDataset.length-1]) \r\n // console.log(\"Training length: \", trainDataset.length)\r\n // console.log(\"validation length: \", validationDataset.length);\r\n\r\n \r\n // finally shuffle both train and validation datasets\r\n trainDataset = fisherYates(trainDataset, this.seed) as Sample[];\r\n validationDataset = fisherYates(validationDataset, this.seed) as Sample[];\r\n\r\n const trainX = tf.data.array(trainDataset.map(sample => sample.data));\r\n const validationX = tf.data.array(validationDataset.map(sample => sample.data));\r\n const trainY = tf.data.array(trainDataset.map(sample => sample.label));\r\n const validationY = tf.data.array(validationDataset.map(sample => sample.label));\r\n\r\n // return tf.data dataset objects\r\n return {\r\n trainDataset: tf.data.zip({ xs: trainX, ys: trainY}),\r\n validationDataset: tf.data.zip({ xs: validationX, ys: validationY})\r\n };\r\n\r\n\r\n}\r\n\r\ndatasetForEvaluation(){\r\n\r\n}\r\n\r\n/**Metrics */\r\n\r\nstatic feature_aux: any;\r\nstatic target_aux: any;\r\n\r\nasync evaluate(){\r\n \r\n if(!TeachableMobileNet.feature_aux){\r\n const features: any=[];\r\n const targets: any=[];\r\n\r\n for (let i = 0; i < TeachableMobileNet.examples.length; i++) {\r\n\r\n const y = flatOneHot(i, TeachableMobileNet.classes_names.length);\r\n \r\n\r\n\r\n //For class i, push all the examples.\r\n TeachableMobileNet.examples[i].forEach((elemn)=>{\r\n\r\n //Pushing the target signature\r\n targets.push(y);\r\n \r\n //Pushing features\r\n features.push(elemn)\r\n })\r\n\r\n } \r\n\r\n TeachableMobileNet.feature_aux= tf.tensor(features);\r\n TeachableMobileNet.target_aux= tf.tensor(targets);\r\n\r\n } \r\n\r\n const aux: any = this.trainingModel.evaluate(TeachableMobileNet.feature_aux, TeachableMobileNet.target_aux);\r\n \r\n return aux[1].dataSync()[0];\r\n\r\n\r\n}\r\n\r\n\r\n// async evaluate(){\r\n\r\n// const features: any=[];\r\n// const targets: any=[];\r\n\r\n// for (let i = 0; i < TeachableMobileNet.examples.length; i++) {\r\n\r\n// const y = flatOneHot(i, TeachableMobileNet.classes_names.length);\r\n \r\n\r\n\r\n// //For class i, push all the examples.\r\n// TeachableMobileNet.examples[i].forEach((elemn)=>{\r\n\r\n// //Pushing the target signature\r\n// targets.push(y);\r\n \r\n// //Pushing features\r\n// features.push(elemn)\r\n// })\r\n\r\n// } \r\n\r\n// const aux_features= tf.tensor(features);\r\n// const aux_target= tf.tensor(targets);\r\n\r\n \r\n// // console.log(\"Tensor stack for evaluation: \", aux_features.shape)\r\n\r\n// const aux: any = this.trainingModel.evaluate(aux_features, aux_target);\r\n\r\n\r\n// return aux[1].dataSync()[0];\r\n\r\n\r\n// }\r\n\r\n\r\n/*** Final statistics */\r\n/* \r\n * Calculate each class accuracy using the validation dataset\r\n*/\r\npublic async calculateAccuracyPerClass(validationData: any) {\r\n\r\n const validationXs = TeachableMobileNet.validationDataset.mapAsync(async (dataset: TensorContainer) => {\r\n return (dataset as { xs: TensorContainer, ys: TensorContainer}).xs;\r\n});\r\n\r\nconst validationYs = TeachableMobileNet.validationDataset.mapAsync(async (dataset: TensorContainer) => {\r\n return (dataset as { xs: TensorContainer, ys: TensorContainer}).ys;\r\n});\r\n\r\n// console.log(\"validation dataset: \", validationXs);\r\n \r\n// console.log(\"For calculating batch size: \", validationYs);\r\n\r\n// we need to split our validation data into batches in case it is too large to fit in memory\r\nconst batchSize = Math.min(validationYs.size, 32);\r\n// const batchSize =1;\r\n\r\nconst iterations = Math.ceil(validationYs.size / batchSize);\r\n\r\n// console.log(\"Batch size: \", batchSize);\r\n\r\nconst batchesX = validationXs.batch(batchSize);\r\n\r\nconst batchesY = validationYs.batch(batchSize);\r\nconst itX = await batchesX.iterator();\r\nconst itY = await batchesY.iterator();\r\nconst allX = [];\r\nconst allY = [];\r\n\r\nfor (let i = 0; i < iterations; i++) {\r\n\r\n // 1. get the prediction values in batches\r\n const batchedXTensor = await itX.next(); \r\n\r\n // console.log(\"Batch size on accuracy per class: \", batchedXTensor.value.shape);\r\n\r\n const batchedXPredictionTensor = this.trainingModel.predict(batchedXTensor.value) as tf.Tensor;\r\n\r\n const argMaxX = batchedXPredictionTensor.argMax(1); // Returns the indices of the max values along an axis\r\n\r\n allX.push(argMaxX);\r\n\r\n // 2. get the ground truth label values in batches\r\n const batchedYTensor = await itY.next();\r\n const argMaxY = batchedYTensor.value.argMax(1); // Returns the indices of the max values along an axis\r\n\r\n allY.push(argMaxY);\r\n \r\n // 3. dispose of all our tensors\r\n batchedXTensor.value.dispose();\r\n batchedXPredictionTensor.dispose();\r\n batchedYTensor.value.dispose();\r\n}\r\n\r\n // concatenate all the results of the batches\r\n const reference = tf.concat(allY); // this is the ground truth\r\n const predictions = tf.concat(allX); // this is the prediction our model is guessing\r\n \r\n // console.log(\"this is the ground truth: \", reference.dataSync())\r\n // console.log(\"This is the prediction our model is guessing: \", predictions.dataSync())\r\n\r\n // only if we concatenated more than one tensor for preference and reference\r\n if (iterations !== 1) {\r\n for (let i = 0; i < allX.length; i++) {\r\n allX[i].dispose();\r\n allY[i].dispose();\r\n }\r\n }\r\n\r\n // console.log(\"Lengtth: \", await reference.dataSync().length) \r\n \r\n // const accuracyperclass=[];\r\n\r\n // const reference_aux= await reference.dataSync();\r\n // const prediction_aux= await predictions.dataSync();\r\n // console.log( predictions.dataSync());\r\n\r\n // reference_aux.forEach((element, index) => {\r\n // if()\r\n \r\n // }); \r\n\r\n\r\n return { reference, predictions }; \r\n\r\n}\r\n\r\n}//end of class\r\n\r\n\r\n\r\n\r\n\r\n/***Support methods (helpers) */\r\n\r\nconst isTensor = (c: any): c is tf.Tensor =>\r\n typeof c.dataId === 'object' && typeof c.shape === 'object';\r\n/**\r\n * Converts an integer into its one-hot representation and returns\r\n * the data as a JS Array.\r\n */\r\nfunction flatOneHot(label: number, numClasses: number) {\r\n\r\n const labelOneHot = new Array(numClasses).fill(0) as number[];\r\n labelOneHot[label] = 1;\r\n\r\n return labelOneHot;\r\n}\r\n\r\ninterface Sample {\r\n data: Float32Array;\r\n label: number[];\r\n}\r\n\r\n\r\n/**\r\n * Shuffle an array of Float32Array or Samples using Fisher-Yates algorithm\r\n * Takes an optional seed value to make shuffling predictable\r\n */\r\nfunction fisherYates(array: Float32Array[] | Sample[], seed?: seedrandom.prng) {\r\n const length = array.length;\r\n\r\n // need to clone array or we'd be editing original as we goo\r\n const shuffled = array.slice();\r\n\r\n for (let i = (length - 1); i > 0; i -= 1) {\r\n let randomIndex ;\r\n if (seed) {\r\n randomIndex = Math.floor(seed() * (i + 1));\r\n }\r\n else {\r\n randomIndex = Math.floor(Math.random() * (i + 1));\r\n }\r\n\r\n [shuffled[i], shuffled[randomIndex]] = [shuffled[randomIndex],shuffled[i]];\r\n }\r\n\r\n return shuffled;\r\n}\r\n","import { Component} from '@angular/core';\r\nimport { Group } from '../../interfaces/group';\r\nimport { CommonModule } from '@angular/common';\r\nimport { TeachableMobileNet } from '../../models/teachable-evolution';\r\n\r\n@Component({\r\n selector: 'neuroevolution-display-panel',\r\n standalone: true,\r\n imports: [CommonModule],\r\n templateUrl: './display-panel.component.html',\r\n styleUrl: './display-panel.component.css'\r\n})\r\nexport class DisplayPanelComponent {\r\n\r\n classes: Group[]=[];\r\n\r\n classes_names!: string[];\r\n\r\n number_of_samples_per_class!: number;\r\n\r\nloadImages(number_of_species: number, classes_names: string[], options: object){\r\n \r\n this.classes_names=classes_names;\r\n this.number_of_samples_per_class=number_of_species;\r\n\r\n this.add_species(number_of_species, options); \r\n\r\n }\r\n\r\n\r\nadd_species(number_of_species: number, options: object){\r\n\r\n for (let i = 0; i < this.classes_names.length; i++) {\r\n this.add_images(this.classes_names[i], number_of_species, options);\r\n \r\n }\r\n\r\n }\r\n\r\n add_images(name: string, number_of_species: number, options: any){ \r\n\r\n const class_add: any= [];\r\n\r\n for (let i = 0; i < number_of_species; i++) { \r\n class_add.push(`${options.base}/${name}/${options.file_name} ${i+1}.${options.file_extension}`);\r\n }\r\n\r\n this.classes.push({name: name, images: class_add}) \r\n\r\n }\r\n\r\n async addexamples(){\r\n\r\n //This is needed to make sure it gives time for the images to upload\r\n //The images upload very fast, what makes this method execute before the images are on HTML\r\n //It can be removed if somehow this method is just called after the images are available.\r\n // console.log(\"Loading examples as tensors....\")\r\n await this.delay(0);\r\n\r\n for (let i = 0; i < this.classes_names.length; i++) {\r\n await this.add_example(this.classes_names[i], this.number_of_samples_per_class);\r\n }\r\n }\r\n\r\n async add_example(name: string, number_of_species: number){ \r\n\r\n const class_add: any= [];\r\n // console.log(name)\r\n for (let i = 0; i < number_of_species; i++) { \r\n \r\n //Collecting the images from HTML\r\n const aux = document.getElementById(`class-${name}-${i}`) as HTMLImageElement; \r\n\r\n //Adding the example\r\n const index= this.classes_names.findIndex((elem)=>elem===name)\r\n\r\n await TeachableMobileNet.addExample(index, name, aux); \r\n \r\n }\r\n\r\n // this.classes.push({name: name, images: class_add}) \r\n\r\n }\r\n\r\n delay(ms: number) {\r\n return new Promise<void>((resolve) => setTimeout(resolve, ms));\r\n}\r\n}\r\n","<div *ngFor=\"let class of classes; index as i\">\r\n <h1>{{class.name}}</h1>\r\n <img *ngFor=\"let item of class.images; index as i\" [src]=\"item\" width=\"224\" height=\"224\" [id]=\"'class-' + class.name + '-' + i\" crossorigin=\"anonymous\" >\r\n</div>\r\n","/*\r\n * Public API Surface of tfjs-evolution\r\n */\r\n\r\nexport * from './lib/tfjs-evolution.service';\r\nexport * from './lib/tfjs-evolution.component';\r\n\r\nexport * from './lib/components/display-panel/display-panel.component';\r\n\r\nexport * from './lib/models/teachable-evolution';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tfjs-evolution.mjs","sources":["../../../projects/tfjs-evolution/src/lib/tfjs-evolution.service.ts","../../../projects/tfjs-evolution/src/lib/tfjs-evolution.component.ts","../../../projects/tfjs-evolution/src/lib/models/custom-mobilenet.ts","../../../projects/tfjs-evolution/src/lib/utils/tf.ts","../../../projects/tfjs-evolution/src/lib/utils/util.ts","../../../projects/tfjs-evolution/src/lib/models/teachable-evolution.ts","../../../projects/tfjs-evolution/src/lib/components/display-panel/display-panel.component.ts","../../../projects/tfjs-evolution/src/lib/components/display-panel/display-panel.component.html","../../../projects/tfjs-evolution/src/lib/Classes/neuro-evolution.ts","../../../projects/tfjs-evolution/src/lib/Classes/genetic-algorithm.ts","../../../projects/tfjs-evolution/src/public-api.ts","../../../projects/tfjs-evolution/src/tfjs-evolution.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class TfjsEvolutionService {\r\n\r\n constructor() { }\r\n}\r\n","import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'neuroevolution-tfjs-evolution',\r\n standalone: true,\r\n imports: [],\r\n template: `\r\n <p>\r\n tfjs-evolution works!\r\n </p>\r\n `,\r\n styles: ``\r\n})\r\nexport class TfjsEvolutionComponent {\r\n\r\n}\r\n","\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\nimport { SymbolicTensor } from '@tensorflow/tfjs';\r\n\r\n\r\nexport const IMAGE_SIZE = 224;\r\n\r\n\r\n/**\r\n * the metadata to describe the model's creation,\r\n * includes the labels associated with the classes\r\n * and versioning information from training.\r\n */\r\nexport interface Metadata {\r\n tfjsVersion: string;\r\n tmVersion?: string;\r\n packageVersion: string;\r\n packageName: string;\r\n modelName?: string;\r\n timeStamp?: string;\r\n labels: string[];\r\n userMetadata?: {};\r\n grayscale?: boolean;\r\n imageSize?: number;\r\n}\r\n\r\nexport interface ModelOptions {\r\n version?: number;\r\n checkpointUrl?: string;\r\n alpha?: number;\r\n trainingLayer?: string;\r\n}\r\n\r\nconst DEFAULT_MOBILENET_VERSION = 2;\r\nconst DEFAULT_TRAINING_LAYER_V1 = 'conv_pw_13_relu';\r\nconst DEFAULT_TRAINING_LAYER_V2 = \"out_relu\"; \r\nconst DEFAULT_ALPHA_V1_v2 = 0.35;\r\nconst DEFAULT_ALPHA_V1 = 0.25;//256\r\nconst DEFAULT_ALPHA_V2 = 0.5; //512\r\nconst DEFAULT_ALPHA_V3 = 0.75;//768 features\r\nconst DEFAULT_ALPHA_V4 = 1;//1024 features\r\nconst DEFAULT_ALPHA = 1;//1024 features\r\n\r\n// v2: 0.35, 0.50, 0.75 or 1.00.\r\n\r\nconst isAlphaValid = (version: number, alpha: number) => {\r\n if (version === 1) {\r\n if (alpha !== 0.25 && alpha !== 0.5 && alpha !== 0.75 && alpha !== 1) {\r\n console.warn(\"Invalid alpha. Options are: 0.25, 0.50, 0.75 or 1.00.\");\r\n console.log(\"Loading model with alpha: \", DEFAULT_ALPHA_V1.toFixed(2)); \r\n return DEFAULT_ALPHA_V1;\r\n }\r\n }\r\n else {\r\n if (alpha !== 0.35 && alpha !== 0.5 && alpha !== 0.75 && alpha !== 1) {\r\n console.warn(\"Invalid alpha. Options are: 0.35, 0.50, 0.75 or 1.00.\");\r\n console.log(\"Loading model with alpha: \", DEFAULT_ALPHA_V2.toFixed(2)); \r\n return DEFAULT_ALPHA_V2;\r\n }\r\n }\r\n\r\n return alpha;\r\n};\r\n\r\n\r\nconst parseModelOptions = (options?: ModelOptions) => {\r\n options = options || {}\r\n\r\n if (options.checkpointUrl && options.trainingLayer) {\r\n if (options.alpha || options.version){\r\n console.warn(\"Checkpoint URL passed to modelOptions, alpha options are ignored\");\r\n } \r\n return [options.checkpointUrl, options.trainingLayer];\r\n } else {\r\n options.version = options.version || DEFAULT_MOBILENET_VERSION;\r\n \r\n if(options.version === 1){\r\n options.alpha = options.alpha || DEFAULT_ALPHA_V4; \r\n options.alpha = isAlphaValid(options.version, options.alpha);\r\n\r\n console.log(`Loading mobilenet ${options.version} and alpha ${options.alpha}`);\r\n // exception is alpha o f 1 can only be 1.0\r\n let alphaString = options.alpha.toFixed(2);\r\n if (alphaString === \"1.00\") { alphaString = \"1.0\"; }\r\n\r\n console.log(\"Using the model: \", )\r\n\r\n return [\r\n // tslint:disable-next-line:max-line-length\r\n //They are loading MobileNet_v1 \r\n `https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_${alphaString}_${IMAGE_SIZE}/model.json`,\r\n DEFAULT_TRAINING_LAYER_V1\r\n ];\r\n }\r\n else if (options.version === 2){\r\n options.alpha = options.alpha || DEFAULT_ALPHA_V4; \r\n options.alpha = isAlphaValid(options.version, options.alpha);\r\n\r\n console.log(`Loading mobilenet ${options.version} and alpha ${options.alpha}`);\r\n console.log(`Loading mobilenet ${options.version} and alpha ${options.alpha}`);\r\n\r\n return [\r\n // tslint:disable-next-line:max-line-length \r\n `https://storage.googleapis.com/teachable-machine-models/mobilenet_v2_weights_tf_dim_ordering_tf_kernels_${options.alpha.toFixed(2)}_${IMAGE_SIZE}_no_top/model.json`,\r\n DEFAULT_TRAINING_LAYER_V2\r\n ];\r\n } else {\r\n throw new Error(`MobileNet V${options.version} doesn't exist`);\r\n } \r\n }\r\n};\r\n\r\n\r\n/**\r\n * load the base mobilenet model\r\n * @param modelOptions options determining what model to load\r\n */\r\nexport async function loadTruncatedMobileNet(modelOptions?: ModelOptions) {\r\n const [checkpointUrl, trainingLayer] = parseModelOptions(modelOptions);\r\n \r\n \r\n const mobilenet = await tf.loadLayersModel(checkpointUrl);\r\n\r\n if (modelOptions && modelOptions.version === 1){\r\n const layer = mobilenet.getLayer(trainingLayer);\r\n \r\n const truncatedModel = tf.model({ inputs: mobilenet.inputs, outputs: layer.output });\r\n console.log(\"Feature model loaded, memory: \", tf.memory().numBytes);\r\n\r\n \r\n const model = tf.sequential();\r\n model.add(truncatedModel);\r\n model.add(tf.layers.flatten()); \r\n \r\n \r\n return model;\r\n }\r\n else {\r\n const layer = mobilenet.getLayer(trainingLayer);\r\n const truncatedModel = tf.model({ inputs: mobilenet.inputs, outputs: layer.output });\r\n console.log(\"Feature model loaded, memory: \", tf.memory().numBytes);\r\n const model = tf.sequential();\r\n model.add(truncatedModel);\r\n model.add(tf.layers.globalAveragePooling2d({})); // go from shape [7, 7, 1280] to [1280]\r\n return model;\r\n }\r\n}\r\n\r\n\r\nexport class CustomMobileNet {\r\n /**\r\n * the truncated mobilenet model we will train on top of\r\n */\r\n protected truncatedModel!: tf.LayersModel;\r\n static truncatedModel: tf.Sequential;\r\n\r\nstatic getinputShape(){\r\n /**truncatedModel is the base model, the model used to apply transfer learning */\r\n const inputShape: any = this.truncatedModel.outputs[0].shape.slice(1); // [ 7 x 7 x 1280] (not sure about those dimensions)\r\n// console.log(\"Input Shape(complete): \", this.truncatedModel.outputs[0].shape);\r\n// console.log(\"Input Shape: \", inputShape);\r\n\r\n const inputSize = tf.util.sizeFromShape(inputShape);\r\n\r\n// console.log(\"Input Size: \", inputSize);\r\n\r\n return inputSize;\r\n}\r\n\r\n static get EXPECTED_IMAGE_SIZE() {\r\n return IMAGE_SIZE;\r\n }\r\n\r\n protected _metadata!: Metadata;\r\n\r\n public getMetadata() {\r\n return this._metadata;\r\n }\r\n\r\n constructor() {\r\n // this._metadata = fillMetadata(metadata);\r\n //Loading the truncated model\r\n // loadTruncatedMobileNet();\r\n // this.loadFeatureModel();\r\n\r\n }\r\n\r\n static async loadFeatureModel(){\r\n\r\n this.truncatedModel = await loadTruncatedMobileNet();\r\n\r\n }\r\n\r\n /**\r\n * get the total number of classes existing within model\r\n */\r\n // getTotalClasses() {\r\n // const output = this.model.output as SymbolicTensor;\r\n // const totalClasses = output.shape[1];\r\n // return totalClasses;\r\n // }\r\n\r\n /**\r\n * get the model labels\r\n */\r\n getClassLabels() {\r\n return this._metadata.labels;\r\n }\r\n\r\n /**\r\n * Given an image element, makes a prediction through mobilenet returning the\r\n * probabilities of the top K classes.\r\n * @param image the image to classify\r\n * @param maxPredictions the maximum number of classification predictions\r\n */\r\n // async predictTopK(image: ClassifierInputSource, maxPredictions = 10, flipped = false) {\r\n // const croppedImage = cropTo(image, this._metadata.imageSize, flipped);\r\n\r\n // const logits = tf.tidy(() => {\r\n // const captured = capture(croppedImage, this._metadata.grayscale);\r\n // return this.model.predict(captured);\r\n // });\r\n\r\n // // Convert logits to probabilities and class names.\r\n // const classes = await getTopKClasses(this._metadata.labels, logits as tf.Tensor<tf.Rank>, maxPredictions);\r\n // dispose(logits);\r\n\r\n // return classes;\r\n // }\r\n\r\n /**\r\n * Given an image element, makes a prediction through mobilenet returning the\r\n * probabilities for ALL classes.\r\n * @param image the image to classify\r\n * @param flipped whether to flip the image on X\r\n */\r\n // async predict(image: ClassifierInputSource, flipped = false) {\r\n // const croppedImage = cropTo(image, this._metadata.imageSize, flipped);\r\n\r\n // const logits = tf.tidy(() => {\r\n // const captured = capture(croppedImage, this._metadata.grayscale);\r\n // return this.model.predict(captured);\r\n // });\r\n\r\n // const values = await (logits as tf.Tensor<tf.Rank>).data();\r\n\r\n // const classes = [];\r\n // for (let i = 0; i < values.length; i++) {\r\n // classes.push({\r\n // className: this._metadata.labels[i],\r\n // probability: values[i]\r\n // });\r\n // }\r\n\r\n // dispose(logits);\r\n\r\n // return classes;\r\n // }\r\n\r\n public dispose() {\r\n this.truncatedModel.dispose();\r\n }\r\n}// end of CustomMobileNet\r\n","import * as tf from '@tensorflow/tfjs';\r\n\r\n/**\r\n * Receives an image and normalizes it between -1 and 1.\r\n * Returns a batched image (1 - element batch) of shape [1, w, h, c]\r\n * @param rasterElement the element with pixels to convert to a Tensor\r\n * @param grayscale optinal flag that changes the crop to [1, w, h, 1]\r\n */\r\nexport function capture(rasterElement: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement, grayscale?: boolean) {\r\n return tf.tidy(() => {\r\n // console.log(\"Not a tensor....\")\r\n const pixels = tf.browser.fromPixels(rasterElement);\r\n\r\n // crop the image so we're using the center square\r\n const cropped = cropTensor(pixels);\r\n\r\n // Expand the outer most dimension so we have a batch size of 1\r\n const batchedImage = cropped.expandDims(0);\r\n\r\n // Normalize the image between -1 and a1. The image comes in between 0-255\r\n // so we divide by 127 and subtract 1.\r\n return batchedImage.toFloat().div(tf.scalar(127)).sub(tf.scalar(1));\r\n });\r\n}\r\n\r\n\r\n\r\nexport function cropTensor( img: tf.Tensor3D ) : tf.Tensor3D {\r\n \r\n const size = Math.min(img.shape[0], img.shape[1]);\r\n const centerHeight = img.shape[0] / 2;\r\n const beginHeight = centerHeight - (size / 2);\r\n const centerWidth = img.shape[1] / 2;\r\n const beginWidth = centerWidth - (size / 2);\r\n \r\n\r\n return img.slice([beginHeight, beginWidth, 0], [size, size, 3]);\r\n}","\r\nimport {Class} from \"./class\"\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\n\r\nexport class Util {\r\n\r\n/**\r\n * Receives an image and normalizes it between -1 and 1.\r\n * Returns a batched image (1 - element batch) of shape [1, w, h, c]\r\n * @param rasterElement the element with pixels to convert to a Tensor\r\n * @param grayscale optinal flag that changes the crop to [1, w, h, 1]\r\n */\r\ncapture(rasterElement: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement, grayscale?: boolean) {\r\n return tf.tidy(() => {\r\n const pixels = tf.browser.fromPixels(rasterElement);\r\n\r\n // // crop the image so we're using the center square\r\n const cropped = this.cropTensor(pixels, grayscale);\r\n\r\n // // Expand the outer most dimension so we have a batch size of 1\r\n const batchedImage = cropped.expandDims(0);\r\n\r\n // // Normalize the image between -1 and a1. The image comes in between 0-255\r\n // // so we divide by 127 and subtract 1.\r\n return batchedImage.toFloat().div(tf.scalar(127)).sub(tf.scalar(1)); \r\n });\r\n} \r\n\r\n\r\ncropTensor( img: tf.Tensor3D, grayscaleModel?: boolean, grayscaleInput?: boolean ) : tf.Tensor3D {\r\n const size = Math.min(img.shape[0], img.shape[1]);\r\n const centerHeight = img.shape[0] / 2;\r\n const beginHeight = centerHeight - (size / 2);\r\n const centerWidth = img.shape[1] / 2;\r\n const beginWidth = centerWidth - (size / 2);\r\n \r\n if (grayscaleModel && !grayscaleInput) {\r\n //cropped rgb data\r\n let grayscale_cropped = img.slice([beginHeight, beginWidth, 0], [size, size, 3]);\r\n \r\n grayscale_cropped = grayscale_cropped.reshape([size * size, 1, 3])\r\n const rgb_weights = [0.2989, 0.5870, 0.1140]\r\n grayscale_cropped = tf.mul(grayscale_cropped, rgb_weights)\r\n grayscale_cropped = grayscale_cropped.reshape([size, size, 3]);\r\n \r\n grayscale_cropped = tf.sum(grayscale_cropped, -1)\r\n grayscale_cropped = tf.expandDims(grayscale_cropped, -1)\r\n\r\n return grayscale_cropped;\r\n }\r\n return img.slice([beginHeight, beginWidth, 0], [size, size, 3]);\r\n}\r\n\r\n\r\n\r\n\r\n/**\r\n * This function will make a copy of a model on the weight level\r\n * This is an attempt to avoid influencing the new mode when the old one\r\n * is eliminated. \r\n * \r\n * @param originalModel - the model to be copied \r\n * @param recipient - the new model\r\n */\r\nasync copyModel_v3 (originalModel: tf.Sequential, recipient: tf.Sequential) {\r\n\r\n originalModel.layers.forEach((layer, index)=>{\r\n recipient.layers[index].setWeights(layer.getWeights())\r\n })\r\n\r\n // originalModel.dispose();\r\n}\r\n \r\n/**\r\n * This function will make a copy of a TFJS model, as so it would be possible \r\n * to erase the original.\r\n * @param model - model to be copied\r\n * @returns - copy of the model\r\n */ \r\nasync copyModel_v2 (originalModel: tf.Sequential) {\r\n // Serialize the original model\r\n const modelTopology = originalModel.toJSON();\r\n\r\n // Load the serialized model into a new model\r\n const copiedModel = await tf.loadLayersModel(\r\n tf.io.fromMemory(modelTopology, undefined, undefined)\r\n );\r\n \r\n // Compile the copied model with the same settings as the original\r\n copiedModel.compile({\r\n loss: originalModel.loss,\r\n optimizer: originalModel.optimizer\r\n });\r\n \r\n return copiedModel;\r\n}\r\n\r\n/**\r\n * This function will make a copy of a TFJS model, as so it would be possible \r\n * to erase the original.\r\n * @param model - model to be copied\r\n * @returns - copy of the model\r\n */ \r\ncopyModel (model: tf.Sequential) {\r\n \r\n const copy = tf.sequential();`\r\n `\r\n model.layers.forEach(layer => {\r\n const aux =layer;\r\n // layer.dispose();\r\n copy.add(aux);\r\n });\r\n copy.compile({\r\n loss: model.loss,\r\n optimizer: model.optimizer\r\n });\r\n return copy;\r\n }\r\n\r\n\r\n removeElementByIndex(arr: any, index: number): number[] {\r\n // Check if the index is within bounds\r\n if (index >= 0 && index < arr.length) {\r\n // Remove the element at the specified index\r\n arr.splice(index, 1); \r\n }\r\n return arr;\r\n }\r\n\r\n removeElement(arr: any, element: any): number[] {\r\n // Remove all occurrences of the specified element from the array\r\n return arr.filter((item: any) => item !== element);\r\n }\r\n\r\nclean_array_of_tensors(tensors: tf.Sequential[]) {\r\n\r\n tensors.forEach((elem, index)=>{ \r\n // if(!index_selection.includes(index)) \r\n elem.dispose() \r\n });\r\n\r\n}\r\n\r\n getClassNameBySignature(classes: Class[], signature: number[]) { \r\n \r\n const class_name = classes.find(p => {\r\n let match = true;\r\n p.signature?.forEach ((elem,index)=>{ \r\n if(elem!==signature[index])\r\n match=false; \r\n })\r\n\r\n return match;\r\n });\r\n\r\n return class_name ? class_name.name : \"not found\";\r\n}\r\n\r\nidentityMatrix(n: number): number[][] {\r\n return Array.from({ length: n }, (_, i) => Array.from({ length: n }, (_, j) => (i === j ? 1 : 0)));\r\n} \r\n\r\n\r\nindexOfMax(arr: number[]): number {\r\n if (arr.length === 0) {\r\n return -1; // Return -1 for an empty array\r\n }\r\n \r\n let max = arr[0];\r\n let maxIndex = 0;\r\n \r\n for (let i = 1; i < arr.length; i++) {\r\n if (arr[i] > max) {\r\n maxIndex = i;\r\n max = arr[i];\r\n }\r\n }\r\n \r\n return maxIndex;\r\n }\r\n\r\n\r\nsuffle(array1:any, array2: any){\r\n // Shuffle the order of elements\r\n for (let i = array1.length - 1; i > 0; i--) {\r\n const j = Math.floor(Math.random() * (i + 1));\r\n\r\n // Swap elements in both arrays\r\n [array1[i], array1[j]] = [array1[j], array1[i]];\r\n [array2[i], array2[j]] = [array2[j], array2[i]];\r\n }\r\n \r\n \r\n }\r\n\r\n sortByValuePreservingIndex<T>(\r\n arr1: number[],\r\n arr2: any[]\r\n ): T[] {\r\n\r\n // console.log(\"Vector for organizing: \", arr1)\r\n // arr2[0].summary()\r\n\r\n // Create an array of objects with value, index from arr1, and original index\r\n const pairingArray = arr1.map((value, index) => ({\r\n value,\r\n index,\r\n originalIndex: index,\r\n elementFromArr2: arr2[index], // Preserve the corresponding element from arr2\r\n }));\r\n \r\n // Sort the pairing array by value (largest to smallest)\r\n pairingArray.sort((a, b) => b.value - a.value);\r\n\r\n \r\n \r\n // Extract the sorted elements from arr2 based on the original index\r\n const sortedElementsFromArr2 = pairingArray.map(pair => pair.elementFromArr2);\r\n \r\n return sortedElementsFromArr2;\r\n } \r\n \r\n}\r\n\r\n","import { CustomMobileNet, loadTruncatedMobileNet } from \"./custom-mobilenet\";\r\n\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\nimport { capture } from '../utils/tf';\r\nimport { Class } from '../utils/class';\r\nimport { Util } from \"../utils/util\";\r\n\r\nimport * as seedrandom from 'seedrandom';\r\n\r\nimport * as tfvis from '@tensorflow/tfjs-vis';\r\n\r\nimport { TensorContainer } from '@tensorflow/tfjs-core/dist/tensor_types';\r\n\r\nconst VALIDATION_FRACTION = 0.15;\r\n\r\n\r\n\r\n/**\r\n * the metadata to describe the model's creation,\r\n * includes the labels associated with the classes\r\n * and versioning information from training.\r\n */\r\nexport interface Metadata {\r\n tfjsVersion: string;\r\n tmVersion?: string;\r\n packageVersion: string;\r\n packageName: string;\r\n modelName?: string;\r\n timeStamp?: string;\r\n labels: string[];\r\n userMetadata?: {};\r\n grayscale?: boolean;\r\n imageSize?: number;\r\n}\r\n\r\n/**\r\n * Receives a Metadata object and fills in the optional fields such as timeStamp\r\n * @param data a Metadata object\r\n */\r\nconst fillMetadata = (data: Partial<Metadata>) => {\r\n // util.assert(typeof data.tfjsVersion === 'string', () => `metadata.tfjsVersion is invalid`);\r\n // data.packageVersion = data.packageVersion || version;\r\n data.packageName = data.packageName || '@teachablemachine/image';\r\n data.timeStamp = data.timeStamp || new Date().toISOString();\r\n data.userMetadata = data.userMetadata || {};\r\n data.modelName = data.modelName || 'untitled';\r\n data.labels = data.labels || [];\r\n // data.imageSize = data.imageSize || IMAGE_SIZE;\r\n return data as Metadata;\r\n};\r\n\r\nexport class TeachableMobileNet extends CustomMobileNet {\r\n\r\n // Array of all the examples collected.\r\n /**\r\n It is static since all the instance will share the same features, for saving memory and time.\r\n The idea is avoiding restoring the features individually and having the recalculate them for every new\r\n individuals.\r\n */\r\n public static examples: Float32Array[][] = [];\r\n\r\n // Number of total samples\r\n private static totalSamples = 0;\r\n\r\n classes: Class[]=[];\r\n\r\n static classes_names: string[]=[];\r\n\r\n static numClasses: number;\r\n\r\n /**\r\n * the training model for transfer learning\r\n */\r\n protected trainingModel!: tf.LayersModel;\r\n trainDataset: any;\r\n validationDataset: any;\r\n static trainDataset: any;\r\n static validationDataset: any;\r\n static numValidation: number;\r\n\r\n constructor(){\r\n super();\r\n this.createHead();\r\n }\r\n\r\n /**\r\n * This method will return the head, the trainable part, the part under evolution.\r\n */\r\n getHead(){\r\n return this.trainingModel;\r\n }\r\n\r\n /**\r\n * Create the head for transfer learning.\r\n * This is the trainable section of the transfer learning.\r\n */\r\n createHead(){\r\n\r\n const inputSize= TeachableMobileNet.getinputShape();\r\n\r\n this.trainingModel = tf.sequential({\r\n layers: [\r\n tf.layers.dense({\r\n inputShape: [inputSize],\r\n units:100,\r\n activation: 'relu', \r\n useBias: true\r\n }),\r\n tf.layers.dense({ \r\n useBias: false,\r\n activation: 'softmax',\r\n units: TeachableMobileNet.classes_names.length\r\n })\r\n ]\r\n });\r\n\r\n const optimizer = tf.train.adam();\r\n // const optimizer = tf.train.rmsprop(params.learningRate);\r\n\r\n this.trainingModel.compile({\r\n optimizer,\r\n // loss: 'binaryCrossentropy',\r\n loss: 'categoricalCrossentropy',\r\n metrics: ['accuracy']\r\n });\r\n }\r\n \r\n async train(){\r\n\r\n const trainingSurface = { name: 'Loss and MSE', tab: 'Training' };\r\n\r\n const dataset= TeachableMobileNet.convertToTfDataset();\r\n\r\n //Salving a copy of the validation dataset, for later\r\n TeachableMobileNet.validationDataset= dataset.validationDataset;\r\n\r\n // console.log(\"Dataset for training: \", dataset.trainDataset);\r\n\r\n const trainData = dataset.trainDataset.batch(30);\r\n const validationData = dataset.validationDataset.batch(10);\r\n\r\n // this.createHead();\r\n\r\n const callbacks= [\r\n // Show on a tfjs-vis visor the loss and accuracy values at the end of each epoch.\r\n tfvis.show.fitCallbacks(trainingSurface, ['loss', 'acc', \"val_loss\", \"val_acc\"],\r\n {\r\n callbacks: ['onEpochEnd'],\r\n }\r\n ),\r\n {},]\r\n\r\n const history: any = await this.trainingModel.fitDataset(trainData, {\r\n epochs: 100,\r\n validationData,\r\n callbacks\r\n}).then((info:any)=>{\r\n console.log('Precisão final', info.history.val_acc[info.history.acc.length-1]);\r\n});\r\n\r\n\r\n// await this.accuracy_per_class();\r\n\r\n\r\n// console.log(\"History: \", history.history.acc);\r\n // await this.trainingModel.fit(this.featureX, this.target, {})\r\n }\r\n\r\nasync accuracy_per_class(confusion_matrix_recipient: any){\r\n /**Calculating Accuracy per class */\r\nconst accuracyperclass: any = await this.calculateAccuracyPerClass(TeachableMobileNet.validationDataset);\r\n// console.log(\"Accuracy per class: \", accuracyperclass);\r\n\r\n//Confusion matrix\r\n// Calling tf.confusionMatrix() method \r\nconst output = tf.math.confusionMatrix( accuracyperclass.reference, accuracyperclass.predictions, TeachableMobileNet.classes_names.length); \r\n \r\n// Printing output \r\noutput.print()\r\nconst confusion_matrix= output.dataSync();\r\n\r\n// console.log(confusion_matrix);\r\n// console.log(confusion_matrix[TeachableMobileNet.classes_names.length + TeachableMobileNet.classes_names.length]);\r\n\r\nconst accuracy = [];\r\n\r\nfor(let i=0; i<TeachableMobileNet.classes_names.length;i++){\r\n\r\n accuracy.push(confusion_matrix[TeachableMobileNet.classes_names.length*i+ i]/TeachableMobileNet.numValidation)\r\n}\r\n\r\nconsole.log(\"Accuracy per class: \", accuracy);\r\n\r\nfor(let i=0; i<TeachableMobileNet.classes_names.length;i++){\r\n\r\n confusion_matrix_recipient.push([]);\r\n\r\n for(let j=0; j<TeachableMobileNet.classes_names.length;j++){\r\n confusion_matrix_recipient[i].push([]);\r\n\r\n confusion_matrix_recipient[i][j]= confusion_matrix[TeachableMobileNet.classes_names.length*i+ j]/TeachableMobileNet.numValidation\r\n confusion_matrix_recipient[i][j]=(confusion_matrix_recipient[i][j].toFixed(2))*100;\r\n }\r\n\r\n // accuracy.push(confusion_matrix[TeachableMobileNet.classes_names.length*i+ i]/TeachableMobileNet.numValidation)\r\n}\r\n\r\nconsole.log(\"Confusion matrix as a matrix\")\r\nconsole.log(confusion_matrix_recipient);\r\n\r\nreturn accuracy.map((elem: any)=>elem.toFixed(2)*100);\r\n}\r\n\r\n \r\n async loadImages(number_of_species: number, classes_names: string[], options: object){\r\n TeachableMobileNet.classes_names=classes_names;\r\n \r\n await this.add_species(number_of_species, options); \r\n\r\n}\r\n\r\nasync add_species(number_of_species: number, options: object){\r\n \r\n //Loading feature model, used to create features from images\r\n // await this.loadFeatureModel();\r\n\r\n for (let i = 0; i < TeachableMobileNet.classes_names.length; i++) {\r\n // this.add_images(this.classes_names[i], number_of_species, options);\r\n }\r\n}\r\n\r\n/**\r\n * \r\n * @param name - name of the class receiving an example\r\n * @param number_of_species - how many images to add\r\n * @param options - details on the location of the images\r\n */\r\nasync add_images(name: string, number_of_species: number, options: any){ \r\n\r\n const class_add: any= [];\r\n\r\n for (let i = 0; i < number_of_species; i++) { \r\n // class_add.push(`${options.base}/${name}/${options.file_name} ${i}.${options.file_extension}`);\r\n \r\n //Uploading images\r\n const cake = new Image(); \r\n // cake.src = `${options.base}/${name}/${options.file_name} ${i}.${options.file_extension}`;\r\n cake.height=224;\r\n cake.width=224;\r\n cake.src=\"./assets/dataset/Can%C3%A1rio-da-Terra/image%200.jpeg\"\r\n // console.log(\"Image location: \", cake.src )\r\n\r\n await new Promise<void>((resolve, reject) => {\r\n cake.onload = () => {\r\n\r\n //Finding the correspondent index of the class with name given\r\n const index= TeachableMobileNet.classes_names.findIndex((elem)=>elem===name)\r\n\r\n // this.addExample(index, cake);\r\n\r\n resolve();\r\n };\r\n \r\n cake.onerror = (error) => {\r\n // Handle error if the image fails to load\r\n reject(error);\r\n };\r\n });\r\n }\r\n\r\n // this.classes.push({name: name, images: class_add}) \r\n\r\n }\r\n\r\n\r\n\r\n \r\n/**\r\n * This method will transform images into tensors\r\n * @param number_of_classes - number of classes\r\n * @param classes_names - name of each class\r\n */\r\nasync createTensors(number_of_classes: number, classes_names: string[]) {\r\n\r\n let output: any = [];\r\n\r\n /** There is a function on TensorFlow.js that also does that */\r\n const signatures= new Util().identityMatrix(number_of_classes);\r\n\r\n for (let i = 0; i < number_of_classes; i++) {\r\n\r\n this.classes[i].signature=signatures[i];\r\n this.classes[i].name=classes_names[i];\r\n\r\n for (let j = 0; j < this.classes[i].images.length; j++) {\r\n\r\n\r\n }\r\n\r\n }\r\n}\r\n\r\n /**\r\n * Add a sample of data under the provided className\r\n * @param className the classification this example belongs to\r\n * @param sample the image / tensor that belongs in this classification\r\n */\r\n // public async addExample(className: number, sample: HTMLCanvasElement | tf.Tensor) {\r\npublic static async addExample(className: number, name: string, sample: HTMLImageElement | HTMLCanvasElement | tf.Tensor) {\r\n\r\n // console.log(\"Adding a new example...\") \r\n \r\n const cap = isTensor(sample) ? sample : capture(sample);\r\n \r\n \r\n //Getting the features\r\n const example = this.truncatedModel.predict(cap) as tf.Tensor;\r\n // console.log(\"Shape after feature extraction: \", example.shape) \r\n \r\n\r\n const activation = example.dataSync() as Float32Array;\r\n \r\n //Very important to clean the memory aftermath, it makes the difference\r\n cap.dispose();\r\n example.dispose();\r\n \r\n // //Accessing the instance variable, not the local ones\r\n // // save samples of each class separately \r\n \r\n if(!TeachableMobileNet.examples[className])\r\n //and an empty array, make sure there is not empty elements. \r\n //it will create issue when transforming to tensors\r\n TeachableMobileNet.examples[className]=[]\r\n\r\n\r\n if(!TeachableMobileNet.classes_names[className])\r\n //Saving the lable when it first appears\r\n TeachableMobileNet.classes_names[className]=name;\r\n\r\n TeachableMobileNet.examples[className].push(activation);\r\n \r\n // // increase our sample counter\r\n TeachableMobileNet.totalSamples++;\r\n }\r\n\r\n\r\n /**\r\n * process the current examples provided to calculate labels and format\r\n * into proper tf.data.Dataset\r\n */\r\n static prepare() {\r\n for (const classes in TeachableMobileNet.examples){\r\n if (classes.length === 0) {\r\n throw new Error('Add some examples before training');\r\n }\r\n }\r\n\r\n const datasets: any = this.convertToTfDataset();\r\n\r\n this.trainDataset = datasets.trainDataset;\r\n this.validationDataset = datasets.validationDataset;\r\n}\r\n\r\npublic prepareDataset() {\r\n for (let i = 0; i < TeachableMobileNet.numClasses; i++) {\r\n //Different from the original implementation of TM, mine is using example as static.\r\n //The goal is saving memory by using a single instance of the variable\r\n TeachableMobileNet.examples[i] = [];\r\n }\r\n}\r\n\r\n \r\n // Optional seed to make shuffling of data predictable\r\n static seed: seedrandom.prng;\r\n\r\n\r\n\r\n \r\n/**\r\n * Process the examples by first shuffling randomly per class, then adding\r\n * one-hot labels, then splitting into training/validation datsets, and finally\r\n * sorting one last time\r\n */\r\n \r\nstatic convertToTfDataset() {\r\n\r\n // first shuffle each class individually\r\n // TODO: we could basically replicate this by insterting randomly\r\n for (let i = 0; i < TeachableMobileNet.examples.length; i++) {\r\n TeachableMobileNet.examples[i] = fisherYates(TeachableMobileNet.examples[i], this.seed) as Float32Array[];\r\n }\r\n\r\n // then break into validation and test datasets\r\n let trainDataset: Sample[] = [];\r\n let validationDataset: Sample[] = [];\r\n\r\n // for each class, add samples to train and validation dataset\r\n for (let i = 0; i < TeachableMobileNet.examples.length; i++) {\r\n \r\n // console.log(\"Number of classes: \", TeachableMobileNet.classes_names.length);\r\n\r\n const y = flatOneHot(i, TeachableMobileNet.classes_names.length);\r\n\r\n const classLength = TeachableMobileNet.examples[i].length;\r\n\r\n // console.log(\"Number of elements per class: \", classLength);\r\n\r\n const numValidation = Math.ceil(VALIDATION_FRACTION * classLength);\r\n const numTrain = classLength - numValidation;\r\n\r\n this.numValidation=numValidation;\r\n \r\n /**It is visiting per class, thus, it is possible to fix y, the target label */\r\n \r\n const classTrain = this.examples[i].slice(0, numTrain).map((dataArray) => {\r\n return { data: dataArray, label: y };\r\n });\r\n\r\n const classValidation = this.examples[i].slice(numTrain).map((dataArray) => {\r\n return { data: dataArray, label: y };\r\n });\r\n\r\n trainDataset = trainDataset.concat(classTrain);\r\n validationDataset = validationDataset.concat(classValidation); \r\n\r\n\r\n }\r\n\r\n // console.log(\"Training element: \", trainDataset[trainDataset.length-1]) \r\n // console.log(\"Training length: \", trainDataset.length)\r\n // console.log(\"validation length: \", validationDataset.length);\r\n\r\n \r\n // finally shuffle both train and validation datasets\r\n trainDataset = fisherYates(trainDataset, this.seed) as Sample[];\r\n validationDataset = fisherYates(validationDataset, this.seed) as Sample[];\r\n\r\n const trainX = tf.data.array(trainDataset.map(sample => sample.data));\r\n const validationX = tf.data.array(validationDataset.map(sample => sample.data));\r\n const trainY = tf.data.array(trainDataset.map(sample => sample.label));\r\n const validationY = tf.data.array(validationDataset.map(sample => sample.label));\r\n\r\n // return tf.data dataset objects\r\n return {\r\n trainDataset: tf.data.zip({ xs: trainX, ys: trainY}),\r\n validationDataset: tf.data.zip({ xs: validationX, ys: validationY})\r\n };\r\n\r\n\r\n}\r\n\r\ndatasetForEvaluation(){\r\n\r\n}\r\n\r\n/**Metrics */\r\n\r\nstatic feature_aux: any;\r\nstatic target_aux: any;\r\n\r\nasync evaluate(){\r\n \r\n if(!TeachableMobileNet.feature_aux){\r\n const features: any=[];\r\n const targets: any=[];\r\n\r\n for (let i = 0; i < TeachableMobileNet.examples.length; i++) {\r\n\r\n const y = flatOneHot(i, TeachableMobileNet.classes_names.length);\r\n \r\n\r\n\r\n //For class i, push all the examples.\r\n TeachableMobileNet.examples[i].forEach((elemn)=>{\r\n\r\n //Pushing the target signature\r\n targets.push(y);\r\n \r\n //Pushing features\r\n features.push(elemn)\r\n })\r\n\r\n } \r\n\r\n TeachableMobileNet.feature_aux= tf.tensor(features);\r\n TeachableMobileNet.target_aux= tf.tensor(targets);\r\n\r\n } \r\n\r\n const aux: any = this.trainingModel.evaluate(TeachableMobileNet.feature_aux, TeachableMobileNet.target_aux);\r\n \r\n return aux[1].dataSync()[0];\r\n\r\n\r\n}\r\n\r\n\r\n// async evaluate(){\r\n\r\n// const features: any=[];\r\n// const targets: any=[];\r\n\r\n// for (let i = 0; i < TeachableMobileNet.examples.length; i++) {\r\n\r\n// const y = flatOneHot(i, TeachableMobileNet.classes_names.length);\r\n \r\n\r\n\r\n// //For class i, push all the examples.\r\n// TeachableMobileNet.examples[i].forEach((elemn)=>{\r\n\r\n// //Pushing the target signature\r\n// targets.push(y);\r\n \r\n// //Pushing features\r\n// features.push(elemn)\r\n// })\r\n\r\n// } \r\n\r\n// const aux_features= tf.tensor(features);\r\n// const aux_target= tf.tensor(targets);\r\n\r\n \r\n// // console.log(\"Tensor stack for evaluation: \", aux_features.shape)\r\n\r\n// const aux: any = this.trainingModel.evaluate(aux_features, aux_target);\r\n\r\n\r\n// return aux[1].dataSync()[0];\r\n\r\n\r\n// }\r\n\r\n\r\n/*** Final statistics */\r\n/* \r\n * Calculate each class accuracy using the validation dataset\r\n*/\r\npublic async calculateAccuracyPerClass(validationData: any) {\r\n\r\n const validationXs = TeachableMobileNet.validationDataset.mapAsync(async (dataset: TensorContainer) => {\r\n return (dataset as { xs: TensorContainer, ys: TensorContainer}).xs;\r\n});\r\n\r\nconst validationYs = TeachableMobileNet.validationDataset.mapAsync(async (dataset: TensorContainer) => {\r\n return (dataset as { xs: TensorContainer, ys: TensorContainer}).ys;\r\n});\r\n\r\n// console.log(\"validation dataset: \", validationXs);\r\n \r\n// console.log(\"For calculating batch size: \", validationYs);\r\n\r\n// we need to split our validation data into batches in case it is too large to fit in memory\r\nconst batchSize = Math.min(validationYs.size, 32);\r\n// const batchSize =1;\r\n\r\nconst iterations = Math.ceil(validationYs.size / batchSize);\r\n\r\n// console.log(\"Batch size: \", batchSize);\r\n\r\nconst batchesX = validationXs.batch(batchSize);\r\n\r\nconst batchesY = validationYs.batch(batchSize);\r\nconst itX = await batchesX.iterator();\r\nconst itY = await batchesY.iterator();\r\nconst allX = [];\r\nconst allY = [];\r\n\r\nfor (let i = 0; i < iterations; i++) {\r\n\r\n // 1. get the prediction values in batches\r\n const batchedXTensor = await itX.next(); \r\n\r\n // console.log(\"Batch size on accuracy per class: \", batchedXTensor.value.shape);\r\n\r\n const batchedXPredictionTensor = this.trainingModel.predict(batchedXTensor.value) as tf.Tensor;\r\n\r\n const argMaxX = batchedXPredictionTensor.argMax(1); // Returns the indices of the max values along an axis\r\n\r\n allX.push(argMaxX);\r\n\r\n // 2. get the ground truth label values in batches\r\n const batchedYTensor = await itY.next();\r\n const argMaxY = batchedYTensor.value.argMax(1); // Returns the indices of the max values along an axis\r\n\r\n allY.push(argMaxY);\r\n \r\n // 3. dispose of all our tensors\r\n batchedXTensor.value.dispose();\r\n batchedXPredictionTensor.dispose();\r\n batchedYTensor.value.dispose();\r\n}\r\n\r\n // concatenate all the results of the batches\r\n const reference = tf.concat(allY); // this is the ground truth\r\n const predictions = tf.concat(allX); // this is the prediction our model is guessing\r\n \r\n // console.log(\"this is the ground truth: \", reference.dataSync())\r\n // console.log(\"This is the prediction our model is guessing: \", predictions.dataSync())\r\n\r\n // only if we concatenated more than one tensor for preference and reference\r\n if (iterations !== 1) {\r\n for (let i = 0; i < allX.length; i++) {\r\n allX[i].dispose();\r\n allY[i].dispose();\r\n }\r\n }\r\n\r\n // console.log(\"Lengtth: \", await reference.dataSync().length) \r\n \r\n // const accuracyperclass=[];\r\n\r\n // const reference_aux= await reference.dataSync();\r\n // const prediction_aux= await predictions.dataSync();\r\n // console.log( predictions.dataSync());\r\n\r\n // reference_aux.forEach((element, index) => {\r\n // if()\r\n \r\n // }); \r\n\r\n\r\n return { reference, predictions }; \r\n\r\n}\r\n\r\n}//end of class\r\n\r\n\r\n\r\n\r\n\r\n/***Support methods (helpers) */\r\n\r\nconst isTensor = (c: any): c is tf.Tensor =>\r\n typeof c.dataId === 'object' && typeof c.shape === 'object';\r\n/**\r\n * Converts an integer into its one-hot representation and returns\r\n * the data as a JS Array.\r\n */\r\nfunction flatOneHot(label: number, numClasses: number) {\r\n\r\n const labelOneHot = new Array(numClasses).fill(0) as number[];\r\n labelOneHot[label] = 1;\r\n\r\n return labelOneHot;\r\n}\r\n\r\ninterface Sample {\r\n data: Float32Array;\r\n label: number[];\r\n}\r\n\r\n\r\n/**\r\n * Shuffle an array of Float32Array or Samples using Fisher-Yates algorithm\r\n * Takes an optional seed value to make shuffling predictable\r\n */\r\nfunction fisherYates(array: Float32Array[] | Sample[], seed?: seedrandom.prng) {\r\n const length = array.length;\r\n\r\n // need to clone array or we'd be editing original as we goo\r\n const shuffled = array.slice();\r\n\r\n for (let i = (length - 1); i > 0; i -= 1) {\r\n let randomIndex ;\r\n if (seed) {\r\n randomIndex = Math.floor(seed() * (i + 1));\r\n }\r\n else {\r\n randomIndex = Math.floor(Math.random() * (i + 1));\r\n }\r\n\r\n [shuffled[i], shuffled[randomIndex]] = [shuffled[randomIndex],shuffled[i]];\r\n }\r\n\r\n return shuffled;\r\n}\r\n","import { Component} from '@angular/core';\r\nimport { Group } from '../../interfaces/group';\r\nimport { CommonModule } from '@angular/common';\r\nimport { TeachableMobileNet } from '../../models/teachable-evolution';\r\n\r\n@Component({\r\n selector: 'neuroevolution-display-panel',\r\n standalone: true,\r\n imports: [CommonModule],\r\n templateUrl: './display-panel.component.html',\r\n styleUrl: './display-panel.component.css'\r\n})\r\nexport class DisplayPanelComponent {\r\n\r\n classes: Group[]=[];\r\n\r\n classes_names!: string[];\r\n\r\n number_of_samples_per_class!: number;\r\n\r\nloadImages(number_of_species: number, classes_names: string[], options: object){\r\n \r\n this.classes_names=classes_names;\r\n this.number_of_samples_per_class=number_of_species;\r\n\r\n this.add_species(number_of_species, options); \r\n\r\n }\r\n\r\n\r\nadd_species(number_of_species: number, options: object){\r\n\r\n for (let i = 0; i < this.classes_names.length; i++) {\r\n this.add_images(this.classes_names[i], number_of_species, options);\r\n \r\n }\r\n\r\n }\r\n\r\n add_images(name: string, number_of_species: number, options: any){ \r\n\r\n const class_add: any= [];\r\n\r\n for (let i = 0; i < number_of_species; i++) { \r\n class_add.push(`${options.base}/${name}/${options.file_name} ${i+1}.${options.file_extension}`);\r\n }\r\n\r\n this.classes.push({name: name, images: class_add}) \r\n\r\n }\r\n\r\n async addexamples(){\r\n\r\n //This is needed to make sure it gives time for the images to upload\r\n //The images upload very fast, what makes this method execute before the images are on HTML\r\n //It can be removed if somehow this method is just called after the images are available.\r\n // console.log(\"Loading examples as tensors....\")\r\n await this.delay(0);\r\n\r\n for (let i = 0; i < this.classes_names.length; i++) {\r\n await this.add_example(this.classes_names[i], this.number_of_samples_per_class);\r\n }\r\n }\r\n\r\n async add_example(name: string, number_of_species: number){ \r\n\r\n const class_add: any= [];\r\n // console.log(name)\r\n for (let i = 0; i < number_of_species; i++) { \r\n \r\n //Collecting the images from HTML\r\n const aux = document.getElementById(`class-${name}-${i}`) as HTMLImageElement; \r\n\r\n //Adding the example\r\n const index= this.classes_names.findIndex((elem)=>elem===name)\r\n\r\n await TeachableMobileNet.addExample(index, name, aux); \r\n \r\n }\r\n\r\n // this.classes.push({name: name, images: class_add}) \r\n\r\n }\r\n\r\n delay(ms: number) {\r\n return new Promise<void>((resolve) => setTimeout(resolve, ms));\r\n}\r\n}\r\n","<div *ngFor=\"let class of classes; index as i\">\r\n <h1>{{class.name}}</h1>\r\n <img *ngFor=\"let item of class.images; index as i\" [src]=\"item\" width=\"224\" height=\"224\" [id]=\"'class-' + class.name + '-' + i\" crossorigin=\"anonymous\" >\r\n</div>\r\n","\r\nimport {TeachableMobileNet} from \"../models/teachable-evolution\"\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\n/**\r\n * Each individual of the population will be made of \r\n * an array, correspodent to the neural network weights and\r\n * an evaluation, its respective accuracy on the dataset given.\r\n * \r\n */\r\ninterface Individual {\r\n individual: TeachableMobileNet,\r\n accuracy?: number\r\n}\r\n\r\nexport abstract class NeuroEvolution {\r\n\r\n /** \r\n This is the population. I have decided to create a population of just weights.\r\n I had to change my mind. Working with weights is tricky. \r\n I have decided to sacrifice memory to make my life easiser.\r\n Tensors has their inner methods, it helps on the operators.\r\n I have to pay attention to memory manegement.\r\n Working with memory in tensors is tricky. \r\n */\r\n\r\n population: Individual[]=[];\r\n private _population_size: number=30;\r\n \r\n /**Setters and Getters */\r\n public set population_size(population_size: number){\r\n this._population_size=population_size;\r\n }\r\n public get population_size(){\r\n return this._population_size;\r\n }\r\n\r\n /**\r\n * Methods with implementation\r\n */\r\n\r\n async evaluate(){\r\n return this.population.forEach(async (elem)=>{\r\n elem.accuracy= await elem.individual.evaluate(); \r\n })\r\n }\r\n\r\n start_population(){\r\n\r\n for(let i=0; i<this.population_size;i++){ \r\n this.population.push({individual: new TeachableMobileNet()})\r\n }\r\n // console.log(\"Population length: \", this.population.length);\r\n // console.log(\"Memory after population iniialization: \", tf.memory().numBytes);\r\n }\r\n\r\n async apply_evolution(iteration: number){\r\n\r\n for(let i=0;i<iteration;i++){\r\n \r\n console.log(\"Interation: \",i)\r\n console.log(\"Memory: \", tf.memory().numBytes);\r\n console.log(\"Tensors in memory: \", tf.memory().numTensors);\r\n console.log(\"Population length: \", this.population.length);\r\n await this.evolution();\r\n }\r\n\r\n }\r\n \r\n /**\r\n * This method will apply the evolution\r\n */\r\n async evolution(){\r\n\r\n \r\n \r\n //Update the accuracy\r\n await this.evaluate();\r\n\r\n const offspring=[];\r\n\r\n /**First step is crossover, for creating offspring */\r\n for(let i=0; i<this.population.length;i++)\r\n {\r\n //The population will double in size\r\n offspring.push(this.crossover()); \r\n }\r\n\r\n //Mutation on the offspring\r\n // console.log(\"Weight before mutation: \", offspring[0].individual.getHead().layers[0].getWeights()[0].dataSync());\r\n\r\n this.mutation(offspring) \r\n\r\n //Joining parents and offspring into the same pool for selection\r\n this.population=[...this.population, ...offspring];\r\n\r\n //Update the accuracy\r\n await this.evaluate();\r\n\r\n\r\n //selection\r\n this.selection();\r\n console.log(\"Best accuracy: \", this.getTheBest().accuracy)\r\n console.log(\"Worst accuracy: \", this.getTheWorst().accuracy) \r\n\r\n }\r\n\r\n /**Abstract methods.\r\n * Should be implemented by each variation of evolutionary algorithms\r\n */\r\n\r\n abstract crossover(): Individual;\r\n abstract mutation(offspring: Individual[]): void;\r\n abstract selection(): void;\r\n\r\n\r\n /**Helpers */\r\n\r\n getTheBest(): Individual{\r\n let index_best: number=0;\r\n let best=0;\r\n\r\n this.population.forEach((elem: any, index: number)=>{\r\n\r\n if(elem.accuracy>best){\r\n best=elem.accuracy;\r\n index_best=index\r\n }\r\n \r\n })\r\n\r\n return this.population[index_best];\r\n }\r\n\r\n\r\n getTheWorst(): Individual{\r\n let index_worst: number=0;\r\n let worst=1;\r\n\r\n this.population.forEach((elem: any, index: number)=>{\r\n\r\n if(elem.accuracy<worst){\r\n worst=elem.accuracy;\r\n index_worst=index\r\n }\r\n \r\n })\r\n\r\n return this.population[index_worst];\r\n }\r\n\r\n /**\r\n * Selecting individuals by elitism\r\n */\r\n select_parents_by_rollet_wheels_v2(selection_number=2): Individual[]{\r\n\r\n // console.log(\"Selecting parents by rollet wheels...\");\r\n \r\n const share: any=[];\r\n \r\n let total: any=0;\r\n \r\n // console.log(\"Population length...\", this.population.length);\r\n \r\n //This will create an overall accuracy\r\n this.population.forEach((elem)=>total+=elem.accuracy);\r\n \r\n let pointer=0;\r\n \r\n this.population.forEach((elem:any, index)=>{\r\n \r\n // console.log(\"Accuracy...\", elem.accuracy);\r\n \r\n share.push(\r\n {\r\n index: index,\r\n share: elem.accuracy/total,\r\n min: pointer,\r\n max: pointer + (elem.accuracy/total)\r\n })\r\n \r\n pointer+=elem.accuracy/total;\r\n });\r\n \r\n // console.log(\"Shares: \", share);\r\n \r\n const aux_selection: any =[];\r\n \r\n //Selecting two individuals using roulette wheels\r\n let counter=0;\r\n\r\n const indexes_aux: number[]=[];\r\n\r\n while(counter<selection_number){\r\n \r\n //Random pointer, used to randomly select an individual\r\n const aux_index= Math.random();\r\n \r\n share.forEach((elem: any)=>{\r\n \r\n if((elem.min<aux_index)&&(elem.max>aux_index)){\r\n \r\n const aux: Individual = {individual: new TeachableMobileNet(), accuracy: this.population[elem.index].accuracy }\r\n \r\n // console.log(\"Individual just created (weigth): \", aux.individual.getHead().layers[0].getWeights()[0].dataSync());\r\n \r\n // console.log(\"Individual original: \", this.population[elem.index].individual.getHead().layers[0].getWeights()[0].dataSync());\r\n // // Original Recipient\r\n // this.copyModel(this.population[elem.index].individual.getHead(),aux.individual.getHead())\r\n\r\n // this.population[elem.index].individual.getHead().dispose();\r\n \r\n // console.log(\"Individual just created (weigtht, copied): \", aux.individual.getHead().layers[0].getWeights()[0].dataSync());\r\n \r\n\r\n counter++;\r\n aux_selection.push(this.population[elem.index]);\r\n\r\n // indexes_aux.push(elem.index)\r\n }\r\n })\r\n }\r\n\r\n // this.population.forEach((elem, index)=>{\r\n // if(!indexes_aux.includes(index)){\r\n // console.log(\"Disposed...\")\r\n // elem.individual.getHead().dispose();\r\n // }\r\n \r\n // })\r\n\r\n // this.population=[];\r\n\r\n return aux_selection;\r\n }\r\n \r\n /**\r\n * Selecting individuals by elitism\r\n */\r\n select_parents_by_rollet_wheels(selection_number=2): Individual[]{\r\n\r\n // console.log\r\n // (\"Selecting parents by rollet wheels...\");\r\n\r\n const share: any=[];\r\n\r\n let total: any=0;\r\n \r\n // console.log(\"Population length...\", this.population.length);\r\n\r\n //This will create an overall accuracy\r\n this.population.forEach((elem)=>total+=elem.accuracy);\r\n\r\n let pointer=0;\r\n\r\n this.population.forEach((elem:any, index)=>{\r\n\r\n // console.log(\"Accuracy...\", elem.accuracy);\r\n\r\n share.push(\r\n {\r\n index: index,\r\n share: elem.accuracy/total,\r\n min: pointer,\r\n max: pointer + (elem.accuracy/total)\r\n })\r\n\r\n pointer+=elem.accuracy/total;\r\n });\r\n\r\n // console.log(\"Shares: \", share);\r\n\r\n const aux_selection: any =[];\r\n\r\n //Selecting two individuals using roulette wheels\r\n let counter=0;\r\n while(counter<selection_number){\r\n \r\n //Random pointer, used to randomly select an individual\r\n const aux_index= Math.random();\r\n\r\n share.forEach((elem: any)=>{\r\n\r\n if((elem.min<aux_index)&&(elem.max>aux_index)){\r\n counter++;\r\n aux_selection.push(this.population[elem.index]);\r\n }\r\n })\r\n }\r\n return aux_selection;\r\n }\r\n\r\n/**\r\n * This function will make a copy of a model on the weight level\r\n * This is an attempt to avoid influencing the new model when the old one\r\n * is eliminated. \r\n * \r\n * @param originalModel - the model to be copied \r\n * @param recipient - the new model\r\n */\r\nasync copyModel (originalModel: tf.LayersModel, recipient: tf.LayersModel) {\r\n\r\n originalModel.layers.forEach((layer: any, index: any)=>{\r\n recipient.layers[index].setWeights(layer.getWeights())\r\n })\r\n} \r\n\r\n}\r\n","import { NeuroEvolution } from \"./neuro-evolution\";\r\nimport {TeachableMobileNet} from \"../models/teachable-evolution\"\r\nimport * as tf from '@tensorflow/tfjs';\r\n\r\n/**\r\n * Each individual of the population will be made of \r\n * an array, correspodent to the neural network weights and\r\n * an evaluation, its respective accuracy on the dataset given.\r\n * \r\n */\r\ninterface Individual {\r\n individual: TeachableMobileNet,\r\n accuracy?: number\r\n}\r\n\r\n\r\nexport class GeneticAlgorithm extends NeuroEvolution { \r\n \r\n \r\n\r\n /**\r\n * Implementatin abstract methods\r\n */\r\n\r\n override crossover(): Individual {\r\n // console.log(\"Applying crossover on Genetic Algorithms...\")\r\n\r\n const selected = this.select_parents_by_rollet_wheels();\r\n\r\n const individual_1 = selected[0];\r\n const individual_2 = selected[1];\r\n\r\n // console.log(\"Individual 1: \")\r\n // individual_1.individual.getHead().summary();\r\n\r\n let individual_3: Individual= {individual: new TeachableMobileNet};\r\n\r\n const alfa = Math.random();\r\n\r\n individual_3.individual.getHead().layers.forEach((layer, index)=>{\r\n individual_3.individual.getHead().layers[index].setWeights(\r\n individual_1.individual.getHead().layers[index].getWeights()\r\n .map((elem: any, index_2: any)=> elem.mul(alfa)\r\n .add(individual_2.individual.getHead().layers[index]\r\n .getWeights()[index_2]\r\n .mul(1 - alfa)\r\n )))\r\n })\r\n\r\n // this.population.push(individual_3);\r\n // console.log(\"Population: \", this.population.length); \r\n \r\n return individual_3; \r\n \r\n }//end of crossover\r\n\r\n override mutation(offspring: Individual[]): void {\r\n\r\n const multation_rate=1;\r\n\r\n offspring.forEach((elem)=>{\r\n elem.individual.getHead().setWeights(\r\n elem.individual.getHead().getWeights().map((elem_2)=> { \r\n return elem_2.add(elem_2.mul(multation_rate*Math.random())) \r\n })\r\n );\r\n })\r\n }\r\n\r\n override selection(): void {\r\n\r\n const selected_individuals= this.select_parents_by_rollet_wheels(this.population_size);\r\n\r\n // const selected_individuals_copy: any=[];\r\n\r\n // selected_individuals.forEach(async (elem)=>{\r\n\r\n // const aux: Individual= {individual: new TeachableMobileNet()};\r\n\r\n // // await this.copyModel(elem.individual.getHead(), aux.individual.getHead());\r\n\r\n // // aux.individual.getHead().summary();\r\n\r\n // selected_individuals_copy.push({individual: aux, accuracy: elem.accuracy});\r\n // });\r\n\r\n \r\n // console.log(\"Memory before cleaning: \", tf.memory().numBytes);\r\n \r\n //Cleaning memory\r\n // this.population.forEach((elem)=> elem.individual.getHead().dispose())\r\n // this.population=[];\r\n\r\n //The best will enter on the population by elitism\r\n const best= this.getTheBest();\r\n\r\n this.population=[];\r\n\r\n this.population=selected_individuals;\r\n\r\n //Adding one extra individual by elitism \r\n // this.population.push(best);\r\n\r\n console.log(\"Best accuracy (elitism): \", best.accuracy);\r\n \r\n \r\n // console.log(\"Current population length: \", this.population.length);\r\n // console.log(\"Current population: \", this.population);\r\n\r\n\r\n // console.log(\"After selection: \", this.population[0])\r\n // console.log(\"Memory before cleaning: \", tf.memory().numBytes);\r\n }\r\n}\r\n","/*\r\n * Public API Surface of tfjs-evolution\r\n */\r\n\r\nexport * from './lib/tfjs-evolution.service';\r\nexport * from './lib/tfjs-evolution.component';\r\n\r\nexport * from './lib/components/display-panel/display-panel.component';\r\n\r\nexport * from './lib/models/teachable-evolution';\r\n\r\nexport * from './lib/Classes/genetic-algorithm';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { NeuroEvolution } from "./neuro-evolution";
2
+ import { TeachableMobileNet } from "../models/teachable-evolution";
3
+ /**
4
+ * Each individual of the population will be made of
5
+ * an array, correspodent to the neural network weights and
6
+ * an evaluation, its respective accuracy on the dataset given.
7
+ *
8
+ */
9
+ interface Individual {
10
+ individual: TeachableMobileNet;
11
+ accuracy?: number;
12
+ }
13
+ export declare class GeneticAlgorithm extends NeuroEvolution {
14
+ /**
15
+ * Implementatin abstract methods
16
+ */
17
+ crossover(): Individual;
18
+ mutation(offspring: Individual[]): void;
19
+ selection(): void;
20
+ }
21
+ export {};
@@ -0,0 +1,64 @@
1
+ import { TeachableMobileNet } from "../models/teachable-evolution";
2
+ import * as tf from '@tensorflow/tfjs';
3
+ /**
4
+ * Each individual of the population will be made of
5
+ * an array, correspodent to the neural network weights and
6
+ * an evaluation, its respective accuracy on the dataset given.
7
+ *
8
+ */
9
+ interface Individual {
10
+ individual: TeachableMobileNet;
11
+ accuracy?: number;
12
+ }
13
+ export declare abstract class NeuroEvolution {
14
+ /**
15
+ This is the population. I have decided to create a population of just weights.
16
+ I had to change my mind. Working with weights is tricky.
17
+ I have decided to sacrifice memory to make my life easiser.
18
+ Tensors has their inner methods, it helps on the operators.
19
+ I have to pay attention to memory manegement.
20
+ Working with memory in tensors is tricky.
21
+ */
22
+ population: Individual[];
23
+ private _population_size;
24
+ /**Setters and Getters */
25
+ set population_size(population_size: number);
26
+ get population_size(): number;
27
+ /**
28
+ * Methods with implementation
29
+ */
30
+ evaluate(): Promise<void>;
31
+ start_population(): void;
32
+ apply_evolution(iteration: number): Promise<void>;
33
+ /**
34
+ * This method will apply the evolution
35
+ */
36
+ evolution(): Promise<void>;
37
+ /**Abstract methods.
38
+ * Should be implemented by each variation of evolutionary algorithms
39
+ */
40
+ abstract crossover(): Individual;
41
+ abstract mutation(offspring: Individual[]): void;
42
+ abstract selection(): void;
43
+ /**Helpers */
44
+ getTheBest(): Individual;
45
+ getTheWorst(): Individual;
46
+ /**
47
+ * Selecting individuals by elitism
48
+ */
49
+ select_parents_by_rollet_wheels_v2(selection_number?: number): Individual[];
50
+ /**
51
+ * Selecting individuals by elitism
52
+ */
53
+ select_parents_by_rollet_wheels(selection_number?: number): Individual[];
54
+ /**
55
+ * This function will make a copy of a model on the weight level
56
+ * This is an attempt to avoid influencing the new model when the old one
57
+ * is eliminated.
58
+ *
59
+ * @param originalModel - the model to be copied
60
+ * @param recipient - the new model
61
+ */
62
+ copyModel(originalModel: tf.LayersModel, recipient: tf.LayersModel): Promise<void>;
63
+ }
64
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tfjs-evolution",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "This is an experimentation with evolutionary computing applied to neural networks using TensorFlow.js",
5
5
  "author": "Jorge Guerra Pires",
6
6
  "license": "MIT",
package/public-api.d.ts CHANGED
@@ -2,3 +2,4 @@ export * from './lib/tfjs-evolution.service';
2
2
  export * from './lib/tfjs-evolution.component';
3
3
  export * from './lib/components/display-panel/display-panel.component';
4
4
  export * from './lib/models/teachable-evolution';
5
+ export * from './lib/Classes/genetic-algorithm';