Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

   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      /**
  38       * @param mixed $targetClass
  39       */
  40      public function backpropagate(array $layers, $targetClass): void
  41      {
  42          $layersNumber = count($layers);
  43  
  44          // Backpropagation.
  45          for ($i = $layersNumber; $i > 1; --$i) {
  46              $this->sigmas = [];
  47              foreach ($layers[$i - 1]->getNodes() as $key => $neuron) {
  48                  if ($neuron instanceof Neuron) {
  49                      $sigma = $this->getSigma($neuron, $targetClass, $key, $i == $layersNumber);
  50                      foreach ($neuron->getSynapses() as $synapse) {
  51                          $synapse->changeWeight($this->learningRate * $sigma * $synapse->getNode()->getOutput());
  52                      }
  53                  }
  54              }
  55  
  56              $this->prevSigmas = $this->sigmas;
  57          }
  58  
  59          // Clean some memory (also it helps make MLP persistency & children more maintainable).
  60          $this->sigmas = [];
  61          $this->prevSigmas = [];
  62      }
  63  
  64      private function getSigma(Neuron $neuron, int $targetClass, int $key, bool $lastLayer): float
  65      {
  66          $neuronOutput = $neuron->getOutput();
  67          $sigma = $neuron->getDerivative();
  68  
  69          if ($lastLayer) {
  70              $value = 0;
  71              if ($targetClass === $key) {
  72                  $value = 1;
  73              }
  74  
  75              $sigma *= ($value - $neuronOutput);
  76          } else {
  77              $sigma *= $this->getPrevSigma($neuron);
  78          }
  79  
  80          $this->sigmas[] = new Sigma($neuron, $sigma);
  81  
  82          return $sigma;
  83      }
  84  
  85      private function getPrevSigma(Neuron $neuron): float
  86      {
  87          $sigma = 0.0;
  88  
  89          foreach ($this->prevSigmas as $neuronSigma) {
  90              $sigma += $neuronSigma->getSigmaForNeuron($neuron);
  91          }
  92  
  93          return $sigma;
  94      }
  95  }