Passed
Push — master ( 12b8b1...5b373f )
by Arkadiusz
04:53
created

EigenTransformerBase::reduce()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 1
1
<?php declare(strict_types=1);
2
3
namespace Phpml\DimensionReduction;
4
5
use Phpml\Math\LinearAlgebra\EigenvalueDecomposition;
6
use Phpml\Math\Matrix;
7
8
/**
9
 * Class to compute eigen pairs (values & vectors) of a given matrix
10
 * with the consideration of numFeatures or totalVariance to be preserved
11
 *
12
 * @author hp
13
 */
14
abstract class EigenTransformerBase
15
{
16
    /**
17
     * Total variance to be conserved after the reduction
18
     *
19
     * @var float
20
     */
21
    public $totalVariance = 0.9;
22
23
    /**
24
     * Number of features to be preserved after the reduction
25
     *
26
     * @var int
27
     */
28
    public $numFeatures = null;
29
30
    /**
31
     * Top eigenvectors of the matrix
32
     *
33
     * @var array
34
     */
35
    protected $eigVectors = [];
36
37
    /**
38
     * Top eigenValues of the matrix
39
     *
40
     * @var type
41
     */
42
    protected $eigValues = [];
43
44
    /**
45
     * Calculates eigenValues and eigenVectors of the given matrix. Returns
46
     * top eigenVectors along with the largest eigenValues. The total explained variance
47
     * of these eigenVectors will be no less than desired $totalVariance value
48
     *
49
     * @param array $matrix
50
     */
51
    protected function eigenDecomposition(array $matrix)
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;
0 ignored issues
show
Documentation Bug introduced by
It seems like $values of type array is incompatible with the declared type object<Phpml\DimensionReduction\type> of property $eigValues.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
81
        $this->eigVectors = $vectors;
82
    }
83
84
    /**
85
     * Returns the reduced data
86
     *
87
     * @param array $data
88
     *
89
     * @return array
90
     */
91
    protected function reduce(array $data)
92
    {
93
        $m1 = new Matrix($data);
94
        $m2 = new Matrix($this->eigVectors);
95
96
        return $m1->multiply($m2->transpose())->toArray();
97
    }
98
}
99