From 72afeb7040104bd9825d0555637fb735eb8c9e5e Mon Sep 17 00:00:00 2001 From: Arkadiusz Kondas Date: Tue, 9 Aug 2016 13:27:43 +0200 Subject: [PATCH] implements and test multilayer perceptron methods --- .../Exception/InvalidArgumentException.php | 8 ++ .../Network/MultilayerPerceptron.php | 83 +++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/src/Phpml/Exception/InvalidArgumentException.php b/src/Phpml/Exception/InvalidArgumentException.php index d280296..86cfd86 100644 --- a/src/Phpml/Exception/InvalidArgumentException.php +++ b/src/Phpml/Exception/InvalidArgumentException.php @@ -81,4 +81,12 @@ class InvalidArgumentException extends \Exception { return new self('Layer node class must implement Node interface'); } + + /** + * @return InvalidArgumentException + */ + public static function invalidLayersNumber() + { + return new self('Provide at least 2 layers: 1 input and 1 output'); + } } diff --git a/src/Phpml/NeuralNetwork/Network/MultilayerPerceptron.php b/src/Phpml/NeuralNetwork/Network/MultilayerPerceptron.php index c0f7df3..4079822 100644 --- a/src/Phpml/NeuralNetwork/Network/MultilayerPerceptron.php +++ b/src/Phpml/NeuralNetwork/Network/MultilayerPerceptron.php @@ -4,6 +4,89 @@ declare (strict_types = 1); namespace Phpml\NeuralNetwork\Network; +use Phpml\Exception\InvalidArgumentException; +use Phpml\NeuralNetwork\Layer; +use Phpml\NeuralNetwork\Node\Bias; +use Phpml\NeuralNetwork\Node\Input; +use Phpml\NeuralNetwork\Node\Neuron; +use Phpml\NeuralNetwork\Node\Neuron\Synapse; + class MultilayerPerceptron extends LayeredNetwork { + /** + * @param array $layers + * + * @throws InvalidArgumentException + */ + public function __construct(array $layers) + { + if (count($layers) < 2) { + throw InvalidArgumentException::invalidLayersNumber(); + } + + $this->addInputLayer(array_shift($layers)); + $this->addNeuronLayers($layers); + $this->addBiasNodes(); + $this->generateSynapses(); + } + + /** + * @param int $nodes + */ + private function addInputLayer(int $nodes) + { + $this->addLayer(new Layer($nodes, Input::class)); + } + + /** + * @param array $layers + */ + private function addNeuronLayers(array $layers) + { + foreach ($layers as $neurons) { + $this->addLayer(new Layer($neurons, Neuron::class)); + } + } + + private function generateSynapses() + { + $layersNumber = count($this->layers) - 1; + for ($i = 0; $i < $layersNumber; ++$i) { + $currentLayer = $this->layers[$i]; + $nextLayer = $this->layers[$i + 1]; + $this->generateLayerSynapses($nextLayer, $currentLayer); + } + } + + private function addBiasNodes() + { + $biasLayers = count($this->layers) - 1; + for ($i = 0;$i < $biasLayers;++$i) { + $this->layers[$i]->addNode(new Bias()); + } + } + + /** + * @param Layer $nextLayer + * @param Layer $currentLayer + */ + private function generateLayerSynapses(Layer $nextLayer, Layer $currentLayer) + { + foreach ($nextLayer->getNodes() as $nextNeuron) { + if ($nextNeuron instanceof Neuron) { + $this->generateNeuronSynapses($currentLayer, $nextNeuron); + } + } + } + + /** + * @param Layer $currentLayer + * @param Neuron $nextNeuron + */ + private function generateNeuronSynapses(Layer $currentLayer, Neuron $nextNeuron) + { + foreach ($currentLayer->getNodes() as $currentNeuron) { + $nextNeuron->addSynapse(new Synapse($currentNeuron)); + } + } }