kernel = $kernel ?? new Euclidean(); } /** * Seed k cluster centroids from a dataset. * * @internal * * @param Dataset $dataset * @param int $k * @throws RuntimeException * @return list> */ public function seed(Dataset $dataset, int $k) : array { DatasetIsNotEmpty::with($dataset)->check(); if ($k > $dataset->numSamples()) { throw new RuntimeException("Cannot seed $k clusters with only " . $dataset->numSamples() . ' samples.'); } $centroids = $dataset->randomSubset(1)->samples(); while (count($centroids) < $k) { $weights = []; foreach ($dataset->samples() as $sample) { $bestDistance = INF; foreach ($centroids as $centroid) { $distance = $this->kernel->compute($sample, $centroid); if ($distance < $bestDistance) { $bestDistance = $distance; } } $weights[] = $bestDistance ** 2; } $centroids[] = $dataset->randomWeightedSubsetWithReplacement(1, $weights)->sample(0); } return $centroids; } /** * Return the string representation of the object. * * @internal * * @return string */ public function __toString() : string { return "Plus Plus (kernel: {$this->kernel})"; } }