[PYTHON] Ein Amateur stolperte in Deep Learning von Grund auf neu Hinweis: Kapitel 5

Einführung

Ich begann plötzlich in Kapitel 5 von "Deep Learning von Grund auf neu - Theorie und Implementierung des mit Python erlernten Deep Learning". Es ist ein Memo der Reise.

Die Ausführungsumgebung ist macOS Mojave + Anaconda 2019.10 und die Python-Version ist 3.7.4. Weitere Informationen finden Sie in Kapitel 1 dieses Memos.

(Zu anderen Kapiteln dieses Memos: Kapitel 1 / Kapitel 2 / Kapitel 3 / Kapitel 4 / Kapitel 5 / [Kapitel 6](https: / /qiita.com/segavvy/items/ca4ac4c9ee1a126bff41) / Kapitel 7 / Kapitel 8 / Zusammenfassung)

Kapitel 5 Fehlerrückverbreitungsmethode

In diesem Kapitel wird die Fehler-Backpropagation-Methode zur Beschleunigung der Berechnung von Gewichtsparametern beim Lernen neuronaler Netze beschrieben.

Das Wort "Propagation" (denpa) ist übrigens eine Übersetzung von Propagetion, aber es wird auch als "Propagation" (denpan) übersetzt, und Japanisch ist chaotisch. Ich habe einen Artikel in einem Blog gefunden, der diesen Bereich untersucht hat. Wenn Sie also interessiert sind, Pause nach dem Gehen> [maschinelles Lernen] Die Übersetzung von "Propagation" ist "Propagation" oder "Propagation"? Bitte.

5.1 Berechnungsdiagramm

Die Erklärung durch das Berechnungsdiagramm ist sehr leicht zu verstehen, wenn Sie die Methode der Fehlerrückübertragung lernen. Das Geheimnis für die Popularität dieses Buches könnte Kapitel 5 sein.

Lernen ist für neuronale Netze unerlässlich, bei denen der Gradient der Gewichtsparameter ermittelt und die Differenzierung der einzelnen Parameter berechnet werden muss. Anhand des Berechnungsdiagramms können wir sehen, dass die Berechnung des Differentials sehr effizient durchgeführt werden kann, indem das lokale Differential von hinten nach vorne zurückpropagiert wird.

5.2 Kettenregel

Dies ist eine Überprüfung der Differentialformel der zusammengesetzten Funktion und der Erklärung, die die Rückausbreitung enthält. Ich denke nicht, dass es ein Problem ist, es durchzulesen, aber wenn Sie es richtig verstehen wollen, müssen Sie die Differenzierung der High School überprüfen.

Ich erinnerte mich überhaupt nicht an die Differentialformel und beschloss, sie nach langer Zeit zu überprüfen. Ich lerne jedoch oft, nachdem mein Hauptgeschäft beendet ist, und wenn es um Bücher und Websites geht, greift mich Schläfrigkeit an und es fällt mir schwer, mich daran zu erinnern. Für einen Angestellten ist es ziemlich schwierig, in der Lückenzeit zu studieren.

Was ich dort gefunden habe, war Triit, das von einem Heimlehrer, Try, durchgeführt wird. Obwohl es sich um eine Videolektion handelt, ist sie sehr einfach zu verstehen, obwohl sie kostenlos ist. Sie ist in etwa 15 Minuten unterteilt und eignet sich daher ideal zum Lernen mit einem Smartphone auf Reisen oder in einer Pause. Es ist ein Service für Studenten, aber ich denke, es ist auch sehr gut geeignet, um arbeitende Menschen zu überprüfen.

Als Referenz finden Sie hier einen Link zu einem Video über den einleitenden Teil der Differenzierung. Bitte beachten Sie, dass dies auf die private Anzeige beschränkt ist.

5.3 Backpropagation

Eine Beschreibung der Backpropagation von Add- und Multiplikationsknoten. Die Rückausbreitung ist einfach zu berechnen, da die Differenzierung sowohl für die Addition als auch für die Multiplikation einfach ist.

5.4 Einfache Layer-Implementierung

Dies ist die Implementierung der Additionsschicht und der Multiplikationsschicht im vorherigen Abschnitt. Da die Unterscheidung einfach ist, ist sie leicht zu implementieren.

5.5 Implementierung der Aktivierungsfunktionsschicht

Eine Implementierung der Aktivierungsfunktionsschicht.

5.5.1 ReLU-Schicht

Da ReLU eine einfache Differenzierungsberechnung hat, ist es einfach zu implementieren und scheint zu einem schnelleren Lernen zu führen. Unten ist der implementierte Code.

relu.py


# coding: utf-8


class ReLU:
    def __init__(self):
        """ReLU-Schicht
        """
        self.mask = None

    def forward(self, x):
        """Vorwärtsausbreitung
        
        Args:
            x (numpy.ndarray):Eingang
            
        Returns:
            numpy.ndarray:Ausgabe
        """
        self.mask = (x <= 0)
        out = x.copy()
        out[self.mask] = 0

        return out

    def backward(self, dout):
        """Backpropagation
        
        Args:
            dout (numpy.ndarray):Differenzierungswert von der rechten Schicht übertragen
        
        Returns:
            numpy.ndarray:Differenzierungswert
        """
        dout[self.mask] = 0
        dx = dout

        return dx

5.5.2 Sigmoidschicht

Die Unterscheidung der Sigmoidfunktion ist etwas kompliziert, kann aber nach und nach anhand des Berechnungsgraphen berechnet werden. Die für den ersten "/" Knoten erforderliche Differenzierung $ y = \ frac {1} {x} $ und die Differenzierung $ y = exp (x) $ für den Knoten "$ exp $" überprüfen die Formel jedoch nicht. Es ist scharf. Für die Formeln in diesem Bereich wird empfohlen, Mathematik aus konkreten Beispielen gelernt> Kleine Integration> Alle 59 Differentialformeln sind nach Wichtigkeit geordnet einfach zu organisieren.

Nach der Berechnung mit dem Berechnungsdiagramm wird es in die Formel (5.12) im Buch umgewandelt, aber zuerst habe ich den Ablauf der Transformation der zweiten Zeile vom Ende zur letzten Zeile nicht verstanden. Es ist einfacher zu verstehen, wenn Sie eine Zeile dazwischen wie folgt einfügen.

\begin{align}
\frac{\partial L}{\partial y}y^2exp(-x) &= \frac{\partial L}{\partial y} \frac{1}{(1+exp(-x))^2} exp(-x) \\
&=\frac{\partial L}{\partial y} \frac{1}{1+exp(-x)} \frac{exp(-x)}{1+exp(-x)} \\
&=\frac{\partial L}{\partial y} \frac{1}{1+exp(-x)} \biggl(\frac{1+exp(-x)}{1+exp(-x)} - \frac{1}{1+exp(-x)}\biggr)← Zeile hinzugefügt\\
&=\frac{\partial L}{\partial y} y(1-y)

\end{align}

Was an diesem Ergebnis überrascht, ist, dass es sehr einfach ist, mit $ y $ zu berechnen, was die Ausgabe der Vorwärtsausbreitung ist. Bei der Fehler-Rück-Ausbreitungsmethode wird zuerst die Vorwärts-Ausbreitung berechnet. Wenn Sie also das Ergebnis haben, führt dies zu einem schnelleren Lernen. Die Eigenschaft, dass selbst wenn $ e ^ x $ differenziert wird, es zu $ e ^ x $ wird, ist ebenfalls wichtig, und es ist wirklich erstaunlich für diejenigen, die über die Sigmoidfunktion nachdenken.

Die Sigmoidschicht wird in diesem Kapitel nicht verwendet, daher wird der Code weggelassen.

5.6 Implementierung der Affine / Softmax-Schicht

5.6.1 Affine Schicht

Der Berechnungsprozess wird in der Backpropagation-Formel der affinen Ebene (5.13) weggelassen, aber @yuyasat [berechnet die Komponenten der Backpropagation der affinen Ebene stetig](https://qiita.com/yuyasat/items/ Der Berechnungsprozess ist in d9cdd4401221df5375b6) als Referenz zusammengefasst.

5.6.2 Stapelversion Affine Ebene

Unten ist der implementierte Code. Darüber hinaus wird im Code des Buches berücksichtigt, wann die Eingabedaten Tensor (4D-Daten) sind, sie sind jedoch nicht enthalten, da die Verwendung noch nicht bekannt ist.

affine.py


# coding: utf-8
import numpy as np


class Affine:

    def __init__(self, W, b):
        """Affine Schicht
        
        Args:
            W (numpy.ndarray):Gewicht
            b (numpy.ndarray):vorspannen
        """
        self.W = W      #Gewicht
        self.b = b      #vorspannen
        self.x = None   #Eingang
        self.dW = None  #Differenzwert des Gewichts
        self.db = None  #Differenzwert der Vorspannung

    def forward(self, x):
        """Vorwärtsausbreitung
        
        Args:
            x (numpy.ndarray):Eingang
            
        Returns:
            numpy.ndarray:Ausgabe
        """
        self.x = x
        out = np.dot(x, self.W) + self.b

        return out

    def backward(self, dout):
        """Backpropagation
        
        Args:
            dout (numpy.ndarray):Differenzierungswert von der rechten Schicht übertragen

        Returns:
            numpy.ndarray:Differenzierungswert
        """
        dx = np.dot(dout, self.W.T)
        self.dW = np.dot(self.x.T, dout)
        self.db = np.sum(dout, axis=0)

        return dx

5.6.3 Softmax-with-Loss-Schicht

Backpropagation einer Schicht mit einer Softmax-Funktion und einem gekreuzten Entropiefehler als Satz. Der Berechnungsprozess wird ausführlich in Anhang A des Buches beschrieben, aber selbst wenn $ e ^ x $ differenziert wird, wird er zu $ e ^ x $, und wenn alle One-Hot-Vektoren des Lehrerlabels hinzugefügt werden, wird er zu 1. Usw. zur Vereinfachung der Formel beitragen.

Das Endergebnis von $ (y_1-t_1, y_2-t_2, y_3-t_3) $ ist ebenfalls überraschend. Es zeigt den Unterschied zwischen der Ausgabe des neuronalen Netzwerks und der Lehrerbezeichnung und kann schnell berechnet werden. Es scheint, dass der Kreuzentropiefehler als "sauber" ausgelegt ist, wenn er als Verlustfunktion der Softmax-Funktion verwendet wird, und es ist wirklich erstaunlich für diejenigen, die über den Kreuzentropiefehler nachdenken.

Beachten Sie, dass der Backpropagation-Wert durch die Anzahl der Stapel geteilt werden muss, um Stapel aufzunehmen. In dem Buch gab es nur eine Erklärung, dass "durch Teilen des zu propagierenden Werts durch die Anzahl der Stapel (batch_size) der Fehler pro Daten auf die vorherige Ebene übertragen wird", und ich konnte nicht verstehen, warum es notwendig war, durch die Anzahl der Stapel zu dividieren. Ich konnte es jedoch anhand der Erklärung des Codes von @ Yoko303s Deep Learning von Grund auf ~ Softmax-with-Loss-Ebene ~ verstehen. In der Batch-Version der Vorwärtsausbreitung werden die Kreuzentropiefehler schließlich summiert und durch die Anzahl der Batches (batch_size) dividiert, um einen Wert zu erhalten. Die Backpropagation erfordert auch die Berechnung dieses Teils, und sein Differenzwert ist $ \ frac {1} {batch_size} $. Unten habe ich das Berechnungsdiagramm für diesen Teil geschrieben.

計算グラフ.png

Ich denke, dieses Verständnis ist richtig, aber bitte weisen Sie auf Fehler hin. Unten ist der implementierte Code.

softmax_with_loss.py


# coding: utf-8
from functions import softmax, cross_entropy_error


class SoftmaxWithLoss:
    def __init__(self):
        """Softmax-with-Verlustschicht
        """
        self.loss = None    #Verlust
        self.y = None       #Ausgabe von Softmax
        self.t = None       #Lehrerdaten (eins-hot vector)

    def forward(self, x, t):
        """Vorwärtsausbreitung
        
        Args:
            x (numpy.ndarray):Eingang
            t (numpy.ndarray):Lehrerdaten

        Returns:
            float:Kreuzentropiefehler
        """
        self.t = t
        self.y = softmax(x)
        self.loss = cross_entropy_error(self.y, self.t)

        return self.loss

    def backward(self, dout=1):
        """Backpropagation
        
        Args:
            dout (float, optional):Der von der rechten Schicht übertragene Differenzwert. Der Standardwert ist 1.

        Returns:
            numpy.ndarray:Differenzierungswert
        """
        batch_size = self.t.shape[0]    #Anzahl der Chargen
        dx = (self.y - self.t) * (dout / batch_size)

        return dx

Beachten Sie, dass der Code im Buch nicht "dout" in "backward" verwendet. Da dout nur mit 1 angegeben wird, gibt es kein Problem im Betrieb, aber ich denke, es ist wahrscheinlich ein Fehler.

5.7 Implementierung der Fehlerrückverbreitungsmethode

5.7.1 Gesamtansicht des Lernens in neuronalen Netzen

Dies ist eine Überprüfung des Implementierungsablaufs. Es gibt keinen besonderen Stolperstein.

5.7.2 Implementierung eines neuronalen Netzwerks, das die Methode der Fehlerrückübertragung unterstützt

Erstens ist die Implementierung von Allzweckfunktionen. Ich habe nur das mitgebracht, was ich brauchte, was ich im vorigen Kapitel geschrieben habe.

functions.py


# coding: utf-8
import numpy as np


def softmax(x):
    """Softmax-Funktion
    
    Args:
        x (numpy.ndarray):Eingang
    
    Returns:
        numpy.ndarray:Ausgabe
    """
    #Für die Stapelverarbeitung ist x(Anzahl der Chargen, 10)Es wird eine zweidimensionale Anordnung von.
    #In diesem Fall ist es erforderlich, für jedes Bild, das gesendet wird, eine gute Berechnung durchzuführen.
    #Hier np, damit es in 1 und 2 Dimensionen geteilt werden kann..max()Und np.sum()Ist Achse=-Berechnet mit 1
    #Keepdims, damit es so gesendet werden kann, wie es ist=True, um die Dimension beizubehalten.
    c = np.max(x, axis=-1, keepdims=True)
    exp_a = np.exp(x - c)  #Überlaufmaßnahmen
    sum_exp_a = np.sum(exp_a, axis=-1, keepdims=True)
    y = exp_a / sum_exp_a
    return y


def numerical_gradient(f, x):
    """Gradientenberechnung
    
    Args:
        f (function):Verlustfunktion
        x (numpy.ndarray):Ein Array von Gewichtungsparametern, für die Sie den Verlauf überprüfen möchten
    
    Returns:
        numpy.ndarray:Steigung
    """
    h = 1e-4
    grad = np.zeros_like(x)

    # np.Zählen Sie die Elemente eines mehrdimensionalen Arrays mit nditer auf
    it = np.nditer(x, flags=['multi_index'])
    while not it.finished:

        idx = it.multi_index  # it.multi_Index ist die Elementnummer in der Liste
        tmp_val = x[idx]  #Originalwert speichern

        # f(x + h)Berechnung von
        x[idx] = tmp_val + h
        fxh1 = f()

        # f(x - h)Berechnung von
        x[idx] = tmp_val - h
        fxh2 = f()

        #Berechnen Sie den Gradienten
        grad[idx] = (fxh1 - fxh2) / (2 * h)
    
        x[idx] = tmp_val  #Rückgabewert
        it.iternext()

    return grad


def cross_entropy_error(y, t):
    """Berechnung des Kreuzentropiefehlers
    
    Args:
        y (numpy.ndarray):Neuronale Netzwerkausgabe
        t (numpy.ndarray):Richtiges Antwortetikett
    
    Returns:
        float:Kreuzentropiefehler
    """

    #Wenn es Daten gibt, formen Sie sie (machen Sie eine Datenzeile)
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)

    #Berechnen Sie den Fehler und normalisieren Sie ihn anhand der Anzahl der Chargen
    batch_size = y.shape[0]
    return -np.sum(t * np.log(y + 1e-7)) / batch_size

Und dann ist da noch die Klasse der neuronalen Netze. Da es auf dem Code im vorherigen Kapitel basiert, gibt es viele der gleichen Teile.

two_layer_net.py


# coding: utf-8
import numpy as np
from affine import Affine
from functions import numerical_gradient
from relu import ReLU
from softmax_with_loss import SoftmaxWithLoss


class TwoLayerNet:

    def __init__(self, input_size, hidden_size, output_size,
                 weight_init_std=0.01):
        """Zweischichtiges neuronales Netzwerk
        
        Args:
            input_size (int):Anzahl der Neuronen in der Eingabeschicht
            hidden_size (int):Anzahl der Neuronen mit versteckter Schicht
            output_size (int):Anzahl der Neuronen in der Ausgabeschicht
            weight_init_std (float, optional):Einstellparameter des Anfangswertes des Gewichts. Der Standardwert ist 0.01。
        """

        #Gewichtsinitialisierung
        self.params = {}
        self.params['W1'] = weight_init_std * \
            np.random.randn(input_size, hidden_size)
        self.params['b1'] = np.zeros(hidden_size)
        self.params['W2'] = weight_init_std * \
            np.random.randn(hidden_size, output_size)
        self.params['b2'] = np.zeros(output_size)

        #Schichterzeugung
        self.layers = {}    # Python 3.OrderedDict ist nicht erforderlich, da die Speicherreihenfolge des Wörterbuchs von 7 beibehalten wird
        self.layers['Affine1'] = \
            Affine(self.params['W1'], self.params['b1'])
        self.layers['Relu1'] = ReLU()
        self.layers['Affine2'] = \
            Affine(self.params['W2'], self.params['b2'])
    
        self.lastLayer = SoftmaxWithLoss()

    def predict(self, x):
        """Inferenz durch neuronales Netzwerk
        
        Args:
            x (numpy.ndarray):Eingabe in das neuronale Netzwerk
        
        Returns:
            numpy.ndarray:Neuronale Netzwerkausgabe
        """
        #Schichten nach vorne ausbreiten
        for layer in self.layers.values():
            x = layer.forward(x)

        return x

    def loss(self, x, t):
        """Berechnung des Verlustfunktionswerts
        
        Args:
            x (numpy.ndarray):Eingabe in das neuronale Netzwerk
            t (numpy.ndarray):Richtiges Antwortetikett

        Returns:
            float:Wert der Verlustfunktion
        """
        #Inferenz
        y = self.predict(x)

        # Softmax-with-Berechnet durch Vorwärtsausbreitung der Verlustschicht
        loss = self.lastLayer.forward(y, t)

        return loss

    def accuracy(self, x, t):
        """Berechnung der Erkennungsgenauigkeit
        
        Args:
            x (numpy.ndarray):Eingabe in das neuronale Netzwerk
            t (numpy.ndarray):Richtiges Antwortetikett
        
        Returns:
            float:Erkennungsgenauigkeit
        """
        y = self.predict(x)
        y = np.argmax(y, axis=1)
        t = np.argmax(t, axis=1)
        
        accuracy = np.sum(y == t) / x.shape[0]
        return accuracy

    def numerical_gradient(self, x, t):
        """Berechnen Sie den Gradienten für den Gewichtsparameter durch numerische Differenzierung
        
        Args:
            x (numpy.ndarray):Eingabe in das neuronale Netzwerk
            t (numpy.ndarray):Richtiges Antwortetikett
        
        Returns:
            dictionary:Ein Wörterbuch, in dem Farbverläufe gespeichert werden
        """
        grads = {}
        grads['W1'] = \
            numerical_gradient(lambda: self.loss(x, t), self.params['W1'])
        grads['b1'] = \
            numerical_gradient(lambda: self.loss(x, t), self.params['b1'])
        grads['W2'] = \
            numerical_gradient(lambda: self.loss(x, t), self.params['W2'])
        grads['b2'] = \
            numerical_gradient(lambda: self.loss(x, t), self.params['b2'])

        return grads

    def gradient(self, x, t):
        """Berechnen Sie den Gradienten für den Gewichtungsparameter mit der Methode der Fehlerrückübertragung
        
         Args:
            x (numpy.ndarray):Eingabe in das neuronale Netzwerk
            t (numpy.ndarray):Richtiges Antwortetikett
        
        Returns:
            dictionary:Ein Wörterbuch, in dem Farbverläufe gespeichert werden
        """
        #Vorwärtsausbreitung
        self.loss(x, t)     #Weitergeben, um den Verlustwert zu berechnen

        #Backpropagation
        dout = self.lastLayer.backward()
        for layer in reversed(list(self.layers.values())):
            dout = layer.backward(dout)

        #Extrahieren Sie den Differenzwert jeder Schicht
        grads = {}
        grads['W1'] = self.layers['Affine1'].dW
        grads['b1'] = self.layers['Affine1'].db
        grads['W2'] = self.layers['Affine2'].dW
        grads['b2'] = self.layers['Affine2'].db

        return grads

Der Code im Buch verwendet "OrderedDict", aber hier verwenden wir das übliche "Dikt". Dies liegt daran, dass ab Python 3.7 die Einfügereihenfolge von "dict" -Objekten gespeichert wird [^ 1].

5.7.3 Gradientenbestätigung der Fehlerrückausbreitungsmethode

Dieser Code vergleicht den Gradienten, der durch das Fehlerrückausbreitungsverfahren erhalten wird, mit dem Gradienten, der durch numerische Differenzierung erhalten wird.

gradient_check.py


# coding: utf-8
import os
import sys
import numpy as np
from two_layer_net import TwoLayerNet
sys.path.append(os.pardir)  #Fügen Sie dem Pfad das übergeordnete Verzeichnis hinzu
from dataset.mnist import load_mnist


#Lesen Sie die MNIST-Trainingsdaten und Testdaten
(x_train, t_train), (x_test, t_test) = \
    load_mnist(normalize=True, one_hot_label=True)

#Zweischichtige Erzeugung neuronaler Arbeit
network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)

#Datenaufbereitung zur Überprüfung
x_batch = x_train[:3]
t_batch = t_train[:3]

#Gradientenberechnung durch numerische Differenzierung und Fehlerrückausbreitungsmethode
grad_numerical = network.numerical_gradient(x_batch, t_batch)
grad_backprop = network.gradient(x_batch, t_batch)

#Überprüfen Sie den Unterschied zwischen jedem Gewicht
for key in grad_numerical.keys():
    #Berechnung der absoluten Differenz
    diff = np.abs(grad_backprop[key] - grad_numerical[key])
    #Durchschnitt und Maximum anzeigen
    print(f"{key}: [Durchschnittlicher Unterschied]{np.average(diff):.10f} [Maximale Differenz]{np.max(diff):.10f}")

In dem Buch habe ich nur den Durchschnitt der Absolutwertdifferenzen überprüft, aber ich habe auch den Maximalwert der Absolutwertdifferenzen überprüft.

W1: [Durchschnittlicher Unterschied]0.0000000003 [Maximale Differenz]0.0000000080
b1: [Durchschnittlicher Unterschied]0.0000000021 [Maximale Differenz]0.0000000081
W2: [Durchschnittlicher Unterschied]0.0000000063 [Maximale Differenz]0.0000000836
b2: [Durchschnittlicher Unterschied]0.0000001394 [Maximale Differenz]0.0000002334

Da b2 ein Wert von ungefähr 7 Stellen nach dem Dezimalpunkt ist, scheint der Fehler etwas größer als das Buch zu sein. Möglicherweise liegt ein schlechter Punkt in der Implementierung vor. Wenn Sie Fragen haben, lassen Sie es mich bitte wissen: Schweiß:

5.7.4 Lernen mit der Fehlerrückverteilungsmethode

Unten ist der Lerncode.

mnist.py


# coding: utf-8
import os
import sys
import matplotlib.pylab as plt
import numpy as np
from two_layer_net import TwoLayerNet
sys.path.append(os.pardir)  #Fügen Sie dem Pfad das übergeordnete Verzeichnis hinzu
from dataset.mnist import load_mnist


#Lesen Sie die MNIST-Trainingsdaten und Testdaten
(x_train, t_train), (x_test, t_test) = \
    load_mnist(normalize=True, one_hot_label=True)

#Hyper-Parametereinstellungen
iters_num = 10000       #Anzahl der Updates
batch_size = 100        #Chargengröße
learning_rate = 0.1     #Lernrate

#Liste der Ergebnisse aufzeichnen
train_loss_list = []    #Wertänderungen der Verlustfunktion
train_acc_list = []     #Erkennungsgenauigkeit für Trainingsdaten
test_acc_list = []      #Erkennungsgenauigkeit für Testdaten

train_size = x_train.shape[0]  #Größe der Trainingsdaten
iter_per_epoch = max(int(train_size / batch_size), 1)    #Anzahl der Iterationen pro Epoche

#Zweischichtige Erzeugung neuronaler Arbeit
network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)

#Fang an zu lernen
for i in range(iters_num):

    #Mini-Batch-Generierung
    batch_mask = np.random.choice(train_size, batch_size, replace=False)
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]

    #Gradientenberechnung
    grad = network.gradient(x_batch, t_batch)

    #Aktualisierung der Gewichtsparameter
    for key in ('W1', 'b1', 'W2', 'b2'):
        network.params[key] -= learning_rate * grad[key]
    
    #Berechnung des Verlustfunktionswerts
    loss = network.loss(x_batch, t_batch)
    train_loss_list.append(loss)

    #Berechnung der Erkennungsgenauigkeit für jede Epoche
    if i % iter_per_epoch == 0:
        train_acc = network.accuracy(x_train, t_train)
        test_acc = network.accuracy(x_test, t_test)
        train_acc_list.append(train_acc)
        test_acc_list.append(test_acc)

        #Fortschrittsanzeige
        print(f'[Anzahl der Updates]{i:>4} [Wert der Verlustfunktion]{loss:.4f} '
              f'[Erkennungsgenauigkeit von Trainingsdaten]{train_acc:.4f} [Erkennungsgenauigkeit von Testdaten]{test_acc:.4f}')

#Zeichnen Sie den Übergang des Wertes der Verlustfunktion
x = np.arange(len(train_loss_list))
plt.plot(x, train_loss_list, label='loss')
plt.xlabel('iteration')
plt.ylabel('loss')
plt.xlim(left=0)
plt.ylim(bottom=0)
plt.show()

#Zeichnen Sie den Übergang der Erkennungsgenauigkeit von Trainingsdaten und Testdaten
x2 = np.arange(len(train_acc_list))
plt.plot(x2, train_acc_list, label='train acc')
plt.plot(x2, test_acc_list, label='test acc', linestyle='--')
plt.xlabel('epochs')
plt.ylabel('accuracy')
plt.xlim(left=0)
plt.ylim(0, 1.0)
plt.legend(loc='lower right')
plt.show()

Und es ist das Ausführungsergebnis derselben Form wie im vorherigen Kapitel.

[Anzahl der Updates]   0 [Wert der Verlustfunktion]2.3008 [Erkennungsgenauigkeit von Trainingsdaten]0.0926 [Erkennungsgenauigkeit von Testdaten]0.0822
[Anzahl der Updates] 600 [Wert der Verlustfunktion]0.2575 [Erkennungsgenauigkeit von Trainingsdaten]0.9011 [Erkennungsgenauigkeit von Testdaten]0.9068
[Anzahl der Updates]1200 [Wert der Verlustfunktion]0.2926 [Erkennungsgenauigkeit von Trainingsdaten]0.9219 [Erkennungsgenauigkeit von Testdaten]0.9242
[Anzahl der Updates]1800 [Wert der Verlustfunktion]0.2627 [Erkennungsgenauigkeit von Trainingsdaten]0.9324 [Erkennungsgenauigkeit von Testdaten]0.9341
[Anzahl der Updates]2400 [Wert der Verlustfunktion]0.0899 [Erkennungsgenauigkeit von Trainingsdaten]0.9393 [Erkennungsgenauigkeit von Testdaten]0.9402
[Anzahl der Updates]3000 [Wert der Verlustfunktion]0.1096 [Erkennungsgenauigkeit von Trainingsdaten]0.9500 [Erkennungsgenauigkeit von Testdaten]0.9483
[Anzahl der Updates]3600 [Wert der Verlustfunktion]0.1359 [Erkennungsgenauigkeit von Trainingsdaten]0.9559 [Erkennungsgenauigkeit von Testdaten]0.9552
[Anzahl der Updates]4200 [Wert der Verlustfunktion]0.1037 [Erkennungsgenauigkeit von Trainingsdaten]0.9592 [Erkennungsgenauigkeit von Testdaten]0.9579
[Anzahl der Updates]4800 [Wert der Verlustfunktion]0.1065 [Erkennungsgenauigkeit von Trainingsdaten]0.9639 [Erkennungsgenauigkeit von Testdaten]0.9600
[Anzahl der Updates]5400 [Wert der Verlustfunktion]0.0419 [Erkennungsgenauigkeit von Trainingsdaten]0.9665 [Erkennungsgenauigkeit von Testdaten]0.9633
[Anzahl der Updates]6000 [Wert der Verlustfunktion]0.0393 [Erkennungsgenauigkeit von Trainingsdaten]0.9698 [Erkennungsgenauigkeit von Testdaten]0.9649
[Anzahl der Updates]6600 [Wert der Verlustfunktion]0.0575 [Erkennungsgenauigkeit von Trainingsdaten]0.9718 [Erkennungsgenauigkeit von Testdaten]0.9663
[Anzahl der Updates]7200 [Wert der Verlustfunktion]0.0850 [Erkennungsgenauigkeit von Trainingsdaten]0.9728 [Erkennungsgenauigkeit von Testdaten]0.9677
[Anzahl der Updates]7800 [Wert der Verlustfunktion]0.0403 [Erkennungsgenauigkeit von Trainingsdaten]0.9749 [Erkennungsgenauigkeit von Testdaten]0.9686
[Anzahl der Updates]8400 [Wert der Verlustfunktion]0.0430 [Erkennungsgenauigkeit von Trainingsdaten]0.9761 [Erkennungsgenauigkeit von Testdaten]0.9685
[Anzahl der Updates]9000 [Wert der Verlustfunktion]0.0513 [Erkennungsgenauigkeit von Trainingsdaten]0.9782 [Erkennungsgenauigkeit von Testdaten]0.9715
[Anzahl der Updates]9600 [Wert der Verlustfunktion]0.0584 [Erkennungsgenauigkeit von Trainingsdaten]0.9777 [Erkennungsgenauigkeit von Testdaten]0.9707

スクリーンショット 2020-01-19 1.20.06.png スクリーンショット 2020-01-19 1.20.59.png

Im Vergleich zu den Ergebnissen im vorherigen Kapitel steigt die Erkennungsgenauigkeit schneller an. Am Ende waren es ungefähr 97%. Der einzige Unterschied zwischen der numerischen Differenzierung und der Fehlerrückausbreitungsmethode sollte die Gradientenberechnungsmethode sein, daher scheint der Wechsel von der Sigmoidfunktion zur ReLU-Funktion zu einer Verbesserung geführt zu haben.

5.8 Zusammenfassung

Das Berechnungsdiagramm sollte leicht verständlich sein. Es wurde auch gut verstanden, dass die Ausgangsschicht und die Verlustfunktion so ausgelegt waren, dass der Differenzwert leicht erhalten werden konnte.

Das ist alles für dieses Kapitel. Wenn Sie Fehler haben, wäre ich Ihnen dankbar, wenn Sie darauf hinweisen könnten. (Zu anderen Kapiteln dieses Memos: Kapitel 1 / Kapitel 2 / Kapitel 3 / Kapitel 4 / Kapitel 5 / [Kapitel 6](https: / /qiita.com/segavvy/items/ca4ac4c9ee1a126bff41) / Kapitel 7 / Kapitel 8 / Zusammenfassung)

[^ 1]: Siehe "Verbesserung des Python-Datenmodells" in Was ist neu in Python 3.7.

Recommended Posts

Ein Amateur stolperte in Deep Learning von Grund auf neu Hinweis: Kapitel 1
Ein Amateur stolperte in Deep Learning von Grund auf neu Hinweis: Kapitel 3
Ein Amateur stolperte in Deep Learning von Grund auf neu. Hinweis: Kapitel 7
Ein Amateur stolperte in Deep Learning von Grund auf neu Hinweis: Kapitel 5
Ein Amateur stolperte in Deep Learning von Grund auf neu Hinweis: Kapitel 4
Ein Amateur stolperte in Deep Learning von Grund auf neu Hinweis: Kapitel 2
Ein Amateur stolperte über Deep Learning ❷ von Grund auf neu Hinweis: Kapitel 5
Ein Amateur stolperte über Deep Learning ❷ von Grund auf neu Hinweis: Kapitel 2
Ein Amateur stolperte über Deep Learning ❷ von Grund auf neu Hinweis: Kapitel 1
Ein Amateur stolperte über Deep Learning ❷ von Grund auf neu Hinweis: Kapitel 4
Deep Learning / Deep Learning von Grund auf neu Kapitel 6 Memo
[Lernnotiz] Deep Learning von Grund auf neu gemacht [Kapitel 5]
[Lernnotiz] Deep Learning von Grund auf neu gemacht [Kapitel 6]
"Deep Learning von Grund auf neu" mit Haskell (unvollendet)
Deep Learning / Deep Learning von Grund auf neu Kapitel 7 Memo
[Lernnotiz] Deep Learning von Grund auf neu gemacht [~ Kapitel 4]
Deep Learning von Grund auf neu ① Kapitel 6 "Lerntechniken"
Deep Learning von Grund auf neu Kapitel 2 Perceptron (Memo lesen)
Deep Learning von Grund auf 1-3 Kapitel
Deep Learning / Deep Learning von Grund auf neu 2 Kapitel 4 Memo
Deep Learning / Deep Learning von Grund auf neu Kapitel 3 Memo
Deep Learning / Deep Learning von Null 2 Kapitel 5 Memo
Erstellen Sie mit Docker eine Umgebung für "Deep Learning von Grund auf neu"
Tiefes Lernen von Grund auf neu (Kostenberechnung)
Deep Learning / Deep Learning von Null 2 Kapitel 7 Memo
Deep Learning / Deep Learning von Null 2 Kapitel 8 Memo
Deep Learning / Deep Learning von Grund auf neu Kapitel 5 Memo
Deep Learning / Deep Learning von Grund auf neu Kapitel 4 Memo
Deep Learning / Deep Learning von Grund auf neu 2 Kapitel 3 Memo
Deep Learning Memo von Grund auf neu gemacht
Deep Learning / Deep Learning von Null 2 Kapitel 6 Memo
[Deep Learning von Grund auf neu] Ich habe versucht, die Gradientenbestätigung auf leicht verständliche Weise zu erklären.
"Deep Learning from Grund" Memo zum Selbststudium (Nr. 14) Führen Sie das Programm in Kapitel 4 in Google Colaboratory aus
"Deep Learning from Grund" Memo zum Selbststudium (Teil 8) Ich habe die Grafik in Kapitel 6 mit matplotlib gezeichnet
Warum ModuleNotFoundError: In "Deep Learning from Grund" wird kein Modul mit dem Namen "didaset.mnist" angezeigt.
Schreiben Sie Ihre Eindrücke von der Deep Learning 3 Framework Edition, die von Grund auf neu erstellt wurde
Tiefes Lernen von Grund auf neu (Vorwärtsausbreitung)
Tiefes Lernen / Tiefes Lernen von Grund auf 2-Versuchen Sie, GRU zu bewegen
[Windows 10] Aufbau einer "Deep Learning from Scratch" -Umgebung
Lernbericht über das Lesen von "Deep Learning von Grund auf neu"
[Deep Learning von Grund auf neu] Über die Optimierung von Hyperparametern
"Deep Learning from Grund" Memo zum Selbststudium (Teil 12) Deep Learning
Python vs Ruby "Deep Learning von Grund auf neu" Kapitel 2 Logikschaltung von Perceptron
Python vs Ruby "Deep Learning von Grund auf neu" Kapitel 4 Implementierung der Verlustfunktion
Selbststudien-Memo "Deep Learning from Grund" (unlesbares Glossar)
"Deep Learning from Grund" Memo zum Selbststudium (Nr. 9) MultiLayerNet-Klasse
Ein Amateur versuchte Deep Learning mit Caffe (Einführung)
GitHub des guten Buches "Deep Learning von Grund auf neu"
Ein Amateur versuchte Deep Learning mit Caffe (Übung)
[Lernnotiz] Deep Learning von Grund auf ~ Implementierung von Dropout ~
Ein Amateur hat Deep Learning mit Caffe ausprobiert (Übersicht)
Python vs Ruby "Deep Learning von Grund auf neu" Zusammenfassung
"Deep Learning from Grund" Memo zum Selbststudium (10) MultiLayerNet-Klasse
"Deep Learning from Grund" Memo zum Selbststudium (Nr. 11) CNN
Python vs Ruby "Deep Learning von Grund auf neu" Kapitel 3 Implementierung eines dreischichtigen neuronalen Netzwerks
[Python] [Verarbeitung natürlicher Sprache] Ich habe Deep Learning ausprobiert (auf Japanisch von Grund auf neu erstellt)
Deep Learning von Grund auf neu Die Theorie und Implementierung des mit Python erlernten Deep Learning Kapitel 3
Lua-Version Deep Learning von Grund auf neu Teil 5.5 [Bereitstellung von pkl-Dateien in Lua Torch]
[Für Anfänger] Was ist in Deep Learning von Grund auf neu geschrieben?