Completed
Push — develop ( 6f5f19...d2e0ce )
by Arkadiusz
02:17
created

KNearestNeighbors::predictSample()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 15
rs 9.4285
cc 2
eloc 8
nc 2
nop 1
1
<?php
2
3
declare (strict_types = 1);
4
5
namespace Phpml\Classifier;
6
7
use Phpml\Classifier\Traits\Predictable;
8
use Phpml\Classifier\Traits\Trainable;
9
use Phpml\Metric\Distance;
10
use Phpml\Metric\Distance\Euclidean;
11
12
class KNearestNeighbors implements Classifier
13
{
14
    use Trainable, Predictable;
15
16
    /**
17
     * @var int
18
     */
19
    private $k;
20
21
    /**
22
     * @var Distance
23
     */
24
    private $distanceMetric;
25
26
    /**
27
     * @param int           $k
28
     * @param Distance|null $distanceMetric (if null then Euclidean distance as default)
29
     */
30
    public function __construct(int $k = 3, Distance $distanceMetric = null)
31
    {
32
        if (null === $distanceMetric) {
33
            $distanceMetric = new Euclidean();
34
        }
35
36
        $this->k = $k;
37
        $this->samples = [];
38
        $this->labels = [];
39
        $this->distanceMetric = $distanceMetric;
40
    }
41
42
    /**
43
     * @param array $sample
44
     *
45
     * @return mixed
46
     */
47
    private function predictSample(array $sample)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
48
    {
49
        $distances = $this->kNeighborsDistances($sample);
50
51
        $predictions = array_combine(array_values($this->labels), array_fill(0, count($this->labels), 0));
52
53
        foreach ($distances as $index => $distance) {
54
            ++$predictions[$this->labels[$index]];
55
        }
56
57
        arsort($predictions);
58
        reset($predictions);
59
60
        return key($predictions);
61
    }
62
63
    /**
64
     * @param array $sample
65
     *
66
     * @return array
67
     *
68
     * @throws \Phpml\Exception\InvalidArgumentException
69
     */
70
    private function kNeighborsDistances(array $sample): array
71
    {
72
        $distances = [];
73
74
        foreach ($this->samples as $index => $neighbor) {
75
            $distances[$index] = $this->distanceMetric->distance($sample, $neighbor);
76
        }
77
78
        asort($distances);
79
80
        return array_slice($distances, 0, $this->k, true);
81
    }
82
}
83