パーセプトロンで論理回路を実装

『ゼロから作る Deep Learning』を読んでC# で実装してみたくなった。 問題は NumPy の変わりに何を使うかだけど、C# には Math.NET Numerics というのがある。

numerics.mathdotnet.com

ベクトルや行列の計算はできそう。テンソルはやってみないと分からない。 まずはパーセプトロン論理回路を実装するところからやってみた。

詳しくは『ゼロから作る Deep Learning』を読んでもらうとして、C# で実装するとこんな感じ。

using MathNet.Numerics.LinearAlgebra.Double;
using System;

namespace PerceptronSample
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("AND");
            Console.WriteLine("x1 x2 y");
            Console.WriteLine($"0  0  {AND(0, 0)}");
            Console.WriteLine($"1  0  {AND(1, 0)}");
            Console.WriteLine($"0  1  {AND(0, 1)}");
            Console.WriteLine($"1  1  {AND(1, 1)}");

            Console.WriteLine("OR");
            Console.WriteLine("x1 x2 y");
            Console.WriteLine($"0  0  {OR(0, 0)}");
            Console.WriteLine($"1  0  {OR(1, 0)}");
            Console.WriteLine($"0  1  {OR(0, 1)}");
            Console.WriteLine($"1  1  {OR(1, 1)}");

            Console.WriteLine("NAND");
            Console.WriteLine("x1 x2 y");
            Console.WriteLine($"0  0  {NAND(0, 0)}");
            Console.WriteLine($"1  0  {NAND(1, 0)}");
            Console.WriteLine($"0  1  {NAND(0, 1)}");
            Console.WriteLine($"1  1  {NAND(1, 1)}");

            Console.WriteLine("XOR");
            Console.WriteLine("x1 x2 y");
            Console.WriteLine($"0  0  {XOR(0, 0)}");
            Console.WriteLine($"1  0  {XOR(1, 0)}");
            Console.WriteLine($"0  1  {XOR(0, 1)}");
            Console.WriteLine($"1  1  {XOR(1, 1)}");

            Console.ReadLine();
        }

        static int AND(int x1, int x2)
        {
            var x = Vector.Build.DenseOfArray(new double[] { x1, x2 });
            var w = Vector.Build.DenseOfArray(new double[] { 0.5, 0.5 });
            var b = -0.7;
            
            // ベクトルの要素どうしの掛け算には PointwiseMultiply を使う
            var tmp = x.PointwiseMultiply(w).Sum() + b;
            if (tmp <= 0)
            {
                return 0;
            }
            else
            {
                return 1;
            }
        }

        static int OR(int x1, int x2)
        {
            var x = Vector.Build.DenseOfArray(new double[] { x1, x2 });
            var w = Vector.Build.DenseOfArray(new double[] { 0.5, 0.5 });
            var b = -0.2;
            var tmp = x.PointwiseMultiply(w).Sum() + b;
            if (tmp <= 0)
            {
                return 0;
            }
            else
            {
                return 1;
            }
        }

        static int NAND(int x1, int x2)
        {
            var x = Vector.Build.DenseOfArray(new double[] { x1, x2 });
            var w = Vector.Build.DenseOfArray(new double[] { -0.5, -0.5 });
            var b = 0.7;
            var tmp = x.PointwiseMultiply(w).Sum() + b;
            if (tmp <= 0)
            {
                return 0;
            }
            else
            {
                return 1;
            }
        }

        static int XOR(int x1, int x2)
        {
            // XOR ゲートは多層パーセプトロンで実現できる
            var s1 = NAND(x1, x2);
            var s2 = OR(x1, x2);
            var y = AND(s1, s2);
            return y;
        }
    }
}

実行結果。ちゃんと論理回路になっている。

Python + NumPy と比べると、コードが冗長になってしまうのは気にしない。