Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.0.x will end 8 May 2023 (12 months).
  • Bug fixes for security issues in 4.0.x will end 13 November 2023 (18 months).
  • PHP version: minimum PHP 7.3.0 Note: the minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is also supported.

Differences Between: [Versions 310 and 400] [Versions 311 and 400] [Versions 39 and 400]

   1  <?php
   2  
   3  declare(strict_types=1);
   4  
   5  namespace Phpml\NeuralNetwork\Training;
   6  
   7  use Phpml\NeuralNetwork\Node\Neuron;
   8  use Phpml\NeuralNetwork\Training\Backpropagation\Sigma;
   9  
  10  class Backpropagation
  11  {
  12      /**
  13       * @var float
  14       */
  15      private $learningRate;
  16  
  17      /**
  18       * @var array
  19       */
  20      private $sigmas = [];
  21  
  22      /**
  23       * @var array
  24       */
  25      private $prevSigmas = [];
  26  
  27      public function __construct(float $learningRate)
  28      {
  29          $this->setLearningRate($learningRate);
  30      }
  31  
  32      public function setLearningRate(float $learningRate): void
  33      {
  34          $this->learningRate = $learningRate;
  35      }
  36  
  37      public function getLearningRate(): float
  38      {
  39          return $this->learningRate;
  40      }
  41  
  42      /**
  43       * @param mixed $targetClass
  44       */
  45      public function backpropagate(array $layers, $targetClass): void
  46      {
  47          $layersNumber = count($layers);
  48  
  49          // Backpropagation.
  50          for ($i = $layersNumber; $i > 1; --$i) {
  51              $this->sigmas = [];
  52              foreach ($layers[$i - 1]->getNodes() as $key => $neuron) {
  53                  if ($neuron instanceof Neuron) {
  54                      $sigma = $this->getSigma($neuron, $targetClass, $key, $i == $layersNumber);
  55                      foreach ($neuron->getSynapses() as $synapse) {
  56                          $synapse->changeWeight($this->learningRate * $sigma * $synapse->getNode()->getOutput());
  57                      }
  58                  }
  59              }
  60  
  61              $this->prevSigmas = $this->sigmas;
  62          }
  63  
  64          // Clean some memory (also it helps make MLP persistency & children more maintainable).
  65          $this->sigmas = [];
  66          $this->prevSigmas = [];
  67      }
  68  
  69      private function getSigma(Neuron $neuron, int $targetClass, int $key, bool $lastLayer): float
  70      {
  71          $neuronOutput = $neuron->getOutput();
  72          $sigma = $neuron->getDerivative();
  73  
  74          if ($lastLayer) {
  75              $value = 0;
  76              if ($targetClass === $key) {
  77                  $value = 1;
  78              }
  79  
  80              $sigma *= ($value - $neuronOutput);
  81          } else {
  82              $sigma *= $this->getPrevSigma($neuron);
  83          }
  84  
  85          $this->sigmas[] = new Sigma($neuron, $sigma);
  86  
  87          return $sigma;
  88      }
  89  
  90      private function getPrevSigma(Neuron $neuron): float
  91      {
  92          $sigma = 0.0;
  93  
  94          foreach ($this->prevSigmas as $neuronSigma) {
  95              $sigma += $neuronSigma->getSigmaForNeuron($neuron);
  96          }
  97  
  98          return $sigma;
  99      }
 100  }