2016-05-01 21:17:09 +00:00
|
|
|
<?php
|
2016-05-01 21:36:33 +00:00
|
|
|
|
2016-11-20 21:53:17 +00:00
|
|
|
declare(strict_types=1);
|
2016-05-01 21:17:09 +00:00
|
|
|
|
|
|
|
namespace Phpml\Clustering;
|
|
|
|
|
|
|
|
use Phpml\Clustering\KMeans\Space;
|
|
|
|
use Phpml\Exception\InvalidArgumentException;
|
|
|
|
|
|
|
|
class KMeans implements Clusterer
|
|
|
|
{
|
2017-11-14 20:21:23 +00:00
|
|
|
public const INIT_RANDOM = 1;
|
2017-11-22 21:16:10 +00:00
|
|
|
|
2017-11-14 20:21:23 +00:00
|
|
|
public const INIT_KMEANS_PLUS_PLUS = 2;
|
2016-05-01 21:36:33 +00:00
|
|
|
|
2016-05-01 21:17:09 +00:00
|
|
|
/**
|
|
|
|
* @var int
|
|
|
|
*/
|
|
|
|
private $clustersNumber;
|
|
|
|
|
2016-05-01 21:36:33 +00:00
|
|
|
/**
|
|
|
|
* @var int
|
|
|
|
*/
|
|
|
|
private $initialization;
|
|
|
|
|
|
|
|
public function __construct(int $clustersNumber, int $initialization = self::INIT_KMEANS_PLUS_PLUS)
|
2016-05-01 21:17:09 +00:00
|
|
|
{
|
2016-05-01 21:36:33 +00:00
|
|
|
if ($clustersNumber <= 0) {
|
2016-05-01 21:17:09 +00:00
|
|
|
throw InvalidArgumentException::invalidClustersNumber();
|
|
|
|
}
|
2016-05-01 21:36:33 +00:00
|
|
|
|
2016-05-01 21:17:09 +00:00
|
|
|
$this->clustersNumber = $clustersNumber;
|
2016-05-01 21:36:33 +00:00
|
|
|
$this->initialization = $initialization;
|
2016-05-01 21:17:09 +00:00
|
|
|
}
|
|
|
|
|
2017-11-22 21:16:10 +00:00
|
|
|
public function cluster(array $samples): array
|
2016-05-01 21:17:09 +00:00
|
|
|
{
|
|
|
|
$space = new Space(count($samples[0]));
|
|
|
|
foreach ($samples as $sample) {
|
|
|
|
$space->addPoint($sample);
|
|
|
|
}
|
2016-05-01 21:36:33 +00:00
|
|
|
|
2016-05-01 21:17:09 +00:00
|
|
|
$clusters = [];
|
2016-05-02 12:02:00 +00:00
|
|
|
foreach ($space->cluster($this->clustersNumber, $this->initialization) as $cluster) {
|
2016-05-01 21:17:09 +00:00
|
|
|
$clusters[] = $cluster->getPoints();
|
|
|
|
}
|
2016-05-01 21:36:33 +00:00
|
|
|
|
2016-05-01 21:17:09 +00:00
|
|
|
return $clusters;
|
|
|
|
}
|
|
|
|
}
|