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