Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
}