Dies ist ein Einführungsartikel über Deep Learning, der heutzutage sehr beliebt ist. Deep Learning verfügt bereits über zahlreiche Open-Source-Bibliotheken, und dieses Mal werden wir Chainer verwenden, das für seine inländische Produktion bekannt ist. In einem Artikel wurde festgestellt, dass die GPU-Berechnung derzeit relativ schnell ist.
Es gibt jedoch viele einführende Artikel zu Chainer, aber die meisten wurden durch Ausführen eines Beispiels von mnist vervollständigt, das handgeschriebene Zeichen erkennt. Wenn Sie sich das Mnist-Beispiel ansehen, können Sie sicher verstehen, wie Chainer verwendet wird, aber irgendwie unterscheidet es sich von der Möglichkeit, es selbst zu erstellen. Diesmal ist es also so weit, dass Sie Deep Learning mithilfe von Chainer selbst erstellen können. Ich werde es mit dem Ziel tun.
・ Betriebssystem: Mac OS X EL Capitan (10.11.5) · Python 2.7.12: Anaconda 4.1.1 (x86_64) ・ Chainer 1.12.0
Wenn Sie die Chainer-Umgebung nicht vorbereitet haben,
$ pip install chainer
Sie können es einfach unter installieren.
Hier werden wir die Vorwärts- und Rückwärtsberechnungen unter Verwendung von Variablen diskutieren. Dies ist die Phase vor dem Eintritt in das Neuronale Netz.
Laden Sie zuerst den Chainer und deklarieren Sie die Variablen.
>>> import chainer
>>> x_data = np.array([5], dtype=np.float32)
>>> x_data
array([ 5.], dtype=float32)
Grundsätzlich scheint es als Float-Typ eines Numpy-Arrays zu deklarieren.
Verwenden Sie `` `chainer.Variable``` als Variable zur Verwendung innerhalb des Chainers.
>>> x = chainer.Variable(x_data)
>>> x
<variable at 0x10b796fd0>
Sie können den Wert von x in `` `.data``` überprüfen.
>>> x.data
array([ 5.], dtype=float32)
Als nächstes deklarieren Sie die Funktion y von x.
Dieses Mal werden wir die folgende Funktion verwenden.
>>> y = x ** 2 - 2 * x + 1
>>> y
<variable at 0x10b693dd0>
Sie können den Wert von y auf die gleiche Weise überprüfen.
>>> y.data
array([ 16.], dtype=float32)
Durch Aufrufen der folgenden Methode kann die Differenzierung berechnet werden.
>>> y.backward()
Der Gradient für die Rückausbreitung ist "grad".
>>> x.grad
array([ 8.], dtype=float32)
Es ist ein wenig schwierig zu verstehen, für welchen Gradienten es ist, aber der Wert des Gradienten, wenn y durch x differenziert wird.
y'(x) = 2x - 2\\
\rightarrow \ y'(5) = 8
Der Wert `8``` von`
`x.grad``` wird abgeleitet von.
Wenn in Chainers offizielle Referenz x ein mehrdimensionales Array ist, initialisieren Sie "y.grad" Danach heißt es, `` `x.grad``` zu berechnen. Wenn Sie es nicht initialisieren, wird es dem Array hinzugefügt, in dem der Gradientenwert gespeichert ist. Denken Sie also daran, dass Sie "vor der Gradientenberechnung initialisieren".
>>> x = chainer.Variable(np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32))
>>> y = x**2 - 2*x + 1
>>> y.grad = np.ones((2, 3), dtype=np.float32)
>>> y.backward()
>>> x.grad
array([[ 0., 2., 4.],
[ 6., 8., 10.]], dtype=float32)
Geben Sie bei der Konfiguration des neuronalen Netzwerks explizit an, welche Art von Strukturmodell konfiguriert werden soll (insbesondere wie viele Knoten und wie viele Schichten). Die Entscheidung für dieses Modell hängt immer noch von Erfahrung und Intuition ab. Das neuronale Netzwerk, einschließlich Deep Learning, passt die internen Hyperparameter automatisch an, das erste Modell muss jedoch im Voraus festgelegt werden. Es ist ein wenig abseits des Themas, aber selbst in der Bayes'schen Statistik ist die Monte-Carlo-Markov-Kette (MCMC) so konzipiert, dass die posteriore Verteilung auf der Grundlage des Bayes'schen Theorems gut geschätzt werden kann, aber selbst in diesem Fall muss die vorherige Verteilung willkürlich bestimmt werden. .. Unabhängig davon, ob es sich um ein neuronales Netzwerk oder eine Bayes'sche Statistik handelt, hoffe ich, dass ein Vorhersagemodell erstellt werden kann, das universell auf jedes Problem reagiert, wenn eine epochale Methode zur Lösung dieses Bereichs vorgeschlagen wird.
Kommen wir zurück zur Geschichte, aber hier machen wir es möglich, den Chainer in abgekürzter Form im Python-Code aufzurufen.
>>> import chainer.links as L
Wie jeder weiß, der sich mit Neuronalen Netzen befasst, gibt es zwischen diesen Knoten einen Parameter namens Gewicht. Versuchen wir zunächst das einfachste lineare Verbindungsmuster.
>>> f = L.Linear(3, 2)
>>> f
<chainer.links.connection.linear.Linear object at 0x10b7b4290>
Dies zeigt eine Struktur mit 3 Eingabeebenen und 2 Ausgabeebenen.
linear
Um den Teil von kurz zu erklären, bedeutet dies, dass die Knoten durch die zuvor erwähnte lineare Verbindung verbunden sind, so dass dies durch den folgenden relationalen Ausdruck ausgedrückt wird.
f(x) = Wx + b\\
f \in \mathcal{R}^{2 \times 1},
x \in \mathcal{R}^{3 \times 1},\\
W \in \mathcal{R}^{2 \times 3}, b \in \mathcal{R}^{2 \times 1}
Daher hat das oben deklarierte `f```, obwohl nicht explizit deklariert, die Parameter`
W und den Gewichtsvektor `` `b
. Ich bin.
>>> f.W.data
array([[-0.02878495, 0.75096768, -0.10530342],
[-0.26099312, 0.44820449, -0.06585278]], dtype=float32)
>>> f.b.data
array([ 0., 0.], dtype=float32)
Wenn Sie es implementieren, ohne die internen Spezifikationen hier zu kennen, ist es unverständlich. Übrigens, obwohl ich mich nicht daran erinnere, die Gewichtsmatrix "W" initialisiert zu haben, hat sie einen zufälligen Wert, wenn das Linearglied aufgrund der Spezifikationen des Ketteners deklariert wird. Es scheint, dass es ist, weil es erschüttert ist.
Wie Sie in der offiziellen Chainer-Dokumentation sehen können, ist dies daher das am häufigsten verwendete Format.
>>> f = L.Linear(3, 2)
>>> x = chainer.Variable(np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32))
>>> y = f(x)
>>> y.data
array([[ 1.15724015, 0.43785751],
[ 3.0078783 , 0.80193317]], dtype=float32)
Sie können sehen, dass x, das ein dreidimensionaler Vektor war, durch lineare Kopplung in zweidimensionales y umgewandelt wird. Zu diesem Zeitpunkt wird der Anfangswert intern automatisch der Gewichtsmatrix W zugewiesen, sodass diese Berechnung fehlerfrei durchgeführt werden kann.
Zur Bestätigung, als ich den Gewichtswert betrachtete, wurde der Anfangswert sicher zugewiesen.
>>> f.W.data
array([[-0.02878495, 0.75096768, -0.10530342],
[-0.26099312, 0.44820449, -0.06585278]], dtype=float32)
>>> f.b.data
array([ 0., 0.], dtype=float32)
Als nächstes berechnen wir den Gradienten, der im vorherigen Kapitel gelernt wurde. In der offiziellen Chainer-Dokumentation wird viel Wert darauf gelegt, aber der Wert jedes Gradienten steigt mit jeder Berechnung an. Daher müssen Sie den Gradientenwert normalerweise mit der folgenden Methode auf 0 initialisieren, bevor Sie den Wert jedes Gradienten berechnen.
>>> f.zerograds()
Stellen Sie sicher, dass die Steigungswerte korrekt initialisiert sind.
>>> f.W.grad
array([[ 0., 0., 0.],
[ 0., 0., 0.]], dtype=float32)
>>> f.b.grad
array([ 0., 0.], dtype=float32)
Berechnen wir nun den Wert für jeden Gradienten.
>>> y.grad = np.ones((2, 2), dtype=np.float32)
>>> y.backward()
>>> f.W.grad
array([[ 5., 7., 9.],
[ 5., 7., 9.]], dtype=float32)
>>> f.b.grad
array([ 2., 2.], dtype=float32)
Sie können es richtig berechnen.
Wir werden das im vorherigen Kapitel explizit definierte Modell in mehreren Ebenen erweitern.
>>> l1 = L.Linear(4, 3)
>>> l2 = L.Linear(3, 2)
Lassen Sie uns vorerst das Gewicht jedes Modells überprüfen.
>>> l1.W.data
array([[-0.2187428 , 0.51174778, 0.30037731, -1.08665013],
[ 0.65367842, 0.23128517, 0.25591806, -1.0708735 ],
[-0.85425782, 0.25255874, 0.23436508, 0.3276397 ]], dtype=float32)
>>> l1.b.data
array([ 0., 0., 0.], dtype=float32)
>>> l2.W.data
array([[-0.18273738, -0.64931035, -0.20702939],
[ 0.26091203, 0.88469893, -0.76247424]], dtype=float32)
>>> l2.b.data
array([ 0., 0.], dtype=float32)
Die Struktur jedes Modells ist oben definiert. Als nächstes werden wir die Gesamtstruktur klären, beispielsweise wie die Modelle, die diese Strukturen definieren, miteinander verbunden sind.
>>> x = chainer.Variable(np.array([[1, 2, 3, 4], [5, 6, 7, 8]], dtype=np.float32))
>>> x.data
array([[ 1., 2., 3., 4.],
[ 5., 6., 7., 8.]], dtype=float32)
>>> h = l1(x)
>>> y = l2(h)
>>> y.data
array([[ 1.69596863, -4.08097076],
[ 1.90756595, -4.22696018]], dtype=float32)
Um sie wiederverwendbar zu machen, wird in der offiziellen Dokumentation empfohlen, Klassen wie folgt zu erstellen:
MyChain.py
# -*- coding: utf-8 -*-
from chainer import Chain
import chainer.links as L
class MyChain(Chain):
def __init__(self):
super(MyChain, self).__init__(
l1 = L.Linear(4, 3),
l2 = L.Linear(3, 2) )
def __call__(self, x):
h = self.l1(x)
return self.l2(h)
Als nächstes werden wir die Gewichte des neuronalen Netzwerkmodells optimieren. Es gibt verschiedene Methoden zur Optimierung dieses Gewichts, aber ehrlich gesagt scheint es kein klares Kriterium zu geben, für das man es verwenden kann. Daher verwenden wir hier die SGD-Methode (Stocastic Gradient Descent). Machen. Der Leistungsunterschied in Abhängigkeit von der Optimierungsmethode wird in Welche Optimierungsmethode zeigt die beste Leistung zum Lernen von CNN erläutert. Ich habe es erhalten.
>>> model = MyChain()
>>> optimizer = optimizers.SGD() #Geben Sie die Optimierungsmethode als SGD an
>>> optimizer.setup(model)
>>> optimizer
<chainer.optimizers.sgd.SGD object at 0x10b7b40d0>
Zu diesem Zeitpunkt können Sie die Parameterinformationen des Modells an `optimizer.setup (model)`
übergeben.
In der offiziellen Dokumentation gibt es zwei Möglichkeiten zur Optimierung. Bei der ersten Methode wird der Gradientenwert manuell berechnet, und die manuelle Berechnung des Gradienten ist ziemlich schwierig. Verwenden Sie daher eine andere Methode, z. B. die automatische Berechnung des Gradienten, außer in besonderen Fällen. Wenn Sie möchten, dass es automatisch berechnet wird, müssen Sie im Voraus eine Verlustfunktion definieren.
Details werden das nächste Mal in "Einführung in Deep Learning (2) - Versuchen wir nichtlineare Regression mit Chainer-" vorgestellt, aber jeder wird die Verlustfunktion einführen. Definieren Wenn es sich um reelle Zahlen handelt, kann dies als ein Problem definiert werden, das die Summe der beiden Normen der Methode der kleinsten Quadrate minimiert, und es scheint, dass es häufig als ein Problem definiert wird, das die Kreuzentropie minimiert. Für die Verlustfunktion werden verschiedene Typen in Hinweise zur Backpropagation-Methode erläutert.
Verlustfunktion
def forward(x, y, model):
loss = ... #Definieren Sie Ihre eigene Verlustfunktion
return loss
Dieses Mal wird angenommen, dass die Funktion "Vorwärts", die die Verlustfunktion berechnet, die Argumente "x", "y" und "Modell" verwendet. Wenn Sie eine solche Verlustfunktion definieren, werden die Parameter wie folgt optimiert.
optimizer.update(forward, x, y, model)
Wir warten darauf, dass Sie uns folgen! Qiita: Karat Yoshizaki twitter:@carat_yoshizaki Hatena-Blog: Carat COO-Blog Homepage: Karat
Heimlehrerservice "Kikagaku", bei dem Sie maschinelles Lernen einzeln lernen können Bitte zögern Sie nicht, uns zu kontaktieren, wenn Sie an "Kikagaku" interessiert sind, wo Sie sofort "Mathematik → Programmierung → Webanwendung" lernen können.
Recommended Posts