Schritt für Schritt zur Theorie, Implementierung in Python und Analyse mit scikit-learn über den Algorithmus, der zuvor in "Klassifikation des maschinellen Lernens" verwendet wurde. Ich werde mit lernen. Ich schreibe es zum persönlichen Lernen, daher möchte ich, dass Sie alle Fehler übersehen.
Dieses Mal werde ich über die ** Gradientenabstiegsmethode ** sprechen, eine Methode zur Optimierung der Parameter der Verlustfunktion. Es ist gut, wenn eine Lösung mathematisch gefunden werden kann, aber es gibt nur wenige solcher Fälle auf der Welt. Es gibt verschiedene Verläufe als Methode zur Suche nach dem optimalen Wert, aber ich möchte einige mit Code zusammenfassen. Die Seiten, auf die ich mich wie üblich bezog, sind wie folgt. Vielen Dank.
Was ist laut Wikipedia die Gradientenmethode?
Gradientenmethode ist ein allgemeiner Begriff für Algorithmen, die Informationen über den Gradienten einer Funktion verwenden, um nach einer Lösung für ein Optimierungsproblem zu suchen.
Es steht geschrieben. In der einfachen Regression ist die Verlustfunktion $ E $ die Summe der Quadrate der Residuen
Wie üblich verwenden wir Scikit-Learn-Diabetes (Diabetesdaten).
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import datasets
diabetes = datasets.load_diabetes()
df = pd.DataFrame(diabetes.data, columns=diabetes.feature_names)
x = df['bmi'].values
y = diabetes.target
plt.scatter(x, y)
Die Steigung und der Abschnitt sind, wenn sie mathematisch gelöst werden, jeweils
Kippen Sie A.: 949.43526038395
Abschnitt b: 152.1334841628967
war.
Der steilste Gradientenabstieg ist die Idee, sich an einem Punkt der Verlustfunktion allmählich in die entgegengesetzte Richtung des Gradientenvektors zu bewegen. Die Steigung sei $$ nabla E $ und berechne
Für die Verlustfunktion
\frac{\partial{E}}{\partial{A}}=\sum(-2x_iy_i+2Ax_i^2+2Bx_i)
\\
=-2\sum(Ax_i+B-y_i)x_i \\
\frac{\partial{E}}{\partial{B}}=\sum(-2x_iy_i+2Ax_i+2B)
\\
=-2\sum(Ax_i+B-y_i) \\
Wird sein. Entscheiden Sie den Anfangswert entsprechend, ändern Sie $ A $ und $ B $ in der Gradientenrichtung mit der obigen Formel und stoppen Sie die Berechnung in einem angemessenen Stadium.
Weitere Überlegungen sind erforderlich, um den Anfangswert zu bestimmen, wie die Lernrate bestimmt wird und unter welchen Bedingungen die Berechnung abgebrochen werden kann. Die Gliederung lautet jedoch wie folgt.
Erstellt eine SteepestGradientDescent-Klasse, die die Methode mit dem steilsten Abstieg realisiert. Ich habe versucht, die Methode auf Scikit-Lernen abzustimmen. Die Lernrate war angemessen und wurde durch die Anzahl der Male abgeschnitten, nicht wenn der Fehler ausreichend klein wurde.
class SteepestGradientDescent:
def __init__(self, eta=0.001, n_iter=2000):
self.eta = eta
self.n_iter = n_iter
self.grad = np.zeros((2,))
self.loss = np.array([])
def fit(self, X, Y, w0):
self.w = w0
for _ in range(self.n_iter):
self.loss = np.append(self.loss, np.sum((Y-self.w[0]-self.w[1]*X)**2))
self.grad[0] = np.sum(-2*(Y-self.w[0]-self.w[1]*X))
self.grad[1] = np.sum(-2*X*(Y-self.w[0]-self.w[1]*X))
self.w -= self.eta * self.grad
def predict(self, x):
return (self.w[0] + self.w[1]*x)
@property
def coef_(self):
return self.w[1]
@property
def intercept_(self):
return self.w[0]
@property
def loss_(self):
return self.loss
Bei der Anpassungsmethode wird der Gradient für alle Daten berechnet und der Koeffizient aktualisiert. Gleichzeitig wurde auch der Wert der Verlustfunktion gespeichert, damit wir sehen konnten, wie das Lernen ablief.
Verwenden wir diese Klasse, um die Diabetesdaten zu approximieren und die Änderung des Verlusts in einem Diagramm darzustellen.
w0 = np.array([1.,1.])
model = SteepestGradientDescent()
model.fit(x, y, w0)
print("A: ", model.coef_)
print("B: ", model.intercept_)
loss = model.loss
plt.plot(np.arange(len(loss)), np.log10(loss))
plt.show()
A: 932.1335010668406
B: 152.13348416289668
Es ist jetzt mit dem mathematisch gelösten Wert. Sie können auch sehen, wie der Verlust abnimmt.
Bei der Methode mit dem steilsten Abstieg wurden alle Proben zur Berechnung des Gradienten verwendet. Die probabilistische Gradientenabstiegsmethode verwendet eine oder mehrere gemischte Daten, um die Parameter zu aktualisieren. Die Methode zur Verwendung mehrerer Methoden wird auch als Mini-Batch-Lernen bezeichnet.
Die Frage ist, was auf diese Weise zu tun ist, aber die Verlustfunktion kann abhängig von der Form mehrere Mindestwerte haben. Denken Sie an das Gelände, aber die Täler, die Sie sehen können, sind nicht immer die niedrigsten, und Sie finden möglicherweise tiefere Täler jenseits der Berge. Dieser scheinbar korrekte, aber nicht Talboden wird als ** lokale Lösung ** bezeichnet, und der untere Talboden wird als ** globale Lösung ** bezeichnet.
Die Methode mit dem steilsten Abstieg lässt sich leicht durch Auswahl des Anfangswertes in eine lokale Lösung umwandeln. Die Methode des probabilistischen Gradientenabstiegs wählt jedoch die Daten, die für die Gradientenberechnung verwendet werden, jedes Mal neu aus, wenn der Parameter aktualisiert wird, sodass die Möglichkeit besteht, eine globale Lösung über einem niedrigen Berg zu erreichen. Scheint höher zu sein.
Darüber hinaus eignet es sich für die Echtzeitverarbeitung, da die zu verwendenden Daten nicht festgelegt werden müssen.
Ich habe die StochasticGradientDescent-Klasse wie zuvor erstellt. Der Inhalt entspricht fast dem steilsten Abstieg, mit Ausnahme des aktualisierten Teils der Parameter. Die Größe des Mini-Batches kann nun festgelegt werden, wie viel für alle Daten verwendet werden soll. Ich erinnere mich an den Parameter mit dem geringsten Verlust und versuche, ihn zurückzugeben.
class StochasticGradientDescent:
def __init__(self, eta=0.01, n_iter=2000, sample_rate=0.1):
self.eta = eta
self.n_iter = n_iter
self.sample_rate = sample_rate
self.grad = np.zeros((2,))
self.loss = np.array([])
def fit(self, X, Y, w0):
self.w = w0
self.min_w = w0
n_samples = int(np.ceil(len(X)*self.sample_rate))
min_loss = 10**18
for _ in range(self.n_iter):
loss = np.sum((Y-self.w[0]-self.w[1]*X)**2)
if min_loss>loss:
min_loss = loss
self.min_w = self.w
self.loss = np.append(self.loss, loss)
for i in range(n_samples):
index = np.random.randint(0, len(X))
batch_x = X[index]
batch_y = Y[index]
self.grad[0] = np.sum(-2*(batch_y-self.w[0]-self.w[1]*batch_x))
self.grad[1] = np.sum(-2*batch_x*(batch_y-self.w[0]-self.w[1]*batch_x))
self.w -= self.eta * self.grad
def predict(self, x):
return (self.w[0] + self.w[1]*x)
@property
def coef_(self):
return self.min_w[1]
@property
def intercept_(self):
return self.min_w[0]
@property
def loss_(self):
return self.loss
Tun Sie dies und sehen Sie sich auch die Veränderungen des Verlusts an.
w0 = np.array([1.,1.])
model = StochasticGradientDescent()
model.fit(x, y, w0)
print("A: ", model.coef_)
print("B: ", model.intercept_)
loss = model.loss
plt.plot(np.arange(len(loss)), np.log10(loss))
plt.show()
A: 925.5203159922469
B: 146.8724188770836
Es unterscheidet sich ein wenig von der genauen Lösung und es fühlt sich an, als würde der Verlust wild werden. Ich fragte mich, ob die Spike-Höhe niedriger wäre, wenn die Lernrate gesenkt würde, und wenn es eine zufällige Stichprobenbeziehung gäbe oder wenn die Korrelation der ursprünglichen Stichprobe gering wäre, würde sie nicht zu einer exakten Lösung konvergieren. Das Einstellen der Parameter hier ist ein Problem.
Als Gradientenabstiegsmethode untersuchte ich die steilste Abstiegsmethode und die zu kaufende Geschwindigkeitsgradientenabstiegsmethode. In der Welt des Scikit-Lernens und des Tiefenlernens gibt es verschiedene andere Gradienten, aber die Grundlagen sind dieselben. Wenn Sie es Schritt für Schritt auf diese Weise betrachten, ist es möglicherweise einfacher, sich die Einstellung von Parametern vorzustellen.
Das nächste Mal möchte ich die Zusammenfassung der Regression sowie des Überlernens und der Regularisierung zusammenfassen.
Recommended Posts