featuresByType(DataType::continuous()); if (count($features) !== $dataset->numFeatures()) { throw new InvalidArgumentException('Dataset must only contain' . ' continuous features.'); } $means = $stdDevs = []; foreach ($features as $values) { [$mean, $variance] = Stats::meanVar($values); $means[] = $mean; $stdDevs[] = sqrt($variance); } return new self($means, $stdDevs); } /** * @param (int|float)[] $center * @param int|float|(int|float)[] $stdDev * @throws InvalidArgumentException */ public function __construct(array $center = [0, 0], $stdDev = 1.0) { if (empty($center)) { throw new InvalidArgumentException('Cannot generate samples' . ' with dimensionality less than 1.'); } if (is_array($stdDev)) { if (count($center) !== count($stdDev)) { throw new InvalidArgumentException('Number of center' . ' coordinates and standard deviations must be equal.'); } foreach ($stdDev as $value) { if ($value < 0) { throw new InvalidArgumentException('Standard deviation' . " must be greater than 0, $value given."); } } $stdDev = Vector::quick($stdDev); } else { if ($stdDev < 0) { throw new InvalidArgumentException('Standard deviation' . " must be greater than 0, $stdDev given."); } } $this->center = Vector::quick($center); $this->stdDev = $stdDev; } /** * Return the center coordinates of the Blob. * * @return list */ public function center() : array { return $this->center->asArray(); } /** * Return the dimensionality of the data this generates. * * @internal * * @return int<0,max> */ public function dimensions() : int { return $this->center->n(); } /** * Generate n data points. * * @param int<0,max> $n * @return Unlabeled */ public function generate(int $n) : Unlabeled { $d = $this->dimensions(); $samples = Matrix::gaussian($n, $d) ->multiply($this->stdDev) ->add($this->center) ->asArray(); return Unlabeled::quick($samples); } }