Mittel 0 gelöst 0% Erfolgsquote

Adam-Optimierer

Implementiere Adam, den Standardoptimierer des Deep Learning, mit gleitenden Mittelwerten und Bias-Korrektur.

Das lernst du

  • Mittelwerte des ersten und zweiten Moments verfolgen
  • In frühen Schritten die Bias-Korrektur anwenden
  • Den Standardoptimierer des Deep Learning implementieren

Problem

Adam führt pro Gewicht zwei gleitende Mittelwerte, des Gradienten (m) und des quadrierten Gradienten (v), und gibt damit jedem Gewicht eine eigene Schrittweite.

Beginne mit m = 0 und v = 0 für jedes Gewicht. Für jeden Schritt t = 1, 2, 3, … mit Gradient g:

  1. m ← beta1 × m + (1 - beta1) × g
  2. v ← beta2 × v + (1 - beta2) × g²
  3. m̂ = m / (1 - beta1ᵗ) und v̂ = v / (1 - beta2ᵗ) (Bias-Korrektur)
  4. w ← w - learning_rate × m̂ / (√v̂ + epsilon)

Implementiere adam_steps(gradients, weights, learning_rate, beta1, beta2, epsilon) und wende pro Zeile von gradients ein Update an, in Reihenfolge.

Eingabe

gradients: Eine Zeile pro Schritt; jede Zeile hat einen Gradienten pro Gewicht.

weights: Die Startgewichte.

learning_rate, beta1, beta2, epsilon: Die Hyperparameter von Adam (üblich sind 0.001, 0.9, 0.999 und 0.00000001).

Ausgabe

Gib die Gewichte nach allen Schritten zurück.

Einschränkungen

0 ≤ Schritte ≤ 1.000, 1 ≤ Gewichte ≤ 100

0 < learning_rate ≤ 1, 0 ≤ beta1, beta2 < 1, 0 < epsilon ≤ 0.001

-100 ≤ jeder Wert ≤ 100

Beispiele

Beispiel 1
Eingabe:
beta1 = 0.9
beta2 = 0.999
epsilon = 1.0e-08
weights = [1.0]
gradients = [
    [2.0]
]
learning_rate = 0.1

Erwartete Ausgabe:
expected = [0.9]
Eingabe:
double beta1 = 0.9;
double beta2 = 0.999;
double epsilon = 1.0e-08;
std::vector<double> weights = {1.0};
std::vector<std::vector<double>> gradients = {
    {2.0}
};
double learning_rate = 0.1;

Erwartete Ausgabe:
std::vector<double> expected = {0.9};
Eingabe:
double beta1 = 0.9;
double beta2 = 0.999;
double epsilon = 1.0e-08;
double[] weights = new double[] {1.0};
double[][] gradients = new double[][] {
    new double[] {2.0}
};
double learning_rate = 0.1;

Erwartete Ausgabe:
double[] expected = new double[] {0.9};

Erläuterung

m = 0.1 × 2 = 0.2 und v = 0.001 × 4 = 0.004. Die Bias-Korrektur ergibt m̂ = 0.2 / 0.1 = 2 und v̂ = 0.004 / 0.001 = 4, also ist der Schritt 0.1 × 2 / √4 = 0.1: w = 0.9. Im ersten Schritt bewegt Adam jedes Gewicht ungefähr um die Lernrate, unabhängig von der Größe des Gradienten.

Beispiel 2
Eingabe:
beta1 = 0.9
beta2 = 0.999
epsilon = 1.0e-08
weights = [0.0, 0.0]
gradients = [
    [100.0, 0.01]
]
learning_rate = 0.01

Erwartete Ausgabe:
expected = [-0.01, -0.01]
Eingabe:
double beta1 = 0.9;
double beta2 = 0.999;
double epsilon = 1.0e-08;
std::vector<double> weights = {0.0, 0.0};
std::vector<std::vector<double>> gradients = {
    {100.0, 0.01}
};
double learning_rate = 0.01;

Erwartete Ausgabe:
std::vector<double> expected = {-0.01, -0.01};
Eingabe:
double beta1 = 0.9;
double beta2 = 0.999;
double epsilon = 1.0e-08;
double[] weights = new double[] {0.0, 0.0};
double[][] gradients = new double[][] {
    new double[] {100.0, 0.01}
};
double learning_rate = 0.01;

Erwartete Ausgabe:
double[] expected = new double[] {-0.01, -0.01};

Erläuterung

Die Gradienten unterscheiden sich um den Faktor 10.000, trotzdem bewegen sich beide Gewichte um etwa 0.01, auf [-0.01, -0.01]: Adam skaliert jeden Schritt mit der Größe des jeweiligen Gradienten.

Referenzen

Diese Aufgabe wurde für CodeUtility angepasst. Beachte die oben genannten Vorgaben und Einschränkungen.

Von anderen lernen

Community-Lösungen

Noch keine veröffentlichten Lösungen. Löse die Aufgabe und teile als Erster eine Lösung.