Es gibt nur einen kleinen Unterschied zwischen Gradientenabstieg und stochastischem Gradientenabstieg. Der Gradientenabstieg berechnet den Gradienten basierend auf der Verlustfunktion, die über alle Trainingsinstanzen berechnet wurde, während der stochastische Gradientenabstieg den Gradienten basierend auf dem Verlust in Chargen berechnet. Beide Techniken werden verwendet, um optimale Parameter für ein Modell zu finden.
Versuchen wir, SGD in diesem 2D-Datensatz zu implementieren.
Der Algorithmus
Der Datensatz verfügt über zwei Funktionen. Wir möchten jedoch einen Bias-Term hinzufügen, damit wir eine Spalte mit Einsen an das Ende der Datenmatrix anhängen.
shape = x.shape
x = np.insert(x, 0, 1, axis=1)
Dann initialisieren wir unsere Gewichte, es gibt viele Strategien, um dies zu tun. Der Einfachheit halber werde ich sie alle auf 1 setzen, aber das zufällige Einstellen der Anfangsgewichte ist wahrscheinlich besser, um mehrere Neustarts verwenden zu können.
w = np.ones((shape[1]+1,))
Unsere erste Zeile sieht so aus
Jetzt werden wir die Gewichte des Modells iterativ aktualisieren, wenn es fälschlicherweise ein Beispiel klassifiziert.
for ix, i in enumerate(x):
pred = np.dot(i,w)
if pred > 0: pred = 1
elif pred < 0: pred = -1
if pred != y[ix]:
w = w - learning_rate * pred * i
Diese Linie ist das Gewichtsupdate w = w - learning_rate * pred * i
.
Wir können sehen, dass ein kontinuierlicher Prozess zu Konvergenz führen wird.
Nach 10 Epochen
Nach 20 Epochen
Nach 50 Epochen
Nach 100 Epochen
Und schlussendlich,
Der Code
Den Datensatz für diesen Code finden Sie hier .
Die Funktion, mit der die Gewichte trainiert werden, wird in der Merkmalsmatrix übernommen x und die Ziele y. Es gibt die trainierten Gewichte zurückw und eine Liste der historischen Gewichte, die während des Trainingsprozesses angetroffen wurden.
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
def get_weights(x, y, verbose = 0):
shape = x.shape
x = np.insert(x, 0, 1, axis=1)
w = np.ones((shape[1]+1,))
weights = []
learning_rate = 10
iteration = 0
loss = None
while iteration <= 1000 and loss != 0:
for ix, i in enumerate(x):
pred = np.dot(i,w)
if pred > 0: pred = 1
elif pred < 0: pred = -1
if pred != y[ix]:
w = w - learning_rate * pred * i
weights.append(w)
if verbose == 1:
print('X_i = ', i, ' y = ', y[ix])
print('Pred: ', pred )
print('Weights', w)
print('------------------------------------------')
loss = np.dot(x, w)
loss[loss<0] = -1
loss[loss>0] = 1
loss = np.sum(loss - y )
if verbose == 1:
print('------------------------------------------')
print(np.sum(loss - y ))
print('------------------------------------------')
if iteration%10 == 0: learning_rate = learning_rate / 2
iteration += 1
print('Weights: ', w)
print('Loss: ', loss)
return w, weights
Wir werden diese SGD auf unsere Daten in perpptron.csv anwenden .
df = np.loadtxt("perceptron.csv", delimiter = ',')
x = df[:,0:-1]
y = df[:,-1]
print('Dataset')
print(df, '\n')
w, all_weights = get_weights(x, y)
x = np.insert(x, 0, 1, axis=1)
pred = np.dot(x, w)
pred[pred > 0] = 1
pred[pred < 0] = -1
print('Predictions', pred)
Zeichnen wir die Entscheidungsgrenze
x1 = np.linspace(np.amin(x[:,1]),np.amax(x[:,2]),2)
x2 = np.zeros((2,))
for ix, i in enumerate(x1):
x2[ix] = (-w[0] - w[1]*i) / w[2]
plt.scatter(x[y>0][:,1], x[y>0][:,2], marker = 'x')
plt.scatter(x[y<0][:,1], x[y<0][:,2], marker = 'o')
plt.plot(x1,x2)
plt.title('Perceptron Seperator', fontsize=20)
plt.xlabel('Feature 1 ($x_1$)', fontsize=16)
plt.ylabel('Feature 2 ($x_2$)', fontsize=16)
plt.show()
Um den Trainingsprozess zu sehen, können Sie die Gewichte drucken, während sie sich im Laufe der Epochen geändert haben.
for ix, w in enumerate(all_weights):
if ix % 10 == 0:
print('Weights:', w)
x1 = np.linspace(np.amin(x[:,1]),np.amax(x[:,2]),2)
x2 = np.zeros((2,))
for ix, i in enumerate(x1):
x2[ix] = (-w[0] - w[1]*i) / w[2]
print('$0 = ' + str(-w[0]) + ' - ' + str(w[1]) + 'x_1'+ ' - ' + str(w[2]) + 'x_2$')
plt.scatter(x[y>0][:,1], x[y>0][:,2], marker = 'x')
plt.scatter(x[y<0][:,1], x[y<0][:,2], marker = 'o')
plt.plot(x1,x2)
plt.title('Perceptron Seperator', fontsize=20)
plt.xlabel('Feature 1 ($x_1$)', fontsize=16)
plt.ylabel('Feature 2 ($x_2$)', fontsize=16)
plt.show()