勾配を実装してみた

C# でゼロから Deep Learning を実装する挑戦を少しずつ進めている。 まだ第 4 章だけど。 今回は勾配を実装してみた。

using MathNet.Numerics.LinearAlgebra;
using System;
using System.Linq;

namespace NumericGradientSample
{
    class Program
    {
        static void Main(string[] args)
        {
            Func<Vector<double>, double> function2 =
                x => x[0] * x[0] + x[1] * x[1];

            Console.WriteLine("(x0, x1) = (3.0, 4.0) のとき");
            Console.WriteLine(
                NumericalGradient(
                    function2,
                    Vector<double>.Build.DenseOfArray(new[] { 3.0, 4.0 })));

            Console.WriteLine("(x0, x1) = (0.0, 2.0) のとき");
            Console.WriteLine(
                NumericalGradient(
                    function2,
                Vector<double>.Build.DenseOfArray(new[] { 0.0, 2.0 })));

            Console.WriteLine("(x0, x1) = (3.0, 0.0) のとき");
            Console.WriteLine(
                NumericalGradient(
                    function2,
                    Vector<double>.Build.DenseOfArray(new[] { 3.0, 0.0 })));

            Console.ReadLine();
        }

        static Vector<double> NumericalGradient(Func<Vector<double>, double> f, Vector<double> x)
        {
            var h = 0.0001;
            var grad = Vector<double>.Build.Dense(x.Count);

            foreach (var idx in Enumerable.Range(0, x.Count))
            {
                var tmpVal = x[idx];

                // f(x+h) の計算
                x[idx] = tmpVal + h;
                var fxh1 = f(x);

                // f(x-h) の計算
                x[idx] = tmpVal - h;
                var fxh2 = f(x);

                grad[idx] = (fxh1 - fxh2) / (2 * h);

                // 値を元に戻す
                x[idx] = tmpVal;
            }

            return grad;
        }
    }
}

実行結果がこちら。