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)
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.
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.
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.
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.
Dies ist die Implementierung der Additionsschicht und der Multiplikationsschicht im vorherigen Abschnitt. Da die Unterscheidung einfach ist, ist sie leicht zu implementieren.
Eine Implementierung der Aktivierungsfunktionsschicht.
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
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.
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.
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
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.
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.
Dies ist eine Überprüfung des Implementierungsablaufs. Es gibt keinen besonderen Stolperstein.
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].
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ß:
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
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.
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