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.
quelle
Antworten:
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:
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:
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:
Sie sollten auf jeden Fall so etwas tun:
was wiederum für Mini-Batches leicht zu verallgemeinern ist:
quelle
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.
quelle