Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
7 / 7
CRAP
100.00% covered (success)
100.00%
25 / 25
LeastSquares
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
7 / 7
10
100.00% covered (success)
100.00%
25 / 25
 train
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
4 / 4
 predictSample
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
4 / 4
 getCoefficients
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getIntercept
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 computeCoefficients
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
7 / 7
 getSamplesMatrix
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
5 / 5
 getTargetsMatrix
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
3 / 3
<?php
declare (strict_types = 1);
namespace Phpml\Regression;
use Phpml\Helper\Predictable;
use Phpml\Math\Matrix;
class LeastSquares implements Regression
{
    use Predictable;
    /**
     * @var array
     */
    private $samples;
    /**
     * @var array
     */
    private $targets;
    /**
     * @var float
     */
    private $intercept;
    /**
     * @var array
     */
    private $coefficients;
    /**
     * @param array $samples
     * @param array $targets
     */
    public function train(array $samples, array $targets)
    {
        $this->samples = $samples;
        $this->targets = $targets;
        $this->computeCoefficients();
    }
    /**
     * @param array $sample
     *
     * @return mixed
     */
    public function predictSample(array $sample)
    {
        $result = $this->intercept;
        foreach ($this->coefficients as $index => $coefficient) {
            $result += $coefficient * $sample[$index];
        }
        return $result;
    }
    /**
     * @return array
     */
    public function getCoefficients()
    {
        return $this->coefficients;
    }
    /**
     * @return float
     */
    public function getIntercept()
    {
        return $this->intercept;
    }
    /**
     * coefficient(b) = (X'X)-1X'Y.
     */
    private function computeCoefficients()
    {
        $samplesMatrix = $this->getSamplesMatrix();
        $targetsMatrix = $this->getTargetsMatrix();
        $ts = $samplesMatrix->transpose()->multiply($samplesMatrix)->inverse();
        $tf = $samplesMatrix->transpose()->multiply($targetsMatrix);
        $this->coefficients = $ts->multiply($tf)->getColumnValues(0);
        $this->intercept = array_shift($this->coefficients);
    }
    /**
     * Add one dimension for intercept calculation.
     *
     * @return Matrix
     */
    private function getSamplesMatrix()
    {
        $samples = [];
        foreach ($this->samples as $sample) {
            array_unshift($sample, 1);
            $samples[] = $sample;
        }
        return new Matrix($samples);
    }
    /**
     * @return Matrix
     */
    private function getTargetsMatrix()
    {
        if (is_array($this->targets[0])) {
            return new Matrix($this->targets);
        }
        return Matrix::fromFlatArray($this->targets);
    }
}