From fd9bcefed7cd3cee2b350af6609137e9433b0c38 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Wed, 26 Oct 2016 17:15:00 +0200 Subject: [PATCH] Created `Genome`'s `constructor` + finished `NeuralNetwork`'s `storage` and `attributes` management (+ serialization) + now it remains the hard & cool part -> genetic algorithm --- build/filemanager/core/FileManager.php | 70 +++-- build/neuralnetwork/core/Genome.php | 170 ++++++++++++ build/neuralnetwork/core/NeuralNetwork.php | 44 +--- .../neuralnetwork/core/NeuralNetworkCore.php | 249 ++++++++++++++++-- .../core/NeuralNetworkManager.php | 114 ++++++++ build/neuralnetwork/storage/A/B/C/test.ex | 8 + build/neuralnetwork/storage/A/B/C/test.ln | 0 build/neuralnetwork/storage/A/B/C/test.nn | 1 + build/neuralnetwork/storage/_buffer.ln | 0 config/neural-network.json | 4 +- public/main.php | 65 ++++- 11 files changed, 625 insertions(+), 100 deletions(-) create mode 100644 build/neuralnetwork/core/Genome.php create mode 100644 build/neuralnetwork/core/NeuralNetworkManager.php create mode 100644 build/neuralnetwork/storage/A/B/C/test.ex create mode 100644 build/neuralnetwork/storage/A/B/C/test.ln create mode 100644 build/neuralnetwork/storage/A/B/C/test.nn create mode 100644 build/neuralnetwork/storage/_buffer.ln diff --git a/build/filemanager/core/FileManager.php b/build/filemanager/core/FileManager.php index 1f99f4e..3ea4c7b 100644 --- a/build/filemanager/core/FileManager.php +++ b/build/filemanager/core/FileManager.php @@ -6,34 +6,49 @@ class FileManager{ + + /* CREATES A FILE WITH ITS NEEDED DIRECTORIES + * + * @path Path of the needed file + * + * @return created If the file has been created successfully + * + */ + public static function create($file){ + /* (0) Checks arguments */ + if( !is_string($file) || is_dir($file) ) + return false; + + /* (1) Creates file */ + try{ + fclose( fopen($file, 'w') ); + return true; + }catch(Exception $e){ return false; } + } + + /* READS FILE'S CONTENT * * @file File to read * */ public static function read($file){ - /* [1] Init driver - =========================================================*/ + /* (0) Checks arguments */ + if( !is_string($file) ) + throw new \Error('Wrong argument for read().'); + + /* (1) Initializing driver on file (read-flag) */ $driver = new \SplFileObject($file, 'r'); - - /* [2] Read lines - =========================================================*/ + /* (2) Read lines */ $read = ''; - /* (1) Reads lines */ $line = 0; while( $driver->current() ){ - $read .= "\n".$driver->current(); + $read .= $driver->current(); $driver->next(); } - - /* [3] Returns read content - =========================================================*/ - /* (2) Destroy driver */ - $driver = null; - /* (3) Returns result */ return $read; } @@ -44,19 +59,27 @@ * @file File to write to * @content Content to write * + * @return written Returns if the content have been written successfully + * + * @note: Creates file if it is possible with `file_put_contents()` + * */ public static function write($file, $content){ + /* (0) Checks arguments */ + if( !is_string($file) || !is_string($content) ) + return false; + /* (1) Erase file */ - file_put_contents($file, ''); + try{ + fclose( fopen($file, 'w') ); + }catch(Exception $e){ return false; } /* (2) Get driver (write-flag) */ $driver = new \SplFileObject($file, 'r+'); /* (3) Writes content */ - $driver->fwrite($content); + return !is_null( $driver->fwrite($content) ); - /* (4) Free driver */ - $driver = null; } @@ -65,16 +88,21 @@ * @file File to append content to * @content Content to append * + * @return append Returns if the content have been append successfully + * + * @note: If file doesn't exists, returns false + * */ public static function append($file, $content){ + /* (0) Checks arguments */ + if( !is_file($file) || !is_string($content) ) + return false; + /* (1) Get driver (append-flag) */ $driver = new \SplFileObject($file, 'a'); /* (2) append content */ - $driver->fwrite($content.PHP_EOL); - - /* (3) Free driver */ - $driver = null; + return !is_null( $driver->fwrite($content.PHP_EOL) ); } diff --git a/build/neuralnetwork/core/Genome.php b/build/neuralnetwork/core/Genome.php new file mode 100644 index 0000000..18667fa --- /dev/null +++ b/build/neuralnetwork/core/Genome.php @@ -0,0 +1,170 @@ + Number of layers to manage + * @neurons Number of neurons per layer + * + * -- CLONING -- + * @base Genome to clone to + * + * -- CROSS-OVER CREATION -- + * @father First parent + * @mother Second parent + * + * + */ + public function __construct(){ + /* (1) Get arguments */ + $argv = func_get_args(); + $argc = count($argv); + + + /* (2) If CrossoverCreation */ + if( $argc > 1 && $argv[0] instanceof Genome && $argv[1] instanceof Genome ) + $this->construct_crossover($argv[0], $argv[1]); + + /* (3) If RandomCreation */ + else if( $argc > 1 && abs(intval($argv[0])) === $argv[0] && abs(intval($argv[1])) === $argv[1] ) + $this->construct_new($argv[0], $argv[1]); + + /* (4) If InheritanceCreation (clone) */ + else if( $argc > 0 && $argv[0] instanceof Genome ) + $this->construct_inheritance($argv[0]); + + /* (5) If no match */ + else + throw new \Error('Invalid Genome constructor\'s arguments.'); + } + + /* BUILDS A Genome RANDOMLY WITH PARAMETERS + * + * @layers The number of hidden layers to manage + * @neurons The number neurons per layer + * + * @return created If Genome has been successfully created + * + */ + private function construct_new($layers=-1, $neurons=-1){ + /* (1) Checks parameters */ + if( abs(intval($layers)) !== $layers || abs(intval($neurons)) !== $neurons ) + return false; + + // set layers + $this->layers = $layers; + + /* (2) Creating random neurons */ + $this->neurons = []; + for( $i = 0 ; $i < $neurons ; $i++ ) + $this->neurons[$i] = rand(self::MIN, self::MAX) / self::MAX; + + /* (3) Creating random synapses */ + $this->synapses = []; + for( $i = 0, $l = pow($neurons, $layers) ; $i < $l ; $i++ ) + $this->synapses[$i] = rand(self::MIN, self::MAX) / self::MAX; + + // Success status + return true; + } + + /* BUILDS A Genome BASED ON A PARENT + * + * @parent Parent genome to clone into children + * + * @return created If cloned Genome has been created successfully + * + */ + private function construct_inheritance($parent=null){ + /* (1) Checks parent type */ + if( !($parent instanceof Genome) ) + return false; + + /* (2) Clones into this Genome */ + $this->layers = $parent->layers; + $this->neurons = $parent->neurons; + $this->synapses = $parent->synapses; + + // Success state + return true; + } + + /* BUILDS A Genome BASED ON TWO PARENTS + * + * @father First parent ($father) + * @mother Second parent ($mother) + * + * @return created If crossed-over Genome has been created successfully + * + */ + private function construct_crossover($father=null, $mother=null){ + /* (1) Checks parent type */ + if( !($father instanceof Genome) || !($mother instanceof Genome) ) + return false; + + /* (2) Checks number of layers+neurons (same species) */ + if( $father->layers !== $mother->layers || count($father->neurons) !== count($mother->neurons) ) + return false; + + /* (3) Do random crossover for neurons */ + $this->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]; + + /* (3) Creating random synapses */ + $this->synapses = []; + for( $i = 0, $l = pow(count($this->neurons), $this->layers) ; $i < $l ; $i++ ) + if( rand(0,1) ) $this->synapses[$i] = $father->synapses[$i]; + else $this->synapses[$i] = $mother->synapses[$i]; + + // Success state + return true; + } + + } + + + + + /************************************************ + **** USE CASE **** + ************************************************/ + $use_case = false; + if( $use_case ){ + + /* (1) Basic Creation */ + $a = new Genome(2, 3); // 2 layers of 3 neurons each -> randomly filled + + /* (2) Inheritance */ + $b = new Genome($a); // Clone of @a + + /* (3) Section Title */ + $b->mutation(0.3); // @b has now mutated with a threshold of 30% + + /* (4) Cross-over (father+mother) */ + $c = new Genome($a, $b); // @c is a randomly-done mix of @a and @b + + } + +?> diff --git a/build/neuralnetwork/core/NeuralNetwork.php b/build/neuralnetwork/core/NeuralNetwork.php index ae6cc62..370f669 100644 --- a/build/neuralnetwork/core/NeuralNetwork.php +++ b/build/neuralnetwork/core/NeuralNetwork.php @@ -3,39 +3,13 @@ namespace neuralnetwork\core; use neuralnetwork\core\NeuralNetworkCore; + use filemanager\core\FileManager; /************************************************ **** Neural Network's Facade **** ************************************************/ class NeuralNetwork{ - /* CHECKS AND STORES PATHS TO STORAGE FILES - * - * @path Path to storage - * - * @return files Array containing storage files' information - * @return error Returns NULL if error - * - */ - public static function setStorage($path){ - /* (1) Checks the path */ - if( !preg_match("/^(?P\/(?:[a-z0-9_-]+\/)*)(?P[a-z0-9_-]+)$/i", $path, $matches) ) - return null; - - /* (2) Checks file's existence and returns it */ - return [ - [ - 'filename' => $matches['path'].$matches['filename'] .'.nn', // will contain neural network data - 'exists' => is_file($matches['path'].$matches['filename'] .'.nn') - ], - [ - 'filename' => $matches['path'].$matches['filename'] .'.ex', // will contain samples - 'exists' => is_file($matches['path'].$matches['filename'] .'.ex') - ] - ]; - - } - /* CREATES A NEW NEURAL NETWORK * * @generations Maximum number of generations to process @@ -59,23 +33,19 @@ public static function load($storage=null){ /* (1) Checks argument */ - if( is_null($storage=self::setStorage($gnr_or_storage)) ) + if( is_null($storage=NeuralNetworkCore::getStorage($storage)) ) throw new Error('Wrong NeuralNetwork loader\'s argument.'); /* (2) If files doesn't exist, raise error */ - if( !$storage[0]['exists'] || !$storage[1]['exists'] ) + if( !$storage[0]['exists'] || !$storage[1]['exists'] || !$storage[2]['exists'] ) throw new Error('Loaded storage have file(s) missing.'); - /* (3) Parses files */ - $last_network = json_decode( FileManager::read($storage[0]['filename']), true); + /* (3) Unserialize last NeuralNetwork */ + $last_network = FileManager::read($storage[0]['filename']); /* (4) Creates and fill instance */ - $instance = new NeuralNetworkCore($last_network['generations'], $last_network['genomes']); - $instance->setStorage($gnr_or_storage); - $instance->setFitnessEnd($last_network['fitness_end']); - $instance->setKeptGenomes($last_network['kept_genomes']); - $instance->setMutationThreshold($last_network['mutation_threshold']); - $instance->setMaxValues($last_network['max_values']); + $instance = new NeuralNetworkCore(0, 0); + $instance->unserialize($last_network); /* (5) Returns instance */ return $instance; diff --git a/build/neuralnetwork/core/NeuralNetworkCore.php b/build/neuralnetwork/core/NeuralNetworkCore.php index 788bfe8..a4c33f8 100644 --- a/build/neuralnetwork/core/NeuralNetworkCore.php +++ b/build/neuralnetwork/core/NeuralNetworkCore.php @@ -4,7 +4,7 @@ use filemanager\core\FileManager; - class NeuralNetworkCore{ + class NeuralNetworkCore implements \Serializable{ /************************************************ **** GLOBAL ATTRIBUTES **** @@ -14,6 +14,8 @@ private $kptGnm; // Number of genomes kept for each generation private $mutThr; // Mutation threshold private $fitEnd; // Fitness range to end process + private $numHid; // Number of hidden layer(s) + private $numNeu; // Number of neurons for each hidden layer private $max; // max values for input and output neurons private $storage; // path to storage @@ -28,6 +30,10 @@ + /************************************************ + **** Static Methods **** + ************************************************/ + /* RETURNS CONFIGURATION CONTENT * * @return config Associative array containing config content @@ -48,6 +54,36 @@ return $parsed; } + /* RETURNS STORAGE STATUS & DATA + * + * @path Path to storage + * + * @return files Array containing storage files' information + * @return error Returns NULL if error + * + */ + public static function getStorage($path){ + /* (1) Checks the path */ + if( !preg_match("/^(?P(?:[a-z0-9_-]+\/)*)(?P[a-z0-9_-]+)$/i", $path, $matches) ) + return null; + + $absolute_path = __ROOT__.self::conf()['storage_parent'].'/'.$matches['path'].$matches['filename']; + + /* (2) Checks file's existence and returns it */ + return [ + [ + 'filename' => $absolute_path.'.nn', // will contain neural network data + 'exists' => is_file($absolute_path.'.nn') + ],[ + 'filename' => $absolute_path.'.ex', // will contain samples + 'exists' => is_file($absolute_path.'.ex') + ],[ + 'filename' => $absolute_path.'.ln', // will contain values & weights + 'exists' => is_file($absolute_path.'.ln') + ] + ]; + + } /* CONSTRUCTOR * @@ -72,14 +108,17 @@ /* (2) Default attributes */ $default = self::conf()['default']; - $this->setKeptGenomes($default['genomes_kept']); // default value - $this->setMutationThreshold($default['mutation_threshold']); // default value - $this->setFitnessEnd($default['fitness_end']); // default value - $this->max = null; // default value - $this->setStorage($default['storage']); // default value + $this->setKeptGenomes($default['genomes_kept']); // default value + $this->setMutationThreshold($default['mutation_threshold']); // default value + $this->setFitnessEnd($default['fitness_end']); // default value + $this->setHiddenLayersCount($default['hidden_layers']); // default value + $this->setHiddenLayerNeuronsCount($default['layer_neurons']); // default value + $this->max = null; // default value + $this->setStorage($default['storage']); // default value } + /************************************************ **** Attributes Setters **** ************************************************/ @@ -92,26 +131,34 @@ * */ public function setStorage($path){ - /* (1) Checks the path */ - if( !preg_match("/^(?P(?:[a-z0-9_-]+\/)*)(?P[a-z0-9_-]+)$/i", $path, $matches) ) + /* [1] Manages storage verification + =========================================================*/ + /* (1) Get storage files' information */ + $storageData = self::getStorage($path); + + /* (2) If doesn't exist, return FALSE */ + if( is_null($storageData) ) return false; - $absolute_path = __ROOT__.self::conf()['storage_parent'].'/'.$matches['path'].$matches['filename']; + /* (3) Stores into instance */ + $this->storage = $storageData; - /* (2) Checks file's existence and returns TRUE */ - $this->storage = [ - [ - 'filename' => $absolute_path.'.nn', // will contain neural network data - 'exists' => is_file($absolute_path.'.nn') - ], - [ - 'filename' => $absolute_path.'.ex', // will contain samples - 'exists' => is_file($absolute_path.'.ex') - ] - ]; + + /* [2] Initializes files + =========================================================*/ + /* (1) Creates directory/ies */ + if( !is_dir(dirname(($this->storage[0]['filename']))) ) + mkdir( dirname($this->storage[0]['filename']), 0775, true ); + + // Checks + if( !is_dir(dirname(($this->storage[0]['filename']))) ) + throw new \Error('Error creating directory: '.dirname(($this->storage[0]['filename']))); + + /* (2) Creates files */ + foreach($this->storage as $file) + FileManager::create( $file['filename'] ); return true; - } /* SET FITNESS END @@ -147,6 +194,28 @@ $this->mutThr = $mutThr; } + /* SET NUMBER OF NEURONS PER HIDDEN LAYER + * + * @numNeu Number of Neurons per hidden layer + * + */ + public function setHiddenLayerNeuronsCount($numNeu){ + if( abs(intval($numNeu)) !== $numNeu ) return; + + $this->numNeu = $numNeu; + } + + /* SET NUMBER OF HIDDEN LAYERS + * + * @numHid Number of hidden layer(s) + * + */ + public function setHiddenLayersCount($numHid){ + if( abs(intval($numHid)) !== $numHid ) return; + + $this->numHid = $numHid; + } + /************************************************ **** Sample Setters **** @@ -167,7 +236,6 @@ ]; } - /* ADD SAMPLE TO THE NEURAL NETWORK * * @input Sample's input values @@ -205,7 +273,6 @@ return false; } - /* [2] Adds values =========================================================*/ FileManager::append( $this->storage[1]['filename'], implode(',',$input) .';'. implode(',',$output) ); @@ -213,6 +280,127 @@ return true; } + + /************************************************ + **** Process Methods **** + ************************************************/ + + /* DEFINES A STORAGE FOR THE NEURAL NETWORK + * + * @path [OPTIONAL] Path to storage + * @override If override is wanted (will erase the whole previous data) + * + */ + public function store($path=null, $override=false){ + if( !is_null($path) ){ + + /* [1] Checks storage existence + =========================================================*/ + /* (1) Get storage files' information */ + $storage = self::getStorage($path); + + /* (2) Checks if files doesn't exist */ + if( $storage[0]['exists'] || $storage[1]['exists'] || $storage[2]['exists'] ) + if( !$override ) + throw new \Error('This storage already exists, you can only load() it.'); + + + /* [2] Creates storage & its files + =========================================================*/ + /* (1) Keep last storage information */ + $last_storage = $this->storage; + + /* (2) Replaces with new storage */ + $this->setStorage($path); + + } + + + /* [3] Stores data + =========================================================*/ + /* (1) Stores NeuralNetwork state (attributes) */ + FileManager::write($storage[0]['filename'], $this->serialize()); + + /* (2) Stores samples */ + FileManager::write($storage[1]['filename'], FileManager::read($last_storage[1]['filename'])); + + /* (3) Stores NeuralNetwork values & weights */ + FileManager::write($storage[2]['filename'], FileManager::read($last_storage[2]['filename'])); + + } + + + /* STARTS THE LEARNING ROUTINE + * + * @callback Callback function to display current state + * + */ + public function learn($callback=null){ + /* [1] Manages @callback argument + =========================================================*/ + if( !is_callable($callback) ) + $callback = function(){}; + + /* [2] Creates the neural network + =========================================================*/ + + } + + /************************************************ + **** Serialization Methods **** + ************************************************/ + + /* RETURNS A SERIALIZED VERSION OF THE NeuralNetwork + * + * @return serialized Serialized representation of the NeuralNetwork + * + */ + public function serialize(){ + /* (1) Initializes json */ + $json = []; + + /* (2) Adding attributes */ + $json['maxGnr'] = $this->maxGnr; + $json['maxGnm'] = $this->maxGnm; + $json['kptGnm'] = $this->kptGnm; + $json['mutThr'] = $this->mutThr; + $json['fitEnd'] = $this->fitEnd; + $json['numHid'] = $this->numHid; + $json['numNeu'] = $this->numNeu; + + $json['max'] = $this->max; + $json['storage'] = $this->storage; + + /* (3) Returns serialized string */ + return json_encode($json); + } + + /* BUILDS THE NeuralNetwork BASED ON ITS SERIALIZED STRING + * + * @serialized Serialized representation of a NeuralNetwork + * + */ + public function unserialize($serialized){ + /* (1) Decodes json */ + $json = json_decode($serialized, true); + + /* (2) Manages json error */ + if( !is_array($json) ) + throw new Error('Unserialization format error.'); + + /* (3) Attributing json attributes */ + $this->maxGnr = $json['maxGnr']; + $this->maxGnm = $json['maxGnm']; + $this->kptGnm = $json['kptGnm']; + $this->mutThr = $json['mutThr']; + $this->fitEnd = $json['fitEnd']; + $this->numHid = $json['numHid']; + $this->numNeu = $json['numNeu']; + + $this->max = $json['max']; + $this->storage = $json['storage']; + } + } @@ -238,6 +426,12 @@ /* (4) Specifies that for each mutation, it must be at maximum 30% different */ $neunet->setMutationThreshold(0.4); + /* (5) Specifies the number of hidden layers */ + $neunet->setHiddenLayersCount(2); + + /* (6) Specifies the number of neurons per hidden layer */ + $neunet->setHiddenLayerNeuronsCount(4); + /* (2) Let's learn ---------------------------------------------------------*/ @@ -261,17 +455,18 @@ /* (3) What to do next ? ---------------------------------------------------------*/ /* (1) Store your data */ - $neunet->store('/some/path/to/filename'); + $neunet->store('/some/path/to/storage'); /* (2) [HIDDEN] will create those 2 files */ - '/some/path/to/filename.nn'; // containing neural network weights - '/some/path/to/filename.ex'; // containing neural network samples + '/some/path/to/storage.nn'; // containing neural network configuration + '/somt/path/to/storage.ln'; // containing neural network learnt values & weights + '/some/path/to/storage.ex'; // containing neural network samples /* (4) And next ? ---------------------------------------------------------*/ /* (1) Load your stored neural network */ - $trainednn = NeuralNetwork::load('/some/path/to/filename'); + $trainednn = NeuralNetwork::load('/some/path/to/storage'); /* (2) Use it to guess output, with well-formed input */ $guessed = $trainednn->guess([1.2, 0.9, 6.1]); diff --git a/build/neuralnetwork/core/NeuralNetworkManager.php b/build/neuralnetwork/core/NeuralNetworkManager.php new file mode 100644 index 0000000..3319c2b --- /dev/null +++ b/build/neuralnetwork/core/NeuralNetworkManager.php @@ -0,0 +1,114 @@ +setFitnessEnd(0.89); + + /* (3) Specifies that it will keep the 2 best genomes of each generation */ + $neunet->setKeptGenomes(2); + + /* (4) Specifies that for each mutation, it must be at maximum 30% different */ + $neunet->setMutationThreshold(0.4); + + /* (5) Specifies the number of hidden layers */ + $neunet->setHiddenLayersCount(2); + + /* (6) Specifies the number of neurons per hidden layer */ + $neunet->setHiddenLayerNeuronsCount(4); + + + /* (2) Let's learn + ---------------------------------------------------------*/ + /* (1) Set dataset sample maximum values */ + $neunet->setMaxValues([2,2,7], [10, 10]); + // input output + + /* (2) Setting our example dataset */ + $neunet->addSample([1.9, 2, 5.3], [6, 0]); + $neunet->addSample([1.2, 1.2, 0.1], [0, 2]); + $neunet->addSample([0, 0, 0], [5, 5]); + + /* (3) Launch learning routine with callback function */ + $neunet->learn(function($ctx){ // callback with @ctx the current context + echo 'generation '. $ctx['generation'] .'/'. $ctx['generations'] ."\n"; + echo 'genome '. $ctx['genome'] .'/'. $ctx['genomes'] ."\n"; + echo 'fitness: '. $ctx['fitness'] .'/'. $ctx['fitness_end']. "\n"; + }); + + + /* (3) What to do next ? + ---------------------------------------------------------*/ + /* (1) Store your data */ + $neunet->store('/some/path/to/storage'); + + /* (2) [HIDDEN] will create those 2 files */ + '/some/path/to/storage.nn'; // containing neural network configuration + '/somt/path/to/storage.ln'; // containing neural network learnt values & weights + '/some/path/to/storage.ex'; // containing neural network samples + + + /* (4) And next ? + ---------------------------------------------------------*/ + /* (1) Load your stored neural network */ + $trainednn = NeuralNetwork::load('/some/path/to/storage'); + + /* (2) Use it to guess output, with well-formed input */ + $guessed = $trainednn->guess([1.2, 0.9, 6.1]); + + /* (3) And correct it if needed*/ + echo "1: ". $guessed[0] ."\n"; + echo "2: ". $guessed[2] ."\n"; + echo "is it correct ?\n"; + // .. some code to manage and read correct output if it was wrong + $trainednn->addSample([1.2, 0.9, 6.1], [9, 0]); + + // You can now relaunch a new neural network's learning + // or You can just add a few generations to evolve your neural network + + } + +?> diff --git a/build/neuralnetwork/storage/A/B/C/test.ex b/build/neuralnetwork/storage/A/B/C/test.ex new file mode 100644 index 0000000..8496455 --- /dev/null +++ b/build/neuralnetwork/storage/A/B/C/test.ex @@ -0,0 +1,8 @@ +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 diff --git a/build/neuralnetwork/storage/A/B/C/test.ln b/build/neuralnetwork/storage/A/B/C/test.ln new file mode 100644 index 0000000..e69de29 diff --git a/build/neuralnetwork/storage/A/B/C/test.nn b/build/neuralnetwork/storage/A/B/C/test.nn new file mode 100644 index 0000000..9dd4e10 --- /dev/null +++ b/build/neuralnetwork/storage/A/B/C/test.nn @@ -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]},"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}]} \ No newline at end of file diff --git a/build/neuralnetwork/storage/_buffer.ln b/build/neuralnetwork/storage/_buffer.ln new file mode 100644 index 0000000..e69de29 diff --git a/config/neural-network.json b/config/neural-network.json index 4bf0df2..1e02176 100644 --- a/config/neural-network.json +++ b/config/neural-network.json @@ -5,6 +5,8 @@ "genomes_kept": 2, "mutation_threshold": 0.3, "fitness_end": 1, - "storage": "_buffer" + "storage": "_buffer", + "hidden_layers": 2, + "layer_neurons": 3 } } diff --git a/public/main.php b/public/main.php index 1a0ae39..b28e641 100644 --- a/public/main.php +++ b/public/main.php @@ -2,28 +2,65 @@ require_once __ROOT__.'/autoloader.php'; + use \neuralnetwork\core\Genome; use \neuralnetwork\core\NeuralNetwork; use \filemanager\core\FileManager; - function behaviour($abc){ - return [($abc[0] & $abc[1]) ^ $abc[2]]; + + if( false && 'test_creating_dataset' ){ + + function behaviour($abc){ + return [($abc[0] & $abc[1]) ^ $abc[2]]; + } + + echo "Welcome to neural-network.php\n"; + echo "-----------------------------\n"; + + $nn = NeuralNetwork::create(50, 100); + + $nn->setMaxValues([1, 1, 1], [1]); + $nn->setHiddenLayersCount(2); + $nn->setHiddenLayerNeuronsCount(3); + + $d = [0, 0, 0]; $nn->addSample($d, behaviour($d)); + $d = [0, 0, 1]; $nn->addSample($d, behaviour($d)); + $d = [0, 1, 0]; $nn->addSample($d, behaviour($d)); + $d = [0, 1, 1]; $nn->addSample($d, behaviour($d)); + $d = [1, 0, 0]; $nn->addSample($d, behaviour($d)); + $d = [1, 0, 1]; $nn->addSample($d, behaviour($d)); + $d = [1, 1, 0]; $nn->addSample($d, behaviour($d)); + $d = [1, 1, 1]; $nn->addSample($d, behaviour($d)); + + $nn->store('A/B/C/test', true); + } - echo "Welcome to neural-network.php\n"; - echo "-----------------------------\n"; + if( false && 'load_neural_network' ){ - $nn = NeuralNetwork::create(50, 100); + $nn = NeuralNetwork::load('A/B/C/test'); - $nn->setMaxValues([1, 1, 1], [1]); + } - $d = [0, 0, 0]; $nn->addSample($d, behaviour($d)); - $d = [0, 0, 1]; $nn->addSample($d, behaviour($d)); - $d = [0, 1, 0]; $nn->addSample($d, behaviour($d)); - $d = [0, 1, 1]; $nn->addSample($d, behaviour($d)); - $d = [1, 0, 0]; $nn->addSample($d, behaviour($d)); - $d = [1, 0, 1]; $nn->addSample($d, behaviour($d)); - $d = [1, 1, 0]; $nn->addSample($d, behaviour($d)); - $d = [1, 1, 1]; $nn->addSample($d, behaviour($d)); + if( true && 'test_genomes' ){ + /* (1) Basic Creation */ + $a = new Genome(2, 3); // 2 layers of 3 neurons each -> randomly filled + /* (2) Inheritance */ + $b = new Genome($a); // Clone of @a + + /* (3) Section Title */ + // $b->mutation(0.3); // @b has now mutated with a threshold of 30% + + /* (4) Cross-over (father+mother) */ + $c = new Genome($a, $b); // @c is a randomly-done mix of @a and @b + } + + + // REWRITE TEST + // for( $a = 0, $al = 50 ; $a < $al ; $a++ ) + // for( $b = 0, $bl = 20 ; $b < $bl ; $b++ ){ + // print "genome $b/$bl on generation $a/$al \r"; + // usleep(1000*10); + // } ?>