← Back
Editing: SwissRoll.php
<?php namespace Rubix\ML\Datasets\Generators; use Tensor\Matrix; use Tensor\Vector; use Rubix\ML\Datasets\Labeled; use Rubix\ML\Exceptions\InvalidArgumentException; use function Rubix\ML\array_transpose; use const Rubix\ML\HALF_PI; /** * Swiss Roll * * Generate a 3-dimensional swiss roll dataset with continuous valued labels. * The labels are the inputs to the swiss roll transformation and are suitable * for non-linear regression problems. * * References: * [1] S. Marsland. (2009). Machine Learning: An Algorithmic Perspective, * Chapter 10. * * @category Machine Learning * @package Rubix/ML * @author Andrew DalPino */ class SwissRoll implements Generator { /** * The center vector of the swiss roll. * * @var Vector */ protected Vector $center; /** * The scaling factor of the swiss roll. * * @var float */ protected float $scale; /** * The depth of the swiss roll i.e the scale of the y dimension. * * @var float */ protected float $depth; /** * The standard deviation of the gaussian noise. * * @var float */ protected float $noise; /** * @param float $x * @param float $y * @param float $z * @param float $scale * @param float $depth * @param float $noise * @throws InvalidArgumentException */ public function __construct( float $x = 0.0, float $y = 0.0, float $z = 0.0, float $scale = 1.0, float $depth = 21.0, float $noise = 0.1 ) { if ($scale < 0.0) { throw new InvalidArgumentException('Scale must be' . " greater than 0, $scale given."); } if ($depth < 0) { throw new InvalidArgumentException('Depth must be' . " greater than 0, $depth given."); } if ($noise < 0.0) { throw new InvalidArgumentException('Noise factor cannot be less' . " than 0, $noise given."); } $this->center = Vector::quick([$x, $y, $z]); $this->scale = $scale; $this->depth = $depth; $this->noise = $noise; } /** * Return the dimensionality of the data this generates. * * @internal * * @return int<0,max> */ public function dimensions() : int { return 3; } /** * Generate n data points. * * @param int<0,max> $n * @return Labeled */ public function generate(int $n) : Labeled { $t = Vector::rand($n) ->multiply(2) ->add(1) ->multiply(M_PI + HALF_PI); $x = $t->multiply($t->cos())->asArray(); $y = Vector::rand($n)->multiply($this->depth)->asArray(); $z = $t->multiply($t->sin())->asArray(); $coordinates = array_transpose([$x, $y, $z]); $noise = Matrix::gaussian($n, 3) ->multiply($this->noise); $samples = Matrix::quick($coordinates) ->multiply($this->scale) ->add($this->center) ->add($noise) ->asArray(); $labels = $t->asArray(); return Labeled::quick($samples, $labels); } }
Save File
Cancel