Problem
Mit Mini-Batch-Gradientenabstieg wird fast jedes neuronale Netz trainiert: Teile die Daten in kleine Batches und aktualisiere die Gewichte nach jedem.
Trainiere y = w × x + b auf dem mittleren quadratischen Fehler, beginnend mit w = 0 und b = 0. Teile die Beispiele in jeder Epoche der Reihe nach in Batches zu je batch_size (der letzte Batch darf kleiner sein). Für jeden Batch der Größe n:
- errorᵢ = w × xᵢ + b - yᵢ für jedes Beispiel im Batch
- dw = (2 / n) × Σ errorᵢ × xᵢ und db = (2 / n) × Σ errorᵢ
- w ← w - learning_rate × dw und b ← b - learning_rate × db
Implementiere train_mini_batch(xs, ys, batch_size, learning_rate, epochs).
Eingabe
xs, ys: Die Datenpunkte (gleiche Länge).
batch_size: Beispiele pro Batch.
learning_rate, epochs: Die Schrittweite und die Anzahl der Durchläufe über die Daten.
Ausgabe
Gib nach dem Training [w, b] zurück.
Einschränkungen
1 ≤ Anzahl der Punkte ≤ 1.000, 1 ≤ batch_size ≤ Anzahl der Punkte, 0 ≤ epochs ≤ 1.000
0 < learning_rate ≤ 1
-100 ≤ jeder Wert ≤ 100
Beispiele
Eingabe:
xs = [1.0, 2.0, 3.0]
ys = [2.0, 4.0, 6.0]
epochs = 1
batch_size = 2
learning_rate = 0.1
Erwartete Ausgabe:
expected = [2.44, 1.08]
Eingabe:
std::vector<double> xs = {1.0, 2.0, 3.0};
std::vector<double> ys = {2.0, 4.0, 6.0};
long long epochs = 1;
long long batch_size = 2;
double learning_rate = 0.1;
Erwartete Ausgabe:
std::vector<double> expected = {2.44, 1.08};
Eingabe:
double[] xs = new double[] {1.0, 2.0, 3.0};
double[] ys = new double[] {2.0, 4.0, 6.0};
long epochs = 1;
long batch_size = 2;
double learning_rate = 0.1;
Erwartete Ausgabe:
double[] expected = new double[] {2.44, 1.08};
Erläuterung
Batch 1 ist x = [1, 2]: Fehler -2 und -4, dw = -10, db = -6, also w = 1 und b = 0.6. Batch 2 ist x = [3] allein: Fehler 1×3 + 0.6 - 6 = -2.4, dw = 2 × (-2.4) × 3 = -14.4 und db = -4.8, also w = 2.44 und b = 1.08. Ergebnis: [2.44, 1.08].
Eingabe:
xs = [1.0, 2.0, 3.0, 4.0]
ys = [3.0, 5.0, 7.0, 9.0]
epochs = 1
batch_size = 4
learning_rate = 0.05
Erwartete Ausgabe:
expected = [1.75, 0.6]
Eingabe:
std::vector<double> xs = {1.0, 2.0, 3.0, 4.0};
std::vector<double> ys = {3.0, 5.0, 7.0, 9.0};
long long epochs = 1;
long long batch_size = 4;
double learning_rate = 0.05;
Erwartete Ausgabe:
std::vector<double> expected = {1.75, 0.6};
Eingabe:
double[] xs = new double[] {1.0, 2.0, 3.0, 4.0};
double[] ys = new double[] {3.0, 5.0, 7.0, 9.0};
long epochs = 1;
long batch_size = 4;
double learning_rate = 0.05;
Erwartete Ausgabe:
double[] expected = new double[] {1.75, 0.6};
Erläuterung
Ein Batch so groß wie der Datensatz ist gewöhnlicher Batch-Gradientenabstieg: eine Aktualisierung pro Epoche. Ergebnis: [1.75, 0.6].
So gehst du vor
Versuch es zuerst allein und öffne dann einen Hinweis nach dem anderen.
Hinweis 1
Verarbeite die Samples in der gegebenen Reihenfolge und aktualisiere die Parameter nach jedem Batch statt nach jedem einzelnen Punkt.
Hinweis 2
Berechne für jedes Batch zuerst die Vorhersagefehler und nutze dann ihre Mittelwerte zusammen mit den x-Werten für die beiden Gradienten.
Hinweis 3
Das letzte Batch kann kleiner sein als die anderen, daher muss seine Gradientenskalierung die Größe dieses Batches verwenden.
Erwartete Komplexität
Zeit O(epochs × n), zusätzlicher Speicher O(1)
Referenzen
Diese Aufgabe wurde für CodeUtility angepasst. Beachte die oben genannten Vorgaben und Einschränkungen.