`Genome::process` first implementation with a single `output` + must add 2 layers to have the last one as the `output`
This commit is contained in:
parent
20382821ca
commit
db41a36af4
|
@ -16,7 +16,7 @@
|
||||||
**** LOCAL ATTRIBUTES ****
|
**** LOCAL ATTRIBUTES ****
|
||||||
************************************************/
|
************************************************/
|
||||||
public $layers; // Number of layers
|
public $layers; // Number of layers
|
||||||
public $neurons; // Neurons of the genome
|
public $neurons; // Number of neurons per layer
|
||||||
public $synapses; // Synapses between neurons
|
public $synapses; // Synapses between neurons
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,14 +78,12 @@
|
||||||
// set layers
|
// set layers
|
||||||
$this->layers = $layers;
|
$this->layers = $layers;
|
||||||
|
|
||||||
/* (2) Creating random neurons */
|
/* (2) Store number of neurons */
|
||||||
$this->neurons = [];
|
$this->neurons = $neurons;
|
||||||
for( $i = 0, $l = $neurons*$layers ; $i < $l ; $i++ )
|
|
||||||
$this->neurons[$i] = rand(self::MIN, self::MAX) / self::MAX;
|
|
||||||
|
|
||||||
/* (3) Creating random synapses */
|
/* (3) Creating random synapses */
|
||||||
$this->synapses = [];
|
$this->synapses = [];
|
||||||
for( $i = 0, $l = pow($neurons, $layers) ; $i < $l ; $i++ )
|
for( $i = 0, $l = $layers*pow($neurons,2) ; $i < $l ; $i++ )
|
||||||
$this->synapses[$i] = rand(self::MIN, self::MAX) / self::MAX;
|
$this->synapses[$i] = rand(self::MIN, self::MAX) / self::MAX;
|
||||||
|
|
||||||
// Success status
|
// Success status
|
||||||
|
@ -106,7 +104,7 @@
|
||||||
|
|
||||||
/* (2) Clones into this Genome */
|
/* (2) Clones into this Genome */
|
||||||
$this->layers = $parent->layers;
|
$this->layers = $parent->layers;
|
||||||
$this->neurons = array_slice($parent->neurons, 0);
|
$this->neurons = $parent->neurons;
|
||||||
$this->synapses = array_slice($parent->synapses, 0);
|
$this->synapses = array_slice($parent->synapses, 0);
|
||||||
|
|
||||||
// Success state
|
// Success state
|
||||||
|
@ -127,21 +125,18 @@
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* (2) Checks number of layers+neurons (same species) */
|
/* (2) Checks number of layers+neurons (same species) */
|
||||||
if( $father->layers !== $mother->layers || count($father->neurons) !== count($mother->neurons) )
|
if( $father->layers !== $mother->layers || $father->neurons !== $mother->neurons )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* (3) Set layer count */
|
/* (3) Set layer count */
|
||||||
$this->layers = $father->layers;
|
$this->layers = $father->layers;
|
||||||
|
|
||||||
/* (4) Do random crossover for neurons */
|
/* (4) Set neurons number */
|
||||||
$this->neurons = [];
|
$this->neurons = $father->neurons;
|
||||||
for( $i = 0, $l = count($father->neurons) ; $i < $l ; $i++ )
|
|
||||||
if( !!rand(0,1) ) $this->neurons[$i] = $father->neurons[$i];
|
|
||||||
else $this->neurons[$i] = $mother->neurons[$i];
|
|
||||||
|
|
||||||
/* (5) Do random crossover for synapses */
|
/* (5) Do random crossover for synapses */
|
||||||
$this->synapses = [];
|
$this->synapses = [];
|
||||||
for( $i = 0, $l = pow(count($this->neurons)/$this->layers, $this->layers) ; $i < $l ; $i++ )
|
for( $i = 0, $l = $this->layers*pow($this->neurons, 2) ; $i < $l ; $i++ )
|
||||||
if( !!rand(0,1) ) $this->synapses[$i] = $father->synapses[$i];
|
if( !!rand(0,1) ) $this->synapses[$i] = $father->synapses[$i];
|
||||||
else $this->synapses[$i] = $mother->synapses[$i];
|
else $this->synapses[$i] = $mother->synapses[$i];
|
||||||
|
|
||||||
|
@ -195,6 +190,64 @@
|
||||||
$this->synapses[$iSynapses[$i]] = rand(self::MIN, self::MAX) / self::MAX;
|
$this->synapses[$iSynapses[$i]] = rand(self::MIN, self::MAX) / self::MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* CALCULATES THE OUTPUT OF THE GENOME
|
||||||
|
*
|
||||||
|
* @input<Array> Input for which we want fitness
|
||||||
|
*
|
||||||
|
* @return output<double> Output calculated with this input
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function process($input=null){
|
||||||
|
/* (1) Checks @input argument */
|
||||||
|
if( !is_array($input) || count($input) !== $this->neurons )
|
||||||
|
throw new \Error('Invalid @input for Genome\'s output calculation.');
|
||||||
|
|
||||||
|
|
||||||
|
/* [1] Set temporary calculation data
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) Set temporary neurons data */
|
||||||
|
$neurons = array_merge( $input, array_fill(0, $this->neurons*$this->layers, 0) );
|
||||||
|
|
||||||
|
/* (2) Set temporary synapses data */
|
||||||
|
$synapses = $this->synapses;
|
||||||
|
|
||||||
|
|
||||||
|
/* [2] Calculates output
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) For each hidden layer
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
for( $l = 1 ; $l < $this->layers+1 ; $l++ ){
|
||||||
|
|
||||||
|
/* (2) For each neuron of this layer
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
for( $n = $l*$this->neurons, $nl = ($l+1)*$this->neurons ; $n < $nl ; $n++ ){
|
||||||
|
|
||||||
|
$neurons[$n] = 0;
|
||||||
|
|
||||||
|
/* (3) For each synapse between current neuron and last layer
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
for( $s = ($l-1)*pow($this->neurons,2), $sl = $l*pow($this->neurons,2) ; $s < $sl ; $s++ )
|
||||||
|
$neurons[$n] += $synapses[$s] * $neurons[ floor($s/$this->neurons) ];
|
||||||
|
// newNeuron += synapse*lastLayerNeuron
|
||||||
|
|
||||||
|
/* Divide the sum to make a mean */
|
||||||
|
$neurons[$n] /= $this->neurons;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (4) Calculates single output
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
$output = 0;
|
||||||
|
|
||||||
|
for( $n = ($this->layers-1)*$this->neurons, $nl = $this->layers*$this->neurons ; $n < $nl ; $n++ )
|
||||||
|
$output += $neurons[$n];
|
||||||
|
|
||||||
|
|
||||||
|
/* [3] Returns output
|
||||||
|
=========================================================*/
|
||||||
|
return $output / $this->neurons;
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************
|
/************************************************
|
||||||
**** Serialization ****
|
**** Serialization ****
|
||||||
|
@ -210,12 +263,9 @@
|
||||||
$csv = '';
|
$csv = '';
|
||||||
|
|
||||||
/* (2) Adds global attributes */
|
/* (2) Adds global attributes */
|
||||||
$csv .= $this->layers .';';
|
$csv .= $this->layers .','. $this->neurons .';';
|
||||||
|
|
||||||
/* (3) Adds neurons data */
|
/* (3) Adds synapses data */
|
||||||
$csv .= implode(',', $this->neurons) .';';
|
|
||||||
|
|
||||||
/* (4) Adds synapses data */
|
|
||||||
$csv .= implode(',', $this->synapses);
|
$csv .= implode(',', $this->synapses);
|
||||||
|
|
||||||
return $csv;
|
return $csv;
|
||||||
|
@ -236,16 +286,16 @@
|
||||||
throw new \Error('Format error during Genome unserialization.');
|
throw new \Error('Format error during Genome unserialization.');
|
||||||
|
|
||||||
/* (2) Get global attributes */
|
/* (2) Get global attributes */
|
||||||
if( !is_numeric($segments[0]) )
|
$global = explode(',', $segments[0]);
|
||||||
|
|
||||||
|
if( count($global) < 2 )
|
||||||
throw new \Error('Format error during Genome unserialization.');
|
throw new \Error('Format error during Genome unserialization.');
|
||||||
|
|
||||||
$this->layers = intval($segments[0]);
|
$this->layers = intval($global[0]);
|
||||||
|
$this->layers = intval($global[1]);
|
||||||
|
|
||||||
/* (3) Get neurons values */
|
/* (3) Get synapses values */
|
||||||
$this->neurons = explode(',', $segments[1]);
|
$this->synapses = explode(',', $segments[1]);
|
||||||
|
|
||||||
/* (4) Get synapses values */
|
|
||||||
$this->synapses = explode(',', $segments[2]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -343,9 +343,42 @@
|
||||||
|
|
||||||
/* [2] Creates the neural network
|
/* [2] Creates the neural network
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
|
// best of last generation
|
||||||
|
$best = new Genome($this->numHid, $this->numNeu);
|
||||||
|
|
||||||
|
|
||||||
|
/* (1) For each generation
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
for( $this->gnr = 0 ; $this->gnr < $this->maxGnr ; $this->gnr++ ){
|
||||||
|
|
||||||
|
/* (1) Initializes genome list for current generation */
|
||||||
|
$this->gnms = [];
|
||||||
|
|
||||||
|
/* (2) For each genome of the generation */
|
||||||
|
for( $this->gnm = 0 ; $this->gnm < $this->maxGnm ; $this->gnm++ ){
|
||||||
|
|
||||||
|
// {2.1} First Generation -> random genomes //
|
||||||
|
if( $this->gnr === 0 )
|
||||||
|
$this->gnms[$this->gnm] = new Genome($this->numHid, $this->numNeu);
|
||||||
|
|
||||||
|
// {2.2} Others generations -> crossover + mutation //
|
||||||
|
else{
|
||||||
|
$this->gnms[$this->gnm] = new Genome($best['father'], $best['mother']);
|
||||||
|
$this->gnms[$this->gnm]->mutation($this->mutThr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (3) Calculate fitness */
|
||||||
|
// ... blablabla
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Select best genomes based on fitness
|
||||||
|
$best = null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/************************************************
|
/************************************************
|
||||||
**** Serialization Methods ****
|
**** Serialization Methods ****
|
||||||
************************************************/
|
************************************************/
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
0,0,0;0
|
|
||||||
0,0,1;1
|
|
||||||
0,1,0;0
|
|
||||||
0,1,1;1
|
|
||||||
1,0,0;0
|
|
||||||
1,0,1;1
|
|
||||||
1,1,0;1
|
|
||||||
1,1,1;0
|
|
|
@ -1 +0,0 @@
|
||||||
{"maxGnr":50,"maxGnm":100,"kptGnm":2,"mutThr":0.3,"fitEnd":1,"numHid":2,"numNeu":3,"max":{"input":[1,1,1],"output":[1]},"storage":[{"filename":"\/home\/xdrm-brackets\/Desktop\/git.xdrm.io\/neural-network.php\/build\/neuralnetwork\/storage\/A\/B\/C\/test.nn","exists":true},{"filename":"\/home\/xdrm-brackets\/Desktop\/git.xdrm.io\/neural-network.php\/build\/neuralnetwork\/storage\/A\/B\/C\/test.ex","exists":true},{"filename":"\/home\/xdrm-brackets\/Desktop\/git.xdrm.io\/neural-network.php\/build\/neuralnetwork\/storage\/A\/B\/C\/test.ln","exists":true}]}
|
|
|
@ -1,8 +1,8 @@
|
||||||
0,0,0;0
|
0,0,0;0,0
|
||||||
0,0,1;1
|
0,0,1;0,1
|
||||||
0,1,0;0
|
0,1,0;0,1
|
||||||
0,1,1;1
|
0,1,1;0,1
|
||||||
1,0,0;0
|
1,0,0;0,0
|
||||||
1,0,1;1
|
1,0,1;0,1
|
||||||
1,1,0;1
|
1,1,0;1,1
|
||||||
1,1,1;0
|
1,1,1;1,1
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
0,0,0;0,0
|
||||||
|
0,0,1;0,1
|
||||||
|
0,1,0;0,1
|
||||||
|
0,1,1;0,1
|
||||||
|
1,0,0;0,0
|
||||||
|
1,0,1;0,1
|
||||||
|
1,1,0;1,1
|
||||||
|
1,1,1;1,1
|
|
@ -0,0 +1 @@
|
||||||
|
{"maxGnr":50,"maxGnm":100,"kptGnm":2,"mutThr":0.3,"fitEnd":1,"numHid":2,"numNeu":3,"max":{"input":[1,1,1],"output":[1,1]},"storage":[{"filename":"\/home\/xdrm-brackets\/Desktop\/git.xdrm.io\/neural-network.php\/build\/neuralnetwork\/storage\/test\/test1.nn","exists":false},{"filename":"\/home\/xdrm-brackets\/Desktop\/git.xdrm.io\/neural-network.php\/build\/neuralnetwork\/storage\/test\/test1.ex","exists":false},{"filename":"\/home\/xdrm-brackets\/Desktop\/git.xdrm.io\/neural-network.php\/build\/neuralnetwork\/storage\/test\/test1.ln","exists":false}]}
|
|
@ -10,7 +10,7 @@
|
||||||
if( false && 'test_creating_dataset' ){
|
if( false && 'test_creating_dataset' ){
|
||||||
|
|
||||||
function behaviour($abc){
|
function behaviour($abc){
|
||||||
return [($abc[0] & $abc[1]) ^ $abc[2]];
|
return [($abc[0] & $abc[1]), $abc[1] | $abc[2]];
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "Welcome to neural-network.php\n";
|
echo "Welcome to neural-network.php\n";
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
$nn = NeuralNetwork::create(50, 100);
|
$nn = NeuralNetwork::create(50, 100);
|
||||||
|
|
||||||
$nn->setMaxValues([1, 1, 1], [1]);
|
$nn->setMaxValues([1, 1, 1], [1, 1]);
|
||||||
$nn->setHiddenLayersCount(2);
|
$nn->setHiddenLayersCount(2);
|
||||||
$nn->setHiddenLayerNeuronsCount(3);
|
$nn->setHiddenLayerNeuronsCount(3);
|
||||||
|
|
||||||
|
@ -31,17 +31,17 @@
|
||||||
$d = [1, 1, 0]; $nn->addSample($d, behaviour($d));
|
$d = [1, 1, 0]; $nn->addSample($d, behaviour($d));
|
||||||
$d = [1, 1, 1]; $nn->addSample($d, behaviour($d));
|
$d = [1, 1, 1]; $nn->addSample($d, behaviour($d));
|
||||||
|
|
||||||
$nn->store('A/B/C/test', true);
|
$nn->store('test/test1', true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( false && 'load_neural_network' ){
|
if( false && 'load_neural_network' ){
|
||||||
|
|
||||||
$nn = NeuralNetwork::load('A/B/C/test');
|
$nn = NeuralNetwork::load('test/test1');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( true && 'test_genomes' ){
|
if( false && 'test_genomes' ){
|
||||||
/* (1) Basic Creation */
|
/* (1) Basic Creation */
|
||||||
$a = new Genome(2, 3); // 2 layers of 3 neurons each -> randomly filled
|
$a = new Genome(2, 3); // 2 layers of 3 neurons each -> randomly filled
|
||||||
|
|
||||||
|
@ -61,9 +61,17 @@
|
||||||
$c = new Genome($a, $b); // @c is a randomly-done mix of @a and @b
|
$c = new Genome($a, $b); // @c is a randomly-done mix of @a and @b
|
||||||
echo "crossover : A+B -> C\n";
|
echo "crossover : A+B -> C\n";
|
||||||
echo "C : ".$c->serialize()."\n";
|
echo "C : ".$c->serialize()."\n";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( true ){
|
||||||
|
|
||||||
|
$g = new Genome(2, 3);
|
||||||
|
|
||||||
|
echo $g->process([1, 1, 0]);
|
||||||
|
}
|
||||||
|
|
||||||
// REWRITE TEST
|
// REWRITE TEST
|
||||||
// for( $a = 0, $al = 50 ; $a < $al ; $a++ )
|
// for( $a = 0, $al = 50 ; $a < $al ; $a++ )
|
||||||
// for( $b = 0, $bl = 20 ; $b < $bl ; $b++ ){
|
// for( $b = 0, $bl = 20 ; $b < $bl ; $b++ ){
|
||||||
|
|
Loading…
Reference in New Issue