diff --git a/build/neuralnetwork/core/Genome.php b/build/neuralnetwork/core/Genome.php index c708762..bd9318c 100644 --- a/build/neuralnetwork/core/Genome.php +++ b/build/neuralnetwork/core/Genome.php @@ -227,7 +227,7 @@ */ public function mutation($threshold=1){ /* (1) Checks @threshold argument */ - if( floatval($threshold) !== $threshold || $threshold < 0 || $threshold > 1 ) + if( !is_numeric($threshold) || $threshold < 0 || $threshold > 1 ) throw new \Exception('Invalid threshold for Genome mutation.'); /* (2) Calculates how many neurons/synapses to mutate */ diff --git a/build/neuralnetwork/core/NeuralNetworkCore.php b/build/neuralnetwork/core/NeuralNetworkCore.php index 65ab56e..47132be 100644 --- a/build/neuralnetwork/core/NeuralNetworkCore.php +++ b/build/neuralnetwork/core/NeuralNetworkCore.php @@ -25,11 +25,11 @@ /************************************************ **** LOCAL ATTRIBUTES **** ************************************************/ - public $maxFit; // Maximum fitness of the previous generation - public $minFit; // Minimum fitness of the current generation - public $gnr; // Current generation index - public $gnm; // Current genome index - private $genome; // Current genome instance + private $maxFit; // Maximum fitness of the previous generation + private $fitnesses; // The fitnesses of the current generation's genomes + public $gnr; // Current generation index + public $gnm; // Current genome index + private $genome; // Current genome instance @@ -83,9 +83,6 @@ ], 'gn' => [ 'filename' => $absolute_path.'.gn', // will contain genomes of the generation 'exists' => is_file($absolute_path.'.gn') - ], 'ft' => [ - 'filename' => $absolute_path.'.ft', // will contain genomes' fitness - 'exists' => is_file($absolute_path.'.ft') ], 'ln' => [ 'filename' => $absolute_path.'.ln', // will contain learnt best genomes 'exists' => is_file($absolute_path.'.ln') @@ -370,10 +367,10 @@ /* (1) Initializes data & storage */ $this->gnr = 0; $this->gnm = 0; - $this->minFit = null; $this->maxFit = null; FileManager::write($this->storage['gn']['filename'], ''); - FileManager::write($this->storage['ft']['filename'], ''); + // FileManager::write($this->storage['ft']['filename'], ''); + $this->fitnesses = []; /* (2) Stores random genomes to storage */ for( $g = 0 ; $g < $this->maxGnm ; $g++ ){ @@ -399,10 +396,10 @@ /* (1) Initializes data & storage */ $this->gnr = 0; $this->gnm = 0; - $this->minFit = null; $this->maxFit = null; FileManager::write($this->storage['gn']['filename'], ''); - FileManager::write($this->storage['ft']['filename'], ''); + // FileManager::write($this->storage['ft']['filename'], ''); + $this->fitnesses = []; /* (2.1) Fetch learnt best genomes */ $loadedGenomes = [ @@ -481,7 +478,11 @@ throw new \Exception('The learning routine is closed.'); /* (1) Stores fitness */ - FileManager::append($this->storage['ft']['filename'], strval($this->genome->getFitness()) ); + $fit = $this->genome->getFitness(); + + if( !$this->antReg || is_null($this->maxFit) || $fit > $this->maxFit ) + $this->fitnesses[$this->gnm] = $fit; + // FileManager::append($this->storage['ft']['filename'], strval($this->genome->getFitness()) ); /* (1) Iterates if possible @@ -499,12 +500,12 @@ $this->gnm = 0; /* (2) Fetch the whole generation fitness values */ - $ftRead = FileManager::read($this->storage['ft']['filename']); - $fitnesses = explode("\n", trim($ftRead) ); + // $ftRead = FileManager::read($this->storage['ft']['filename']); + // $this->fitnesses = explode("\n", trim($ftRead) ); /* (3) Checks if fitnessEnd is reached */ - if( min($fitnesses) == $this->fitEnd ){ + if( count($this->fitnesses) > 0 && max($this->fitnesses) == $this->fitEnd ){ /* (1) Get the 2 best genomes */ $best = FileManager::readline($this->storage['gn']['filename'], 0); @@ -522,13 +523,11 @@ /* (4) Checks if theres a fitness maximum evolution */ - $fitnessEvolution = !$this->antReg || is_null($this->maxFit) && is_null($this->minFit) || max($fitnesses) > $this->maxFit; + // Extract @mother & @father indexes // + $iBest = $this->bestFitnesses($this->fitnesses); /* (4.1) If evolution -> choose best + cross-over ... */ - if( $fitnessEvolution ){ - - // {1} Extract @mother & @father indexes // - $iBest = $this->bestFitnesses($fitnesses); + if( !is_null($iBest[0]) ){ // {2} Extract best 2 genomes // $sFather = FileManager::readline($this->storage['gn']['filename'], $iBest[0]); @@ -541,8 +540,7 @@ $mother = new Genome(2, 2, 2, 2); $mother->unserialize($sMother); - $this->maxFit = max($fitnesses); - $this->minFit = min($fitnesses); + $this->maxFit = max($this->fitnesses); $this->storeLearntBest(); @@ -566,7 +564,7 @@ /* (7) Create new generation */ FileManager::write($this->storage['gn']['filename'], ''); - FileManager::write($this->storage['ft']['filename'], ''); + // FileManager::write($this->storage['ft']['filename'], ''); for( $g = 0 ; $g < $this->maxGnm ; $g++ ){ @@ -587,6 +585,8 @@ } + $this->fitnesses = []; + /* (3) If end of process ---------------------------------------------------------*/ }else{ @@ -611,7 +611,6 @@ /* (2) Stores data to learnt data */ FileManager::write($this->storage['ln']['filename'], $best); } - // TODO: Manage @mutThr decreasing to be more precise /************************************************ **** Utility **** @@ -646,8 +645,8 @@ $c++; } - /* (3) Anti-regression, if @mother < @father only use @father*/ - if( $fitnesses[$iMother] < $fitnesses[$iFather] ) + /* (3) If mother not found copy father */ + if( is_null($iMother) ) $iMother = $iFather; return [ $iFather, $iMother ]; diff --git a/config/neural-network.json b/config/neural-network.json index af81521..edea878 100644 --- a/config/neural-network.json +++ b/config/neural-network.json @@ -2,7 +2,7 @@ "storage_parent": "/build/neuralnetwork/storage", "default": { - "mutation_threshold": 0.5, + "mutation_threshold": 1, "fitness_end": 1, "storage": "_buffer", "hidden_layers": 2, diff --git a/public/main.php b/public/main.php index c71d7b7..53ff6a6 100644 --- a/public/main.php +++ b/public/main.php @@ -12,7 +12,7 @@ - $train = true; + $train = $argc > 1 && $argv[1] == 'train'; $guess = !$train; if( $train && 'learning_process' ){ @@ -34,13 +34,13 @@ =========================================================*/ }catch(\Exception $e){ - $nn = NeuralNetwork::create(50, 500); + $nn = NeuralNetwork::create(50, 100); - $nn->setHiddenLayersCount(3); // 3 Hidden layers - $nn->setHiddenLayerNeuronsCount(4); // Composed with 3 neurons each + $nn->setHiddenLayersCount(5); // 3 Hidden layers + $nn->setHiddenLayerNeuronsCount(3); // Composed with 3 neurons each $nn->setInputLayerCount(3); // 3 inputs $nn->setOutputLayerCount(1); // 1 output - $nn->setMutationThreshold(0.3); // mutation 30% each generation + $nn->setMutationThreshold(0.5); // mutation 30% each generation $nn->setFitnessEnd(-1.5); // Algorithm is done when fitness reaches 0 $nn->setAntiRegression(true); // That repeats a generation while its fitness is lower than the previous one @@ -71,12 +71,11 @@ /* [2] Initializing learning routine =========================================================*/ - $defaultMT = 0.3; $fitness = 0; $max_fit = 0; $nn->loadLearningRoutine(function($input, $output){ global $fitness; - $fitness -= abs($output[0] - behaviourtest2($input)[0]); + $fitness -= abs(round($output[0]) - behaviourtest2($input)[0]); }); echo "$part. Learning routine initialized.\n"; $part++; @@ -94,7 +93,6 @@ $last_gnr = $nn->gnr; $max_fit = -1e9; - $min_fit = 100; /* (2) For each genome */ while( true ){ @@ -102,19 +100,18 @@ /* (2.1) Get current genome */ $g = $nn->getGenome(); - echo "\r[x] gnm ".($nn->gnm+1)."/500 on gnr ".($nn->gnr+1)."/50 - x".($gen_repeat+1)." - fit[$min_fit;$max_fit] "; + echo "\r[x] gnm ".($nn->gnm+1)."/100 on gnr ".($nn->gnr+1)."/50 - x".($gen_repeat+1)." - fit[$max_fit] "; /* (2.2) Train genome with random samples */ - for( $r = 0 ; $r < 100 ; $r++ ) - $g->train([rand(0,10), rand(0,10), rand(0,10)]); + for( $r = 0 ; $r < 500 ; $r++ ) + $g->train([rand(0,100), rand(0,100), rand(0,100)]); /* (2.3) Set fitness & go to next genome */ if( $fitness > $max_fit ) $max_fit = $fitness; - if( $fitness < $min_fit ) $min_fit = $fitness; $g->setFitness($fitness); - if( $nn->gnm >= 500-1 ) + if( $nn->gnm >= 100-1 ) break; $nn->nextGenome();