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.
   1  <?php
   2  
   3  declare(strict_types=1);
   4  
   5  namespace Phpml\DimensionReduction;
   6  
   7  use Phpml\Math\LinearAlgebra\EigenvalueDecomposition;
   8  use Phpml\Math\Matrix;
   9  
  10  /**
  11   * Class to compute eigen pairs (values & vectors) of a given matrix
  12   * with the consideration of numFeatures or totalVariance to be preserved
  13   *
  14   * @author hp
  15   */
  16  abstract class EigenTransformerBase
  17  {
  18      /**
  19       * Total variance to be conserved after the reduction
  20       *
  21       * @var float
  22       */
  23      public $totalVariance = 0.9;
  24  
  25      /**
  26       * Number of features to be preserved after the reduction
  27       *
  28       * @var int
  29       */
  30      public $numFeatures = null;
  31  
  32      /**
  33       * Top eigenvectors of the matrix
  34       *
  35       * @var array
  36       */
  37      protected $eigVectors = [];
  38  
  39      /**
  40       * Top eigenValues of the matrix
  41       *
  42       * @var array
  43       */
  44      protected $eigValues = [];
  45  
  46      /**
  47       * Calculates eigenValues and eigenVectors of the given matrix. Returns
  48       * top eigenVectors along with the largest eigenValues. The total explained variance
  49       * of these eigenVectors will be no less than desired $totalVariance value
  50       */
  51      protected function eigenDecomposition(array $matrix): void
  52      {
  53          $eig = new EigenvalueDecomposition($matrix);
  54          $eigVals = $eig->getRealEigenvalues();
  55          $eigVects = $eig->getEigenvectors();
  56  
  57          $totalEigVal = array_sum($eigVals);
  58          // Sort eigenvalues in descending order
  59          arsort($eigVals);
  60  
  61          $explainedVar = 0.0;
  62          $vectors = [];
  63          $values = [];
  64          foreach ($eigVals as $i => $eigVal) {
  65              $explainedVar += $eigVal / $totalEigVal;
  66              $vectors[] = $eigVects[$i];
  67              $values[] = $eigVal;
  68  
  69              if ($this->numFeatures !== null) {
  70                  if (count($vectors) == $this->numFeatures) {
  71                      break;
  72                  }
  73              } else {
  74                  if ($explainedVar >= $this->totalVariance) {
  75                      break;
  76                  }
  77              }
  78          }
  79  
  80          $this->eigValues = $values;
  81          $this->eigVectors = $vectors;
  82      }
  83  
  84      /**
  85       * Returns the reduced data
  86       */
  87      protected function reduce(array $data): array
  88      {
  89          $m1 = new Matrix($data);
  90          $m2 = new Matrix($this->eigVectors);
  91  
  92          return $m1->multiply($m2->transpose())->toArray();
  93      }
  94  }