Esempio n. 1
0
        public static void GradientCheck(LayerBase <double> layer, int inputWidth, int inputHeight, int inputDepth, int batchSize, double epsilon = 1e-4)
        {
            layer.Init(inputWidth, inputHeight, inputDepth);

            // Forward pass
            var input = BuilderInstance <double> .Volume.Random(new Shape(inputWidth, inputHeight, inputDepth, batchSize), 0.0,
                                                                Math.Sqrt(2.0 / (inputWidth * inputHeight * inputDepth)));

            var output = layer.DoForward(input, true);

            // Set output gradients to 1
            var outputGradient = BuilderInstance <double> .Volume.From(new double[output.Shape.TotalLength].Populate(1.0), output.Shape);

            // Backward pass to retrieve gradients
            layer.Backward(outputGradient);
            var computedGradients = layer.InputActivationGradients;

            using (var result = BuilderInstance <double> .Volume.SameAs(output.Shape))
            {
                // Now let's approximate gradient using derivate definition
                for (var d = 0; d < inputDepth; d++)
                {
                    for (var y = 0; y < inputHeight; y++)
                    {
                        for (var x = 0; x < inputWidth; x++)
                        {
                            result.Clear();

                            var oldValue = input.Get(x, y, d);

                            input.Set(x, y, d, oldValue + epsilon);
                            var output1 = layer.DoForward(input).Clone();
                            input.Set(x, y, d, oldValue - epsilon);
                            var output2 = layer.DoForward(input).Clone();

                            input.Set(x, y, d, oldValue);

                            output2.SubtractFrom(output1, result);

                            var grad = new double[output.Shape.TotalLength];
                            for (var j = 0; j < output.Shape.TotalLength; j++)
                            {
                                grad[j] = result.Get(j) / (2.0 * epsilon);
                            }

                            var gradient = grad.Sum();               // approximated gradient
                            var actual   = computedGradients.Get(x, y, d);
                            Assert.AreEqual(gradient, actual, 1e-3); // compare layer gradient to the approximated gradient
                        }
                    }
                }
            }
        }
Esempio n. 2
0
        public static void GradienWrtParameterstCheck(int inputWidth, int inputHeight, int inputDepth, int bacthSize, LayerBase <double> layer, double epsilon = 1e-4)
        {
            layer.Init(inputWidth, inputHeight, inputDepth);

            // Forward pass
            var input = BuilderInstance <double> .Volume.From(new double[inputWidth *inputHeight *inputDepth *bacthSize].Populate(1.0),
                                                              new Shape(inputWidth, inputHeight, inputDepth, bacthSize));

            var output = layer.DoForward(input);

            // Set output gradients to 1
            var outputGradient = BuilderInstance <double> .Volume.From(new double[output.Shape.TotalLength].Populate(1.0), output.Shape);

            // Backward pass to retrieve gradients
            layer.Backward(outputGradient);

            var paramsAndGrads = layer.GetParametersAndGradients();

            foreach (var paramAndGrad in paramsAndGrads)
            {
                var vol = paramAndGrad.Volume;
                var gra = paramAndGrad.Gradient;

                // Now let's approximate gradient
                for (var i = 0; i < paramAndGrad.Volume.Shape.TotalLength; i++)
                {
                    input = BuilderInstance <double> .Volume.From(new double[input.Shape.TotalLength].Populate(1.0), input.Shape);

                    var oldValue = vol.Get(i);
                    vol.Set(i, oldValue + epsilon);
                    var output1 = layer.DoForward(input).Clone();
                    vol.Set(i, oldValue - epsilon);
                    var output2 = layer.DoForward(input).Clone();
                    vol.Set(i, oldValue);

                    using (var result = BuilderInstance <double> .Volume.SameAs(output1.Shape))
                    {
                        output2.SubtractFrom(output1, result);

                        var grad = new double[output.Shape.TotalLength];
                        for (var j = 0; j < output.Shape.TotalLength; j++)
                        {
                            grad[j] = result.Get(j) / (2.0 * epsilon);
                        }

                        var gradient = grad.Sum();                   // approximated gradient
                        Assert.AreEqual(gradient, gra.Get(i), 1e-3); // compare layer gradient to the approximated gradient}
                    }
                }
            }
        }