Täglich werden neue Algorithmen für Optimierungsmethoden in neuronalen Netzen erstellt. Im vorherigen Artikel habe ich zusammengefasst, wie es von SGD zu ADAM entwickelt wurde.
https://qiita.com/Fumio-eisan/items/798351e4915e4ba396c2
In diesem Artikel möchte ich diese Optimierungstechnik implementieren und sehen, wie schnell sie in einem neuronalen Netzwerk konvergiert! .. Dieses Mal möchte ich diese Optimierungsmethode auf eine einfache quadratische Funktion anwenden. Nehmen Sie in Lehrbüchern usw. grundsätzlich ein handgeschriebenes numerisches Bild wie MNIST als Beispiel und bestätigen Sie, dass der Wert der Verlustfunktion abnimmt. Da jedoch die Verlustfunktion im neuronalen Netzwerk sehr kompliziert ist, ist es schwierig zu erkennen, ob der Minimalwert abgeleitet wird. Daher möchte ich dieses Mal eine quadratische Funktion als Beispiel nehmen und sehen, wie sie sich dem Minimalwert nähert. Außerdem habe ich das Definieren und Laden der Klasse selbst implementiert, aber ich werde feststellen, was ich dort verstanden habe.
Dies ist eine Übersicht.
Hier ist der Zweck der quadratischen Funktion und der Optimierungsmethode, die dieses Mal angestrebt werden.
Ich habe mich entschlossen, den Mindestwert einer sehr leicht verständlichen Funktion zu finden. Da $ y = x ^ 2 $, wird $ y $, das den Mindestwert annimmt, zu $ y = 0 $, wenn $ x = 0 $. Ich möchte diese Funktion verwenden, die sowohl sinnlich als auch visuell leicht zu verstehen ist, um $ x $ ständig zu aktualisieren und zu bestätigen, dass sie sich $ y = 0 $ nähert.
Dieses Mal wird das Programm, das die Funktion definiert, in optimizers.py gespeichert. Anschließend wird die Funktion in sample.ipynb gelesen, berechnet und dargestellt. Daher würden wir uns bei der Implementierung freuen, wenn Sie diese beiden Programme im selben Ordner speichern und ausführen könnten.
Erstens ist die grundlegende SGD. Die Formel ist unten gezeigt.
\mathbf{x}_{t + 1} \gets \mathbf{x}_{t} - \eta g_t\\
g_t = 2 *\mathbf{x}_{t}
$ \ eta $ ist die Lernrate und $ g_t $ ist der Gradient der Funktion. $ g_t $ ist diesmal $ 2 * \ mathbf {x} _ {t} $, also ist es praktisch.
Als nächstes werden wir diese Technik implementieren.
optimizers.py
class SGD:
def __init__(self, lr = 0.01,x=100):
self.lr = 0.01
self.x =100.0
def update(self,x):
x+= -self.lr * 2*x
return x
Die Formel selbst ist einfach, daher denke ich, dass es leicht zu verstehen ist, wenn man sich das Programm ansieht. Diese Funktion berechnet im nächsten Schritt $ x $ und gibt $ x $ zurück. $ \ Eta $ wird hier als $ lr $ geschrieben.
Hier ist ein Programm, das wiederholt $ x $ berechnet, um tatsächlich den Mindestwert zu finden.
sample.ipynb
max_iterations = 100
y7=[]
y8=[]
y9=[]
v7=[]
v8=[]
v9=[]
optimizer = optimizers.SGD()
x = 100
optimizer.lr =0.1
for i in range(max_iterations):
x = optimizer.update(x)
y7.append(x)
v7.append(optimizer.lr)
x = 100
optimizer.lr =0.01
for i in range(max_iterations):
x = optimizer.update(x)
y8.append(x)
v8.append(optimizer.lr)
x = 100
optimizer.lr =0.9
for i in range(max_iterations):
x = optimizer.update(x)
y9.append(x)
v9.append(optimizer.lr)
Mal sehen, wie sich die Konvergenz der Funktion ändert, wenn wir $ \ eta $ auf 0.1,0.01,0.9 ändern.
sample.ipynb
x = np.arange(max_iterations)
plt.plot(x, y7, label='lr=0.1')
plt.plot(x, y8, label='lr=0.01')
plt.plot(x, y9, label='lr=0.9')
plt.xlabel("iterations")
plt.ylabel("y")
plt.ylim(-5, 120)
plt.legend()
plt.show()
Sie können sehen, dass je näher sich der Wert von $ y $ auf der vertikalen Achse 0 nähert, desto mehr konvergiert er.
Wenn $ \ eta $ 0,01 ist, dauert die Konvergenz einige Zeit. Im Gegenteil, wenn $ \ eta $ bis zu 0,9 zu groß ist, können Sie sehen, dass es während der Jagd zur Konvergenz kommt. Wenn dieser Wert in dieser Funktion 1 oder mehr beträgt, wird er abweichen. Daher ist ersichtlich, dass $ \ eta $ ein guter Wert um 0,1 ist, der schnell konvergiert und Divergenz unterdrückt.
Als nächstes werden wir Momentum implementieren. Im Vergleich zum vorherigen SGD unterdrückt dieser Algorithmus Vibrationen, indem er die Bewegung von $ x $ selbst berücksichtigt.
\mathbf{x}_{t + 1} \gets \mathbf{x}_{t} + h_t\\
h_t=-\eta * g_t +\alpha * h_{t-1}
Definieren Sie eine Funktion.
optimizers.py
class Momentum:
def __init__(self,lr=0.01,alpha=0.8,v=None):
self.lr = 0.01
self.v = 0.0
self.alpha = 0.8
def update(self,x):
self.v = self.v*self.alpha - (2.0)*x*self.lr
x += + self.v
return x
Und Renn. Dieses Mal werden wir den Effekt bewerten, indem wir den Wert von $ \ alpha $ als Hyperparameter ändern.
Der Standard $ \ alpha $ soll 0,8 sein. Selbst in diesem Ergebnis können wir sehen, dass 0,8 ein Wert ist, der genau richtig zu sein scheint. Wenn der Wert größer als dieser Wert ist, werden Sie viel jagen.
Nun, diesmal ist der letzte AdaGrad. Bisher war die Lernrate $ \ eta $ konstant. Das Merkmal ist jedoch, dass diese Lernrate selbst den Effekt hat, dass sie mit der Anzahl der Berechnungen allmählich abnimmt.
h_{0} = \epsilon\\
h_{t} = h_{t−1} + g_t^{2}\\
\eta_{t} = \frac{\eta_{0}}{\sqrt{h_{t}}}\\
\mathbf{x}_{t+1} = \mathbf{w}^{t} - \eta_{t}g_t
Definieren Sie eine Funktion.
optimizers.py
class AdaGrad:
def __init__(self,h0=10.0):
self.v = 0.0
self.h = 0.0
self.h0 = 10.0
def update(self,x):
self.h += + (2.0*x)**2
self.v = -self.h0/(np.sqrt(self.h)+1e-7)
x += + self.v*2*x
return x
Übrigens habe ich diesmal berechnet, indem ich den Anfangswert der Lernrate $ \ eta_0 $ (h0 im Programm) geändert habe.
Es stellte sich heraus, dass $ \ eta_0 $ um 100 schneller konvergiert und nicht divergiert.
Da ich ein Anfänger in Python bin, habe ich init in meiner Klasse mit einem starken Eindruck verwendet. Dieses Mal fand ich Folgendes.
Argumente, die durch init (self, argument) definiert sind, können nach dem Aufruf von class in Anführungszeichen gesetzt werden, um die Parameter des Arguments zu ändern.
Wenn Sie dieses Argument nicht schreiben, können Sie die Parameter nach dem Aufruf der Klasse nicht ändern.
Dieses Mal wurde die Funktion durch drei Arten von Optimierungsmethoden minimiert. Sie können sehen, dass es die Idee der schrittweisen Formel verwendet, die in der sogenannten High-School-Mathematik gelernt wurde. Obwohl ich alles außer Numpy gemacht habe, hat es mir geholfen, mein Verständnis der Programmierung selbst zu vertiefen. Wie ich in O'Reillys Deep-Learning-Buch erfahren habe, implementiere ich tatsächlich eine Optimierungsmethode in einem neuronalen Netzwerk. Sie können jeden Inhalt wie die Definition von Funktionen und kleinen Variablen, das Einfügen einer Aktivierungsfunktion, die Gradientenberechnung durch die Methode der inversen Fehlerausbreitung, die Bestimmung des Anfangswertes des Gewichtsparameters usw. verstehen. Wenn es jedoch um die Programmierung geht, wird es sehr kompliziert.
** Ich fragte mich erneut, ob die Programmierer eine Kombination dieser vielen Regeln und strukturellen Kenntnisse implementieren würden, was eine entmutigende Aufgabe wäre. Aufgrund dieser Schwierigkeit möchte ich Ihnen dafür danken, dass Sie es als Klasse oder Methode bezeichnet haben und die Funktion problemlos verwenden können. ** ** **
Das vollständige Programm ist hier gespeichert. https://github.com/Fumio-eisan/optimizers_20200326
Recommended Posts