Vergleich: SGD vs. Momentum vs. Adam-Optimizer

Führe die drei Optimierer auf derselben Verlustfunktion "langes schmales Tal" aus, um die Konvergenzpfade und Geschwindigkeitsunterschiede zu visualisieren.

Am Ende dieses Tutorials wirst du verstehen:SGD oszilliert, Momentum nutzt Trägheit zum Glätten, Adam passt die Schrittweite adaptiv an – die mathematischen Prinzipien und intuitiven Effekte der drei Strategien.


Alltagsanalogie

Bergab auf einer kurvenreichen Straße – drei Strategien

SGD-Strategie: Nur auf die Füße schauen, immer in die steilste Richtung gehen. Bei einer engen Rinne pendelt es hin und her.

Momentum-Strategie: Wie das Rollen eines Schneeballs – die Richtung der vorherigen Geschwindigkeit merken, und die Trägheit lässt ihn über kleine Schlaglöcher hinwegrauschen.

Adam-Strategie: Hat nicht nur Trägheit, sondern passt die Schrittlänge an den Zustand jedes Straßenabschnitts an – kleine Schritte an steilen Hängen, große Schritte auf flachem Boden.


Intuitive Vorstellung

SGD
theta -= lr * g
Reine Gradientenrichtung, keine historischen Informationen, oszilliert in steilen Richtungen
Momentum
v = beta*v + (1-beta)*g
theta -= lr * v
Sammelt historische Gradienten; Trägheit unterdrückt Oszillation
Adam
m = beta1*m + (1-beta1)*g
v = beta2*v + (1-beta2)*g^2
theta -= lr * m_hat/(sqrt(v_hat)+eps)
Momentum + adaptive Lernrate, jeder Parameter passt seine Schrittweite unabhängig an

Testfunktion: \(f(x, y) = 0.5x^2 + 5y^2\) – ein langes schmales Tal, in dem die x-Richtung flach und die y-Richtung steil ist.


Python-Praxisübung

Beispiel

import numpy as np

def f(pos):
    x, y = pos
    return 0.5 * x**2 + 5 * y**2

def grad(pos):
    x, y = pos
    return np.array([x, 10 * y])


def sgd(start, lr=0.1, steps=60):
    pos = np.array(start, dtype=float)
    history = [pos.copy()]
    for _ in range(steps):
        pos = pos - lr * grad(pos)
        history.append(pos.copy())
    return np.array(history)


def momentum(start, lr=0.1, beta=0.9, steps=60):
    pos = np.array(start, dtype=float)
    v = np.zeros_like(pos)
    history = [pos.copy()]
    for _ in range(steps):
        g = grad(pos)
        v = beta * v + (1 - beta) * g
        pos = pos - lr * v
        history.append(pos.copy())
    return np.array(history)


def adam(start, lr=0.3, beta1=0.9, beta2=0.999, eps=1e-8, steps=60):
    pos = np.array(start, dtype=float)
    m = np.zeros_like(pos)
    v = np.zeros_like(pos)
    history = [pos.copy()]
    for t in range(1, steps + 1):
        g = grad(pos)
        m = beta1 * m + (1 - beta1) * g
        v = beta2 * v + (1 - beta2) * (g ** 2)
        m_hat = m / (1 - beta1 ** t)
        v_hat = v / (1 - beta2 ** t)
        pos = pos - lr * m_hat / (np.sqrt(v_hat) + eps)
        history.append(pos.copy())
    return np.array(history)


start = [4.0, 4.0]
results = {
    "SGD": sgd(start, lr=0.1),
    "Momentum": momentum(start, lr=0.1),
    "Adam": adam(start, lr=0.3),
}

print("BEISPIEL Vergleich der drei Optimierer (Startpunkt [4,4]):\n")
for name, hist in results.items():
    dists = np.linalg.norm(hist, axis=1)
    mask = dists < 0.05
    conv = (np.argmax(mask) if mask.any() else "nicht konvergiert")
    n_osc = np.sum(np.diff(np.sign(hist[:, 1])) != 0)
    print(f" {name:10s}: {str(conv):>6s} Schritte bis zur Konvergenz, y-Oszillation {n_osc} Mal, Verlust={f(hist[-1]):.6f}")
EXAMPLE 三种优化器对比 (起点 [4,4]):

  SGD      : 未收敛 步收敛, y震荡36次, 损失=0.000035
  Momentum :     21 步收敛, y震荡6次,  损失=0.000000
  Adam     :     16 步收敛, y震荡0次,  损失=0.000000

Anwendungsszenarien in der KI

SzenarioEmpfohlener OptimiererGrund
Die meisten AufgabenAdam/AdamWAdaptiv, schnelle Konvergenz, wenige Parameter abzustimmen
Transformer-TrainingAdamWGPT/BERT verwenden es beide
Wenn extrem hohe Präzision erforderlich istSGD+MomentumDie Generalisierungsfähigkeit ist manchmal besser
Andere Erweiterungen