Stochastischer Gradientenabstieg basierend auf Vektoroperationen?


10

Nehmen wir an, ich möchte einen stochastischen Regressionsalgorithmus für den Gradientenabstieg unter Verwendung eines Datensatzes mit N Stichproben trainieren. Da die Größe des Datensatzes festgelegt ist, werde ich die Daten T-mal wiederverwenden. Bei jeder Iteration oder "Epoche" verwende ich jedes Trainingsmuster genau einmal, nachdem ich den gesamten Trainingssatz zufällig neu angeordnet habe.

Meine Implementierung basiert auf Python und Numpy. Daher kann die Verwendung von Vektoroperationen die Rechenzeit erheblich verkürzen. Die Entwicklung einer vektorisierten Implementierung des Batch-Gradienten-Abstiegs ist recht einfach. Im Fall eines stochastischen Gradientenabfalls kann ich jedoch nicht herausfinden, wie die äußere Schleife vermieden werden kann, die in jeder Epoche durch alle Proben iteriert.

Kennt jemand eine vektorisierte Implementierung des stochastischen Gradientenabstiegs?

BEARBEITEN : Ich wurde gefragt, warum ich den Online-Gradientenabstieg verwenden möchte, wenn die Größe meines Datensatzes festgelegt ist.

Aus [1] ist ersichtlich, dass der Online-Gradientenabstieg langsamer als der Batch-Gradientenabstieg auf das Minimum der empirischen Kosten konvergiert. Es konvergiert jedoch schneller auf das Minimum der erwarteten Kosten, wodurch die Generalisierungsleistung gemessen wird. Ich möchte die Auswirkungen dieser theoretischen Ergebnisse auf mein spezielles Problem durch Kreuzvalidierung testen. Ohne eine vektorisierte Implementierung ist mein Online-Gradientenabstiegscode viel langsamer als der Batch-Gradientenabstiegscode. Dies erhöht die Zeit, die erforderlich ist, um den Kreuzvalidierungsprozess abzuschließen, erheblich.

EDIT : Ich füge hier den Pseudocode meiner Online-Gradientenabstiegsimplementierung ein, wie von ffriend angefordert. Ich löse ein Regressionsproblem.

Method: on-line gradient descent (regression)
Input: X (nxp matrix; each line contains a training sample, represented as a length-p vector), Y (length-n vector; output of the training samples)
Output: A (length-p+1 vector of coefficients)

Initialize coefficients (assign value 0 to all coefficients)
Calculate outputs F
prev_error = inf
error = sum((F-Y)^2)/n
it = 0
while abs(error - prev_error)>ERROR_THRESHOLD and it<=MAX_ITERATIONS:
    Randomly shuffle training samples
    for each training sample i:
        Compute error for training sample i
        Update coefficients based on the error above
    prev_error = error
    Calculate outputs F
    error = sum((F-Y)^2)/n
    it = it + 1

[1] "Online-Lernen in großem Maßstab", L. Bottou, Y. Le Cunn, NIPS 2003.


2
Teilen Sie den Datensatz in Mini-Batches auf und passen Sie das Modell nacheinander an jeden Mini-Batch an.
Freund

Vielen Dank an @ffriend. Dies wäre jedoch keine reine Online-Implementierung.
Pablo Suau

1
Was ist der Grund für die Verwendung der "reinen Online" -Implementierung, wenn Ihr Datensatz repariert ist? SGD sagt nur, dass Sie nicht den gesamten Datensatz auf einmal iterieren müssen, sondern ihn in eine beliebige Anzahl von Teilen (Mini-Batches) aufteilen und einzeln verarbeiten können. Mini-Batch der Größe 1 ist nur dann sinnvoll, wenn Sie über eine kontinuierliche und möglicherweise endlose Datenquelle verfügen (z. B. Twitter-Feed) und das Modell nach jeder neuen Beobachtung aktualisieren möchten. Dies ist jedoch ein sehr seltener Fall und definitiv nicht für feste Datensätze.
Freund

Entschuldigung für meine sehr späte Antwort. Bitte überprüfen Sie den Text, den ich der ursprünglichen Frage hinzugefügt habe.
Pablo Suau

1
Können Sie Ihre Implementierung zeigen? Ich sehe Missverständnisse, aber ohne Codebeispiel wird es schwierig sein, es zu erklären.
Freund

Antworten:


10

Zunächst wird das Wort "Stichprobe" normalerweise verwendet, um eine Teilmenge der Bevölkerung zu beschreiben , daher beziehe ich mich auf dasselbe wie "Beispiel".

Ihre SGD-Implementierung ist aufgrund dieser Zeile langsam:

for each training example i:

Hier verwenden Sie explizit genau ein Beispiel für jede Aktualisierung von Modellparametern. Per Definition ist die Vektorisierung eine Technik zum Konvertieren von Operationen an einem Element in Operationen an einem Vektor solcher Elemente. Nein, Sie können Beispiele nicht einzeln verarbeiten und trotzdem die Vektorisierung verwenden.

Sie können jedoch ungefähre wahre SGD unter Verwendung von Mini-Chargen . Mini-Batch ist eine kleine Teilmenge des Originaldatensatzes (z. B. 100 Beispiele). Sie berechnen Fehler- und Parameteraktualisierungen basierend auf Mini-Batches, durchlaufen jedoch immer noch viele davon ohne globale Optimierung, wodurch der Prozess stochastisch wird. Um Ihre Implementierung viel schneller zu machen, reicht es aus, die vorherige Zeile zu ändern in:

batches = split dataset into mini-batches
for batch in batches: 

und berechnen Sie den Fehler aus der Charge, nicht aus einem einzigen Beispiel.

Obwohl dies ziemlich offensichtlich ist, sollte ich auch die Vektorisierung auf Beispielebene erwähnen. Das heißt, statt so etwas:

theta = np.array([...])  # parameter vector
x = np.array([...])      # example
y = 0                    # predicted response
for i in range(len(example)):
    y += x[i] * theta[i]
error = (true_y - y) ** 2  # true_y - true value of response

Sie sollten auf jeden Fall so etwas tun:

error = (true_y - sum(np.dot(x, theta))) ** 2

was wiederum für Mini-Batches leicht zu verallgemeinern ist:

true_y = np.array([...])     # vector of response values
X = np.array([[...], [...]]) # mini-batch
errors = true_y - sum(np.dot(X, theta), 1)
error = sum(e ** 2 for e in errors)

1
Ich denke, das ist der richtige Weg. Mini-Batches mit einer ausgewählten Größe können tatsächlich schneller konvergieren als Batch- oder Online-Versionen (erstere aktualisieren die Gewichte nur einmal pro Satz und letztere können nicht vektorisiert werden und haben häufiger zusätzliche Schritte zur Gewichtsaktualisierung)
Neil Slater

Danke euch beiden. Entschuldigung für die hartnäckige Ablehnung von Mini-Chargen, aber ich war mir nicht sicher, welche Auswirkungen diese Methode auf die Konvergenzrate hat. Neil, kommt deine Bestätigung aus deiner eigenen Erfahrung oder gibt es theoretisch / empirisch veröffentlichte Ergebnisse?
Pablo Suau

1
@PabloSuau Sie können Andrew Ngs Kurs über maschinelles Lernen in Coursera, Woche 10, überprüfen. Er erklärt, warum die Konvergenz schneller sein kann als SGD und Batch-GD. Genauer gesagt: Es sollte immer so schnell sein wie SGD, aber manchmal sollte es in der Praxis sogar noch schneller sein.
gaborous

1

Schauen Sie sich die Partial_fit- Methode des SGD-Klassifikators von scikit an . Sie haben die Kontrolle darüber, was Sie damit aufrufen: Sie können das "echte" Online-Lernen durchführen, indem Sie jeweils eine Instanz übergeben, oder Sie können Instanzen in Mini-Batches stapeln, wenn alle Ihre Daten in einem Array verfügbar sind. Wenn dies der Fall ist, können Sie das Array in Scheiben schneiden, um die Minibatches bereitzustellen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.