1<?php 2 3namespace Rubix\ML\Tests\NeuralNet\Layers; 4 5use Tensor\Matrix; 6use Rubix\ML\Deferred; 7use Rubix\ML\NeuralNet\Layers\Layer; 8use Rubix\ML\NeuralNet\Layers\Dense; 9use Rubix\ML\NeuralNet\Layers\Hidden; 10use Rubix\ML\NeuralNet\Initializers\He; 11use Rubix\ML\NeuralNet\Layers\Parametric; 12use Rubix\ML\NeuralNet\Optimizers\Stochastic; 13use Rubix\ML\NeuralNet\Initializers\Constant; 14use PHPUnit\Framework\TestCase; 15 16/** 17 * @group Layers 18 * @covers \Rubix\ML\NeuralNet\Layers\Dense 19 */ 20class DenseTest extends TestCase 21{ 22 protected const RANDOM_SEED = 0; 23 24 /** 25 * @var int 26 */ 27 protected $fanIn; 28 29 /** 30 * @var \Tensor\Matrix 31 */ 32 protected $input; 33 34 /** 35 * @var \Rubix\ML\Deferred 36 */ 37 protected $prevGrad; 38 39 /** 40 * @var \Rubix\ML\NeuralNet\Optimizers\Optimizer 41 */ 42 protected $optimizer; 43 44 /** 45 * @var \Rubix\ML\NeuralNet\Layers\Dense 46 */ 47 protected $layer; 48 49 /** 50 * @before 51 */ 52 protected function setUp() : void 53 { 54 $this->fanIn = 3; 55 56 $this->input = Matrix::quick([ 57 [1.0, 2.5, -0.1], 58 [0.1, 0.0, 3.0], 59 [0.002, -6.0, -0.5], 60 ]); 61 62 $this->prevGrad = new Deferred(function () { 63 return Matrix::quick([ 64 [0.50, 0.2, 0.01], 65 [0.25, 0.1, 0.89], 66 ]); 67 }); 68 69 $this->optimizer = new Stochastic(0.001); 70 71 $this->layer = new Dense(2, 0.0, true, new He(), new Constant(0.0)); 72 73 srand(self::RANDOM_SEED); 74 } 75 76 /** 77 * @test 78 */ 79 public function build() : void 80 { 81 $this->assertInstanceOf(Dense::class, $this->layer); 82 $this->assertInstanceOf(Layer::class, $this->layer); 83 $this->assertInstanceOf(Hidden::class, $this->layer); 84 $this->assertInstanceOf(Parametric::class, $this->layer); 85 } 86 87 /** 88 * @test 89 */ 90 public function initializeForwardBackInfer() : void 91 { 92 $this->layer->initialize($this->fanIn); 93 94 $this->assertEquals(2, $this->layer->width()); 95 96 $expected = [ 97 [0.1331636897703166, -2.659941938483866, 0.37781475642889195], 98 [0.8082829632098398, -2.9282037817258764, 0.21589538926944302], 99 ]; 100 101 $forward = $this->layer->forward($this->input); 102 103 $this->assertInstanceOf(Matrix::class, $forward); 104 $this->assertEquals($expected, $forward->asArray()); 105 106 $gradient = $this->layer->back($this->prevGrad, $this->optimizer)->compute(); 107 108 $expected = [ 109 [0.2513486032877107, 0.10053944131508427, 0.698223970571707], 110 [0.16407184592276702, 0.0656287383691068, 0.2102008334557029], 111 [0.44839890381544645, 0.1793595615261786, 0.7297101185916894], 112 ]; 113 114 $this->assertInstanceOf(Matrix::class, $gradient); 115 $this->assertEquals($expected, $gradient->asArray()); 116 117 $expected = [ 118 [0.1314490977703166, -2.670373438483866, 0.376362656428892], 119 [0.8063645522098398, -2.9367382817258765, 0.20608923926944314], 120 ]; 121 122 $infer = $this->layer->infer($this->input); 123 124 $this->assertInstanceOf(Matrix::class, $infer); 125 $this->assertEquals($expected, $infer->asArray()); 126 } 127} 128