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

Einführung

Plötzlich begann ich in Kapitel 3 von "Deep Learning von Grund auf - Theorie und Implementierung von Deep Learning, das mit Python gelernt wurde" zu studieren. Es ist ein Memo der Reise.

Die Ausführungsumgebung ist macOS Mojave + Anaconda 2019.10. Weitere Informationen finden Sie in Kapitel 1 dieses Memos.

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

Kapitel 3 Neuronales Netz

In diesem Kapitel wird beschrieben, wie das neuronale Netzwerk funktioniert.

3.1 Vom Perzeptron zum neuronalen Netz

Es erklärt den Unterschied beim Zählen von Schichten und den Unterschied zwischen Perceptron und dem neuronalen Netzwerk. Es ist etwas unpraktisch, dass verschiedene Personen unterschiedliche Schichten zählen.

3.2 Aktivierungsfunktion

Dies ist eine Einführung in die Arten von Aktivierungsfunktionen. Ich habe versucht, die drei Arten von Funktionen grafisch darzustellen, die angezeigt werden.

# coding: utf-8
import numpy as np
import matplotlib.pylab as plt


def step_function(x):
    """Schrittfunktion, die 1 zurückgibt, wenn die Eingabe 0 überschreitet
    
    Args:
        x (numpy.ndarray):Eingang
    
    Returns:
        numpy.ndarray:Ausgabe
    """
    return np.array(x > 0, dtype=np.int)


def sigmoid(x):
    """Sigmaid-Funktion
    
    Args:
        x (numpy.ndarray):Eingang
    
    Returns:
        numpy.ndarray:Ausgabe
    """
    return 1 / (1 + np.exp(-x))


def relu(x):
    """ReLU-Funktion
    
    Args:
        x (numpy.ndarray)):Eingang
    
    Returns:
        numpy.ndarray:Ausgabe
    """
    return np.maximum(0, x)


#Berechnung
x = np.arange(-5.0, 5.0, 0.01)  #Schritt ist klein, damit die Schrittfunktion nicht diagonal aussieht
y_step = step_function(x)
y_sigmoid = sigmoid(x)
y_relu = relu(x)

#Diagrammzeichnung
plt.plot(x, y_step, label="step")
plt.plot(x, y_sigmoid, linestyle="--", label="sigmoid")
plt.plot(x, y_relu, linestyle=":", label="ReLU")
plt.ylim(-0.1, 5.1)
plt.legend()
plt.show()

スクリーンショット 2019-11-23 22.37.42.png Das einzige, was ich nicht verstanden habe, war, dass die Aktivierungsfunktion keine lineare Funktion sein sollte. Ich habe aus der Erklärung des Buches verstanden, dass wenn es nur ein Neuron in jeder Schicht gibt, es in einer Schicht ausgedrückt werden kann, selbst wenn es mehrschichtig ist. Aber selbst wenn es in jeder Schicht mehrere Neuronen gibt, kann es in einer Schicht ausgedrückt werden? Ich konnte es hier nicht gut verstehen.

3.3 Berechnung eines mehrdimensionalen Arrays

Die Erklärung besteht darin, die Berechnung mehrdimensionaler Arrays durch die Berechnung von Matrizen zu ersetzen, um die Effizienz zu verbessern. Ich habe den Ersatz durch Matrixberechnung studiert, als ich vor ungefähr 3 Jahren den Online-Kurs für maschinelles Lernen [^ 1] belegte und ihn in den folgenden 100 Klopfen der Sprachverarbeitung [^ 2] verwendete, also werde ich ihn überprüfen. Ich tat.

3.4 Implementierung eines 3-Schicht-Neuronalen Netzwerks

Implementieren Sie ein dreischichtiges neuronales Netzwerk mithilfe der Matrixberechnung im vorherigen Abschnitt. Es gab keine Funktion zum Lernen, also gab es nichts, worüber man stolpern konnte.

3.5 Design der Ausgabeschicht

Erläuterung der Softmax-Funktion. ~~ Auch hier gab es keinen besonderen Stolperstein. ~~ Ich wollte nicht stolpern, aber ich habe einen Fehler bemerkt. Wenn Sie keine Stapelverarbeitung durchführen, gibt es kein Problem, wie im Buch implementiert, aber Sie müssen es ändern, wenn Sie "3.6.3 Stapelverarbeitung" implementieren.

Unten finden Sie den Softmax-Code, der die Stapelverarbeitung unterstützt.

python


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.
    if x.ndim == 2:

        #Für jedes Bild (Achse=1) Berechnen Sie den Maximalwert und formen Sie ihn neu, damit er gesendet werden kann
        c = np.max(x, axis=1).reshape(x.shape[0], 1)

        #Berechnen Sie das Molekül, während Sie den Maximalwert als Überlauf-Gegenmaßnahme abziehen
        exp_a = np.exp(x - c)

        #Der Nenner gilt auch für jedes Bild (Achse)=Umformen, so dass es zu 1) summiert und gesendet werden kann
        sum_exp_a = np.sum(exp_a, axis=1).reshape(x.shape[0], 1)
        
        #Berechnet für jedes Bild
        y = exp_a / sum_exp_a

    else:

        #Wenn es sich nicht um eine Stapelverarbeitung handelt, implementieren Sie sie gemäß dem Buch
        c = np.max(x)
        exp_a = np.exp(x - c)  #Überlaufmaßnahmen
        sum_exp_a = np.sum(exp_a)
        y = exp_a / sum_exp_a

    return y

Darüber hinaus im GitHub-Repository https://github.com/oreilly-japan/deep-learning-from-scratch dieses Buches An einer Quelle wurde es für den Rundfunk transponiert. Vielleicht ist es ein Geschwindigkeitsvorteil, aber auf den ersten Blick wusste ich nicht, was ich tat, also habe ich Code ausprobiert, der "Umformung" verwendet.

3.6 Handschriftliche Nummernerkennung

Es implementiert tatsächlich den Inferenzprozess des neuronalen Netzwerks unter Verwendung der trainierten Parameter. Ich benötige ein "sample_weight.pkl", in dem die gelernten Parameter gespeichert sind, daher das GitHub-Repository dieses Buches [https://github.com/oreilly-japan/deep-learning-from-scratch](https: // github). Lassen Sie uns die Dateien im Ordner ch3 von com / oreilly-japan / deep-learning-from-Grund) in das aktuelle Verzeichnis bringen.

Als ich mit der Implementierung gemäß dem Buch fortfuhr, stieß ich auf eine Überlaufwarnung.

/Users/segavvy/Documents/deep-learning-from-scratch/ch03/3.6_mnist.py:19: RuntimeWarning: overflow encountered in exp
  return 1 / (1 + np.exp(-x))

Lesen Sie hierzu die Erläuterung zu Maschinelles Lernen mit Python treffen >> Logistische Regression >> Sigmoid-Funktion und legen Sie den Wert von x fest. Ich habe versucht, das Problem zu beheben, damit es nicht überläuft.

Bei der Berechnung der endgültigen Erkennungsgenauigkeit wird im Buch "Genauigkeit_cnt" in "Float" typkonvertiert. In Python3 gibt die Division zwischen Ganzzahlen jedoch einen Gleitkomma zurück, sodass diese Konvertierung unnötig erscheint.

Während ich es implementierte, fragte ich mich, welche Art von Bild ich nicht gut ableiten konnte, also versuchte ich es anzuzeigen.

Unten ist der Code, den ich geschrieben habe.

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


def sigmoid(x):
    """Sigmaid-Funktion
Da es bei der Implementierung des Buches überläuft, wird es unter Bezugnahme auf die folgende Site korrigiert.
    http://www.kamishima.net/mlmpyja/lr/sigmoid.html

    Args:
        x (numpy.ndarray):Eingang
    
    Returns:
        numpy.ndarray:Ausgabe
    """
    #Korrigieren Sie x in einem Bereich, der nicht überläuft
    sigmoid_range = 34.538776394910684
    x2 = np.maximum(np.minimum(x, sigmoid_range), -sigmoid_range)

    #Sigmaid-Funktion
    return 1 / (1 + np.exp(-x2))


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.
    if x.ndim == 2:

        #Für jedes Bild (Achse=1) Berechnen Sie den Maximalwert und formen Sie ihn neu, damit er gesendet werden kann
        c = np.max(x, axis=1).reshape(x.shape[0], 1)

        #Berechnen Sie das Molekül, während Sie den Maximalwert als Überlauf-Gegenmaßnahme abziehen
        exp_a = np.exp(x - c)

        #Der Nenner gilt auch für jedes Bild (Achse)=Umformen, so dass es zu 1) summiert und gesendet werden kann
        sum_exp_a = np.sum(exp_a, axis=1).reshape(x.shape[0], 1)
        
        #Berechnet für jedes Bild
        y = exp_a / sum_exp_a

    else:

        #Wenn es sich nicht um eine Stapelverarbeitung handelt, implementieren Sie sie gemäß dem Buch
        c = np.max(x)
        exp_a = np.exp(x - c)  #Überlaufmaßnahmen
        sum_exp_a = np.sum(exp_a)
        y = exp_a / sum_exp_a

    return y


def load_test_data():
    """MNIST-Testbild- und Testetikettenerfassung
Der Bildwert ist 0.0〜1.Normalisiert auf 0.

    Returns:
        numpy.ndarray, numpy.ndarray:Testbild,Testetikett
    """
    (x_train, t_train), (x_test, t_test) \
        = load_mnist(flatten=True, normalize=True)
    return x_test, t_test


def load_sapmle_network():
    """Holen Sie sich Probe trainierte Gewichtsparameter
    
    Returns:
        dict:Gewichts- und Bias-Parameter
    """
    with open("sample_weight.pkl", "rb") as f:
        network = pickle.load(f)
    return network


def predict(network, x):
    """Inferenz durch neuronales Netzwerk
    
    Args:
        network (dict):Gewichts- und Bias-Parameter
        x (numpy.ndarray):Eingabe in das neuronale Netzwerk
    
    Returns:
        numpy.ndarray:Neuronale Netzwerkausgabe
    """
    #Parameterabruf
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']

    #Berechnung des neuronalen Netzes (vorwärts)
    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)

    a3 = np.dot(z2, W3) + b3
    y = softmax(a3)

    return y


def show_image(img):
    """Bildschirm
    
    Args:
        image (numpy.ndarray):Bild-Bitmap
    """
    pil_img = Image.fromarray(np.uint8(img))
    pil_img.show()


#MNIST-Testdaten lesen
x, t = load_test_data()

#Laden Sie die Parameter für das Probengewicht
network = load_sapmle_network()

#Inferenz, Berechnung der Erkennungsgenauigkeit
batch_size = 100  #Stapelverarbeitungseinheit
accuracy_cnt = 0  #Die Anzahl der richtigen Antworten
error_image = None  #Nicht erkanntes Bild
for i in range(0, len(x), batch_size):

    #Chargendatenaufbereitung
    x_batch = x[i:i + batch_size]

    #Inferenz
    y_batch = predict(network, x_batch)
    p = np.argmax(y_batch, axis=1)

    #Richtige Antwortanzahl
    accuracy_cnt += np.sum(p == t[i:i + batch_size])

    #Fehler beim nicht erkannten Bild_Mit Bild verbinden
    for j in range(0, batch_size):
        if p[j] != t[i + j]:
            if error_image is None:
                error_image = x_batch[j]
            else:
                error_image = np.concatenate((error_image, x_batch[j]), axis=0)

print("Erkennungsgenauigkeit:" + str(accuracy_cnt / len(x)))

#Nicht erkannte Bilder anzeigen
error_image *= 255  #Der Bildwert ist 0.0〜1.Da es auf 0 normalisiert ist, setzen Sie es auf 0 bis 255 zurück, damit es angezeigt werden kann.
show_image(error_image.reshape(28 * (len(x) - accuracy_cnt), 28))

Und das Ausführungsergebnis.

Erkennungsgenauigkeit:0.9352

スクリーンショット 2019-12-27 21.07.37.png

Da die fehlgeschlagenen ~~ 793 ~~ 648 Bilder einfach vertikal verbunden sind, wird ein lächerlich langes Bild angezeigt, aber es gibt sicherlich viele Zeichen, die schwer zu verstehen sind. Es gibt jedoch einige Zeichen, die erkannt werden können.

~~ Das Buch sagt auch, dass die Erkennungsgenauigkeit "0,9352" sein wird, aber aus irgendeinem Grund ist sie "0,9207" geworden. Selbst wenn ich die Sigmoid-Funktion in den Zustand zurückversetzt habe, in dem die Warnung ausgegeben wurde, hat sie sich nicht geändert, sodass möglicherweise ein anderer Fehler vorliegt ... ~~

3.7 Zusammenfassung

~~ Kapitel 3 hatte auch viel Kritik für mich, so dass ich keinen großen Stolperstein gemacht habe, aber ich mache mir Sorgen über den Unterschied in der Erkennungsgenauigkeit am Ende. ~~ Ich hatte nicht vor, über Kapitel 3 zu stolpern, aber ich bemerkte die folgenden zwei Punkte später.

Problem 1, das mir später aufgefallen ist

Wie @tunnel betonte, fand ich heraus, warum sich die Erkennungsgenauigkeit vom Buch unterschied! Ursprünglich war es notwendig, die auf 0,0 bis 1,0 normierten Bilddatenwerte zu verwenden, aber diejenigen, die 0 bis 255 blieben, wurden verwendet. Danke @tunnel! Auch wenn die Werte bisher unterschiedlich sind, ist die Erkennungsgenauigkeit wahrscheinlich beeinträchtigt, aber es ist interessant, dass sie nicht so schlecht geworden ist.

Problem 2, das mir später aufgefallen ist

Selbst wenn ich aus irgendeinem Grund in Kapitel 4 erfahren habe, wurde die Verlustfunktion nicht klein, und als ich die Ursache untersuchte, bemerkte ich, dass die Softmax-Funktion die Stapelverarbeitung nicht unterstützen konnte. Der obige Code wurde behoben. (Ich war froh, wenn dies in Kapitel 3 etwas näher erläutert wurde ...)

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

[^ 1]: Dies ist eine Vorlesung Maschinelles Lernen, die von der Stanford University im Online-Kursdienst Coursera angeboten wird. Freiwillige fügten japanische Untertitel hinzu, und selbst wenn ich nicht gut Englisch konnte, war es ziemlich gut. Die Technik, Array-Berechnungen durch Matrixberechnungen zu ersetzen, wird unter dem Namen Vectorization beschrieben. [^ 2]: Ich habe es verwendet, als ich Problem 73 von Kapitel 8 von 100 Language Processing Knock 2015 gelöst habe. Lernen Sie zu diesem Zeitpunkt Notizen [100 Amateur-Sprachverarbeitungsklopfen: 73](https://qiita.com/segavvy/items/5ad0d5742a674bdf56cc#%E3%83%99%E3%82%AF%E3%83%88% Gepostet als E3% 83% AB% E5% 8C% 96).

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
[Lernnotiz] Deep Learning von Grund auf neu gemacht [Kapitel 7]
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
Deep Learning von Grund auf neu ① Kapitel 6 "Lerntechniken"
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 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)
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?
[Deep Learning von Grund auf neu] Ich habe die Affine-Ebene implementiert