Nachahmung von Pythons Numpy in C #

Tiefes Lernen mit C #!

Reproduzierte Pythons Numpy-Bibliothek in C

Selbst wenn ich sage, dass ich es reproduziert habe, ist es nur ein Teil der Funktion, die ich kenne. Ich habe noch nicht angefangen, Deep Learning zu lernen. Ich habe O'Reillys "Make from Grund Deep Learning" gelesen und es irgendwie mit Python geschafft. Ich habe etwas in C # gemacht, das genauso funktioniert. C # hat keine Bibliothek wie Numpy (jemand hat möglicherweise eine erstellt, wenn Sie danach suchen), daher implementieren Sie sie selbst.

Ich habe schon einmal einen Artikel wie diesen gepostet.

Erstes tiefes Lernen in C # - Einleiten der Implementierung in Python-

Zu diesem Zeitpunkt habe ich es möglich gemacht, eine einfache Matrixberechnung durchzuführen, aber dieses Mal habe ich sie ein wenig verbessert.

Derzeit ist es möglicherweise schwer zu verstehen, aber ich werde das Python-Deep-Learning-Programm vorstellen, das ich in dieser Situation erstellt habe.

Programm mit Python gemacht

deeplearning.py


import numpy as np
import matplotlib.pylab as plt

def sigmoid(x):
    return 1 / (1+np.exp(-x))

def ident(x):
    return x

def numerical_gradient(f, x):
    h = 1e-4 # 0.0001
    grad = np.zeros_like(x)
    
    it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
    while not it.finished:
        idx = it.multi_index
        tmp_val = x[idx]
        x[idx] = tmp_val + h
        fxh1 = f(x) # f(x+h)
        
        x[idx] = tmp_val - h 
        fxh2 = f(x) # f(x-h)
        grad[idx] = (fxh1 - fxh2) / (2*h)
        
        x[idx] = tmp_val #Stellen Sie den Wert wieder her
        it.iternext()   
        
    return grad

def softmax(a):
    c=np.max(a)
    exp_a=np.exp(a-c)
    sum_exp_a=np.sum(exp_a)
    return exp_a/sum_exp_a

def diff(f,x):
    h=1e-4
    return (f(x+h)-f(x-h)/(2*h))

def cross_etp_err(y,t):
    delta=1e-7
    return -np.sum(t*np.log(y+delta))

class testnet:
    def __init__(self):
#-----------------------------------------------------
        self.X=np.array([1.0,0.5])
        self.W1=np.array([[0.0,0.0,0.0],[0.0,0.0,0.0]])
        self.B1=np.array([0.0,0.0,0.0])
#-----------------------------------------------------
        self.W2=np.array([[0.0,0.0],[0.0,0.0],[0.0,0.0]])
        self.B2=np.array([0.0,0.0])
#-----------------------------------------------------
        self.W3=np.array([[0.0,0.0],[0.0,0.0]])
        self.B3=np.array([0.0,0.0])
#-----------------------------------------------------
        self.T=np.array([0,1])

        self.w1_grad=np.zeros_like(self.W1)
        self.b1_grad=np.zeros_like(self.B1)
        self.w2_grad=np.zeros_like(self.W2)
        self.b2_grad=np.zeros_like(self.B2)
        self.w3_grad=np.zeros_like(self.W3)
        self.b3_grad=np.zeros_like(self.B3)
############################
    def loss(self):
        A1=np.dot(self.X,self.W1)+self.B1
        Z1=sigmoid(A1)
        A2=np.dot(Z1,self.W2)+self.B2
        Z2=sigmoid(A2)
        A3=np.dot(Z2,self.W3)+self.B3
        Y=softmax(A3)
        return cross_etp_err(Y,self.T)
############################
net = testnet()

def f(W):
    return net.loss()

rate=0.1

def deep_learning(net):
    net.w1_grad=numerical_gradient(f,net.W1)
    net.b1_grad=numerical_gradient(f,net.B1) 
    net.w2_grad=numerical_gradient(f,net.W2)
    net.b2_grad=numerical_gradient(f,net.B2)
    net.w3_grad=numerical_gradient(f,net.W3)
    net.b3_grad=numerical_gradient(f,net.B3)

    
    net.W1-=rate*net.w1_grad
    net.B1-=rate*net.b1_grad
    net.W2-=rate*net.w2_grad
    net.B2-=rate*net.b2_grad
    net.W3-=rate*net.w3_grad
    net.B3-=rate*net.b3_grad

loop=0;
while loop<100:
    deep_learning(net)
    print(str(loop)+":"+str(net.B3[0]))
    loop+=1

Imitieren Sie Numpy und implementieren Sie es in C

deeplearning.cs


using System.Linq;

namespace Matrix
{
    class Mat
    {
        private int r = 0;
        public int R
        {
            get { return r; }
        }
        private int c = 0;
        public int C
        {
            get { return c; }
        }
        private bool err = false;
        public bool Err
        {
            get { return err; }
        }
        private double[][] matrix_data;
        public double[][] Matrix_data
        {
            get {
                double[][] a = new double[2][];
                a[0] = new double[] { 0, 0 };
                a[1] = new double[] { 0, 0 };
                if (err) return a;
                else return matrix_data;
            }
            set
            {
                matrix_data = value;
            }
        }
        public double[][] Zero_matrix
        {
            get
            {
                double[][] zm = new double[this.r][];
                for (int i = 0; i < this.r; i++)
                {
                    zm[i] = new double[this.c];
                    for (int j = 0; j < this.c; j++)
                    {
                        zm[i][j] = 0;
                    }
                }
                return zm;
            }
        }
        public Mat(params double[][] vs)
        {
            int len = vs[0].Length;

            for (int i = 0; i < vs.Length; i++)
            {
                if (i != 0 && len != vs[i].Length)
                {
                    err = true;
                }
            }
            if (!err)
            {
                r = vs.Length;
                c = vs[0].Length;
                matrix_data = vs;
            }
        }
        public double[][] sigmoid()
        {
            double[][] sig = new double[1][];
            sig[0] = new double[this.c];

            for(int i = 0; i < this.c; i++)
            {
                sig[0][i] = 1 / (1 + System.Math.Exp(this.matrix_data[0][i]));
            }

            return sig;
        }
        public double[][] softmax()
        {
            double[][] sm = new double[1][];
            sm[0] = new double[this.c];

            double m = this.matrix_data[0].Max();

            double[] exp_a = new double[this.c];
            for (int i = 0; i < this.c; i++)
            {
                exp_a[i] = System.Math.Exp(this.matrix_data[0][i] - m);
            }

            double sum = 0.0;
            for (int i = 0; i < this.c; i++)
            {
                sum = sum + exp_a[i];
            }

            for (int i = 0; i < this.c; i++)
            {
                sm[0][i] = exp_a[i] / sum;
            }

            return sm;
        }
        public double cross_etp_err(Mat t)
        {
            double delta = 0.0000001;
            double sum = 0.0;
            for (int i = 0; i < this.c; i++)
            {
                sum = sum + t.matrix_data[0][i] * System.Math.Log(this.matrix_data[0][i] + delta);
            }

            return -sum;
        }
        public double[][] numerical_gradient(System.Func<double> loss)
        {
            double h = 0.0001;
            double[][] grad = new double[this.r][];
            double tmp_val = 0.0;
            double fxh1 = 0.0;
            double fxh2 = 0.0;

            for(int i = 0; i < this.r; i++)
            {
                grad[i] = new double[this.c];
                for(int j = 0; j < this.c; j++)
                {
                    tmp_val = this.matrix_data[i][j];
                    this.matrix_data[i][j] = tmp_val + h;
                    fxh1 = loss();

                    this.matrix_data[i][j] = tmp_val - h;
                    fxh2 = loss();

                    grad[i][j] = (fxh1 - fxh2) / (2 * h);
                    this.matrix_data[i][j] = tmp_val;
                }
            }

            return grad;
        }
        //Unterhalb der Bedienerüberlastung
        public static double[][] operator +(Mat p1, Mat p2)
        {
            double[][] d = new double[p1.R][];

            if (p1.C == p2.C && p1.R == p2.R)
            {
                for (int i = 0; i < p1.R; i++)
                {
                    d[i] = new double[p1.C];
                    for (int j = 0; j < p1.C; j++)
                    {
                        d[i][j] = p1.Matrix_data[i][j] + p2.Matrix_data[i][j];
                    }
                }
            }
            else
            {
                for (int k = 0; k < p1.R; k++)
                {
                    d[k] = new double[2] { 0, 0 };
                }
            }

            return d;
        }
        public static double[][] operator +(double[][] p1, Mat p2)
        {
            double[][] d = new double[p1.Length][];

            if (p1[0].Length == p2.C && p1.Length == p2.R)
            {
                for (int i = 0; i < p1.Length; i++)
                {
                    d[i] = new double[p1[0].Length];
                    for (int j = 0; j < p1[0].Length; j++)
                    {
                        d[i][j] = p1[i][j] + p2.Matrix_data[i][j];
                    }
                }
            }
            else
            {
                for (int k = 0; k < p1.Length; k++)
                {
                    d[k] = new double[2] { 0, 0 };
                }
            }

            return d;
        }
        public static double[][] operator +(Mat p1, double[][] p2)
        {
            double[][] d = new double[p1.R][];

            if (p1.C == p2[0].Length && p1.R == p2.Length)
            {
                for (int i = 0; i < p1.R; i++)
                {
                    d[i] = new double[p1.C];
                    for (int j = 0; j < p1.C; j++)
                    {
                        d[i][j] = p1.Matrix_data[i][j] + p2[i][j];
                    }
                }
            }
            else
            {
                for (int k = 0; k < p1.R; k++)
                {
                    d[k] = new double[2] { 0, 0 };
                }
            }

            return d;
        }
        public static double[][] operator +(double p1, Mat p2)
        {
            double[][] d = new double[p2.R][];
            for (int i = 0; i < p2.R; i++)
            {
                d[i] = new double[p2.C];
                for (int j = 0; j < p2.C; j++)
                {
                    d[i][j] = p2.Matrix_data[i][j] + p1;
                }
            }

            return d;
        }
        public static double[][] operator +(Mat p1, double p2)
        {
            double[][] d = new double[p1.R][];
            for (int i = 0; i < p1.R; i++)
            {
                d[i] = new double[p1.C];
                for (int j = 0; j < p1.C; j++)
                {
                    d[i][j] = p1.Matrix_data[i][j] + p2;
                }
            }

            return d;
        }
        public static double[][] operator -(Mat p1, Mat p2)
        {
            double[][] d = new double[p1.R][];

            if (p1.C == p2.C && p1.R == p2.R)
            {
                for (int i = 0; i < p1.R; i++)
                {
                    d[i] = new double[p1.C];
                    for (int j = 0; j < p1.C; j++)
                    {
                        d[i][j] = p1.Matrix_data[i][j] - p2.Matrix_data[i][j];
                    }
                }
            }
            else
            {
                for (int k = 0; k < p1.R; k++)
                {
                    d[k] = new double[2] { 0, 0 };
                }
            }

            return d;
        }
        public static double[][] operator -(double[][] p1, Mat p2)
        {
            double[][] d = new double[p1.Length][];

            if (p1[0].Length == p2.C && p1.Length == p2.R)
            {
                for (int i = 0; i < p1.Length; i++)
                {
                    d[i] = new double[p1[0].Length];
                    for (int j = 0; j < p1[0].Length; j++)
                    {
                        d[i][j] = p1[i][j] - p2.Matrix_data[i][j];
                    }
                }
            }
            else
            {
                for (int k = 0; k < p1.Length; k++)
                {
                    d[k] = new double[2] { 0, 0 };
                }
            }

            return d;
        }
        public static double[][] operator -(Mat p1, double[][] p2)
        {
            double[][] d = new double[p1.R][];

            if (p1.C == p2[0].Length && p1.R == p2.Length)
            {
                for (int i = 0; i < p1.R; i++)
                {
                    d[i] = new double[p1.C];
                    for (int j = 0; j < p1.C; j++)
                    {
                        d[i][j] = p1.Matrix_data[i][j] - p2[i][j];
                    }
                }
            }
            else
            {
                for (int k = 0; k < p1.R; k++)
                {
                    d[k] = new double[2] { 0, 0 };
                }
            }

            return d;
        }

        public static double[][] operator -(double p1, Mat p2)
        {
            double[][] d = new double[p2.R][];
            for (int i = 0; i < p2.R; i++)
            {
                d[i] = new double[p2.C];
                for (int j = 0; j < p2.C; j++)
                {
                    d[i][j] = p1 - p2.Matrix_data[i][j];
                }
            }

            return d;
        }
        public static double[][] operator -(Mat p1, double p2)
        {
            double[][] d = new double[p1.R][];
            for (int i = 0; i < p1.R; i++)
            {
                d[i] = new double[p1.C];
                for (int j = 0; j < p1.C; j++)
                {
                    d[i][j] = p1.Matrix_data[i][j] - p2;
                }
            }

            return d;
        }
        public static double[][] operator *(Mat p1, Mat p2)
        {
            double[][] d = new double[p1.R][];

            if (p1.C == p2.C && p1.R == p2.R)
            {
                for (int i = 0; i < p1.R; i++)
                {
                    d[i] = new double[p1.C];
                    for (int j = 0; j < p1.C; j++)
                    {
                        d[i][j] = p1.Matrix_data[i][j] * p2.Matrix_data[i][j];
                    }
                }
            }
            else
            {
                for (int k = 0; k < p1.R; k++)
                {
                    d[k] = new double[2] { 0, 0 };
                }
            }

            return d;
        }
        public static double[][] operator *(double[][] p1, Mat p2)
        {
            double[][] d = new double[p1.Length][];

            if (p1[0].Length == p2.C && p1.Length == p2.R)
            {
                for (int i = 0; i < p1.Length; i++)
                {
                    d[i] = new double[p1[0].Length];
                    for (int j = 0; j < p1[0].Length; j++)
                    {
                        d[i][j] = p1[i][j] * p2.Matrix_data[i][j];
                    }
                }
            }
            else
            {
                for (int k = 0; k < p1.Length; k++)
                {
                    d[k] = new double[2] { 0, 0 };
                }
            }

            return d;
        }
        public static double[][] operator *(Mat p1, double[][] p2)
        {
            double[][] d = new double[p1.R][];

            if (p1.C == p2[0].Length && p1.R == p2.Length)
            {
                for (int i = 0; i < p1.R; i++)
                {
                    d[i] = new double[p1.C];
                    for (int j = 0; j < p1.C; j++)
                    {
                        d[i][j] = p1.Matrix_data[i][j] * p2[i][j];
                    }
                }
            }
            else
            {
                for (int k = 0; k < p1.R; k++)
                {
                    d[k] = new double[2] { 0, 0 };
                }
            }

            return d;
        }

        public static double[][] operator *(double p1, Mat p2)
        {
            double[][] d = new double[p2.R][];
            for (int i = 0; i < p2.R; i++)
            {
                d[i] = new double[p2.C];
                for (int j = 0; j < p2.C; j++)
                {
                    d[i][j] = p1 * p2.Matrix_data[i][j];
                }
            }

            return d;
        }
        public static double[][] operator *(Mat p1, double p2)
        {
            double[][] d = new double[p1.R][];
            for (int i = 0; i < p1.R; i++)
            {
                d[i] = new double[p1.C];
                for (int j = 0; j < p1.C; j++)
                {
                    d[i][j] = p1.Matrix_data[i][j] * p2;
                }
            }

            return d;
        }
        public static double[][] operator /(Mat p1, Mat p2)
        {
            double[][] d = new double[p1.R][];

            if (p1.C == p2.C && p1.R == p2.R)
            {
                for (int i = 0; i < p1.R; i++)
                {
                    d[i] = new double[p1.C];
                    for (int j = 0; j < p1.C; j++)
                    {
                        d[i][j] = p1.Matrix_data[i][j] / p2.Matrix_data[i][j];
                    }
                }
            }
            else
            {
                for (int k = 0; k < p1.R; k++)
                {
                    d[k] = new double[2] { 0, 0 };
                }
            }

            return d;
        }
        public static double[][] operator /(double[][] p1, Mat p2)
        {
            double[][] d = new double[p1.Length][];

            if (p1[0].Length == p2.C && p1.Length == p2.R)
            {
                for (int i = 0; i < p1.Length; i++)
                {
                    d[i] = new double[p1[0].Length];
                    for (int j = 0; j < p1[0].Length; j++)
                    {
                        d[i][j] = p1[i][j] / p2.Matrix_data[i][j];
                    }
                }
            }
            else
            {
                for (int k = 0; k < p1.Length; k++)
                {
                    d[k] = new double[2] { 0, 0 };
                }
            }

            return d;
        }
        public static double[][] operator /(Mat p1, double[][] p2)
        {
            double[][] d = new double[p1.R][];

            if (p1.C == p2[0].Length && p1.R == p2.Length)
            {
                for (int i = 0; i < p1.R; i++)
                {
                    d[i] = new double[p1.C];
                    for (int j = 0; j < p1.C; j++)
                    {
                        d[i][j] = p1.Matrix_data[i][j] / p2[i][j];
                    }
                }
            }
            else
            {
                for (int k = 0; k < p1.R; k++)
                {
                    d[k] = new double[2] { 0, 0 };
                }
            }

            return d;
        }

        public static double[][] operator /(double p1, Mat p2)
        {
            double[][] d = new double[p2.R][];
            for (int i = 0; i < p2.R; i++)
            {
                d[i] = new double[p2.C];
                for (int j = 0; j < p2.C; j++)
                {
                    d[i][j] = p1 / p2.Matrix_data[i][j];
                }
            }

            return d;
        }
        public static double[][] operator /(Mat p1, double p2)
        {
            double[][] d = new double[p1.R][];
            for (int i = 0; i < p1.R; i++)
            {
                d[i] = new double[p1.C];
                for (int j = 0; j < p1.C; j++)
                {
                    d[i][j] = p1.Matrix_data[i][j] / p2;
                }
            }

            return d;
        }
        public static double[][] dot(Mat p1, Mat p2)
        {
            double[][] d = new double[p1.R][];
            double temp = 0;

            if (p1.C == p2.R)
            {
                for (int i = 0; i < p1.R; i++)
                {
                    d[i] = new double[p2.C];
                    for (int j = 0; j < p2.C; j++)
                    {
                        for(int a = 0; a < p1.C; a++)
                        {
                            temp = temp + p1.Matrix_data[i][a] * p2.Matrix_data[a][j];
                        }
                        d[i][j] = temp;
                        temp = 0.0;
                    }
                }
            }
            else
            {
                for (int k = 0; k < p1.R; k++)
                {
                    d[k] = new double[2] { 0, 0 };
                }
            }

            return d;
        }
    }
}

Da es in einer Klasse zusammengefasst ist, kann es auch als Bibliothek verwendet werden.

C # Deep Learning Programm

main.cs


namespace Matrix
{
    class Program
    {
        static Mat X = new Mat(
                new double[] { 1.0, 0.5 }
                ),
            W1 = new Mat(
                new double[] { 0.0, 0.0, 0.0 },
                new double[] { 0.0, 0.0, 0.0 }
                ),
            B1 = new Mat(
                new double[] { 0.0, 0.0, 0.0 }
                ),
            W2 = new Mat(
                new double[] { 0.0, 0.0 },
                new double[] { 0.0, 0.0 },
                new double[] { 0.0, 0.0 }
                ),
            B2 = new Mat(
                new double[] { 0.0, 0.0 }
                ),
            W3 = new Mat(
                new double[] { 0.0, 0.0 },
                new double[] { 0.0, 0.0 }
                ),
            B3 = new Mat(
                new double[] { 0.0, 0.0 }
                ),
            T = new Mat(
                new double[] { 0, 1 }
                );

        static double loss()
        {
            Mat A1 = new Mat(
                new double[] { 0.0, 0.0, 0.0 }
                ),
                Z1 = new Mat(
                new double[] { 0.0, 0.0, 0.0 }
                ),
                A2 = new Mat(
                new double[] { 0.0, 0.0 }
                ),
                Z2 = new Mat(
                new double[] { 0.0, 0.0 }
                ),
                A3 = new Mat(
                new double[] { 0.0, 0.0 }
                ),
                Y = new Mat(
                new double[] { 0.0, 0.0 }
                );

            double[][] eeeeee = Mat.dot(X, W1);

            A1.Matrix_data = Mat.dot(X, W1) + B1;
            Z1.Matrix_data = A1.sigmoid();
            A2.Matrix_data = Mat.dot(Z1, W2) + B2;
            Z2.Matrix_data = A2.sigmoid();
            A3.Matrix_data = Mat.dot(Z2, W3) + B3;
            Y.Matrix_data = A3.softmax();

            return Y.cross_etp_err(T);
        }
        static void Main(string[] args)
        {
            double rate = 0.1;

            Mat W1_grad = new Mat(W1.Zero_matrix),
                B1_grad = new Mat(B1.Zero_matrix),
                W2_grad = new Mat(W2.Zero_matrix),
                B2_grad = new Mat(B2.Zero_matrix),
                W3_grad = new Mat(W3.Zero_matrix),
                B3_grad = new Mat(B3.Zero_matrix);
            for (int i = 0; i < 100; i++)
            {
                W1_grad.Matrix_data = W1.numerical_gradient(loss);
                B1_grad.Matrix_data = B1.numerical_gradient(loss);
                W2_grad.Matrix_data = W2.numerical_gradient(loss);
                B2_grad.Matrix_data = B2.numerical_gradient(loss);
                W3_grad.Matrix_data = W3.numerical_gradient(loss);
                B3_grad.Matrix_data = B3.numerical_gradient(loss);

                W1.Matrix_data = W1 - (rate * W1_grad);
                B1.Matrix_data = B1 - (rate * B1_grad);
                W2.Matrix_data = W2 - (rate * W2_grad);
                B2.Matrix_data = B2 - (rate * B2_grad);
                W3.Matrix_data = W3 - (rate * W3_grad);
                B3.Matrix_data = B3 - (rate * B3_grad);

                System.Console.WriteLine(i.ToString() + ":" + B3.Matrix_data[0][0].ToString());
            }
        }
    }
}

Argumente im Konstruktor der Mat-Klasse haben den Typ params double [] oderdouble [] []. Sie können "Mat", reelle Zahlen und "double [] []" addieren, subtrahieren, multiplizieren und dividieren. Zusätzlich ist es möglich, die Softmax-Funktion, die Sigmoid-Funktion, die Gradientenberechnung, den Toleranzentropiefehler usw. zu berechnen.

Recommended Posts

Nachahmung von Pythons Numpy in C #
wo von numpy
Verarbeiten Sie Signale in C-Sprache
Achsenspezifikation mit NumPy
Greifen Sie auf MongoDB in C zu
C-API in Python 3
Erweitern Sie Python in C ++ (Boost.NumPy)
Einbettung der Maschinensprache in die Sprache C.
Heap-Sortierung in C-Sprache
Verwenden Sie reguläre Ausdrücke in C.
Matrixprodukt in Python numpy
Binäre Suche in Python / C ++
Minimaler Gesamtflächenbaum in C #
Beschleunigen Sie den Zhang-Suen-Algorithmus in Numpy
Schreiben Sie einen tabellengesteuerten Test in C.
Realisieren Sie die Schnittstellenklasse in der Sprache C.
ABC166 in Python A ~ C Problem
Selbstorganisierende Karte in der Python NumPy-Version
[Numpy] Rufen Sie savetxt () im Append-Modus auf
Beim Lesen der C ++ - Struktur mit Cython
Löse ABC036 A ~ C mit Python
So verpacken Sie C in Python
Löse ABC037 A ~ C mit Python
Invertiere numpy Boolean Array in Tilda
Segfo mit 16 Zeichen in C-Sprache
Schreiben Sie einen C-Sprach-Unit-Test in Python