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