127 lines
3.2 KiB
PHP
127 lines
3.2 KiB
PHP
<?php
|
|
|
|
namespace Rubix\ML\Tests\NeuralNet\Layers;
|
|
|
|
use Tensor\Matrix;
|
|
use Rubix\ML\Deferred;
|
|
use Rubix\ML\NeuralNet\Layers\Layer;
|
|
use Rubix\ML\NeuralNet\Layers\Dense;
|
|
use Rubix\ML\NeuralNet\Layers\Hidden;
|
|
use Rubix\ML\NeuralNet\Initializers\He;
|
|
use Rubix\ML\NeuralNet\Layers\Parametric;
|
|
use Rubix\ML\NeuralNet\Optimizers\Stochastic;
|
|
use Rubix\ML\NeuralNet\Initializers\Constant;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* @group Layers
|
|
* @covers \Rubix\ML\NeuralNet\Layers\Dense
|
|
*/
|
|
class DenseTest extends TestCase
|
|
{
|
|
protected const RANDOM_SEED = 0;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
protected $fanIn;
|
|
|
|
/**
|
|
* @var \Tensor\Matrix
|
|
*/
|
|
protected $input;
|
|
|
|
/**
|
|
* @var \Rubix\ML\Deferred
|
|
*/
|
|
protected $prevGrad;
|
|
|
|
/**
|
|
* @var \Rubix\ML\NeuralNet\Optimizers\Optimizer
|
|
*/
|
|
protected $optimizer;
|
|
|
|
/**
|
|
* @var \Rubix\ML\NeuralNet\Layers\Dense
|
|
*/
|
|
protected $layer;
|
|
|
|
/**
|
|
* @before
|
|
*/
|
|
protected function setUp() : void
|
|
{
|
|
$this->fanIn = 3;
|
|
|
|
$this->input = Matrix::quick([
|
|
[1.0, 2.5, -0.1],
|
|
[0.1, 0.0, 3.0],
|
|
[0.002, -6.0, -0.5],
|
|
]);
|
|
|
|
$this->prevGrad = new Deferred(function () {
|
|
return Matrix::quick([
|
|
[0.50, 0.2, 0.01],
|
|
[0.25, 0.1, 0.89],
|
|
]);
|
|
});
|
|
|
|
$this->optimizer = new Stochastic(0.001);
|
|
|
|
$this->layer = new Dense(2, 0.0, true, new He(), new Constant(0.0));
|
|
|
|
srand(self::RANDOM_SEED);
|
|
}
|
|
|
|
/**
|
|
* @test
|
|
*/
|
|
public function build() : void
|
|
{
|
|
$this->assertInstanceOf(Dense::class, $this->layer);
|
|
$this->assertInstanceOf(Layer::class, $this->layer);
|
|
$this->assertInstanceOf(Hidden::class, $this->layer);
|
|
$this->assertInstanceOf(Parametric::class, $this->layer);
|
|
}
|
|
|
|
/**
|
|
* @test
|
|
*/
|
|
public function initializeForwardBackInfer() : void
|
|
{
|
|
$this->layer->initialize($this->fanIn);
|
|
|
|
$this->assertEquals(2, $this->layer->width());
|
|
|
|
$expected = [
|
|
[0.1331636897703166, -2.659941938483866, 0.37781475642889195],
|
|
[0.8082829632098398, -2.9282037817258764, 0.21589538926944302],
|
|
];
|
|
|
|
$forward = $this->layer->forward($this->input);
|
|
|
|
$this->assertInstanceOf(Matrix::class, $forward);
|
|
$this->assertEquals($expected, $forward->asArray());
|
|
|
|
$gradient = $this->layer->back($this->prevGrad, $this->optimizer)->compute();
|
|
|
|
$expected = [
|
|
[0.2513486032877107, 0.10053944131508427, 0.698223970571707],
|
|
[0.16407184592276702, 0.0656287383691068, 0.2102008334557029],
|
|
[0.44839890381544645, 0.1793595615261786, 0.7297101185916894],
|
|
];
|
|
|
|
$this->assertInstanceOf(Matrix::class, $gradient);
|
|
$this->assertEquals($expected, $gradient->asArray());
|
|
|
|
$expected = [
|
|
[0.1314490977703166, -2.670373438483866, 0.376362656428892],
|
|
[0.8063645522098398, -2.9367382817258765, 0.20608923926944314],
|
|
];
|
|
|
|
$infer = $this->layer->infer($this->input);
|
|
|
|
$this->assertInstanceOf(Matrix::class, $infer);
|
|
$this->assertEquals($expected, $infer->asArray());
|
|
}
|
|
}
|