Comparaison SGD vs Momentum vs Adam Optimizer

Exécutez les trois optimiseurs sur la même fonction de perte « vallée longue et étroite » pour visualiser les chemins de convergence et les différences de vitesse.

À la fin de ce tutoriel, vous comprendrez :SGD oscille, Momentum s'appuie sur l'inertie pour lisser, Adam ajuste de manière adaptative la taille du pas—les principes mathématiques et les effets intuitifs des trois stratégies.


Analogie de la vie quotidienne

Descendre une route sinueuse—trois stratégies

Stratégie SGD : ne regardez que vos pieds, allez toujours dans la direction la plus raide. Face à un ravin étroit, elle rebondit d'un côté à l'autre.

Stratégie Momentum : comme faire rouler une boule de neige—souvenez-vous de la direction de la vitesse précédente, et l'inertie lui permet de franchir rapidement les petits nids-de-poule.

Stratégie Adam : non seulement elle a de l'inertie, mais elle ajuste aussi la foulée selon l'état de chaque portion de route—faites de petits pas dans les pentes raides, et de grandes enjambées sur terrain plat.


Compréhension intuitive

SGD
theta -= lr * g
Direction pure du gradient, aucune information historique, oscille dans les directions raides
Momentum
v = beta*v + (1-beta)*g
theta -= lr * v
Accumule les gradients historiques ; l’inertie supprime les oscillations
Adam
m = beta1*m + (1-beta1)*g
v = beta2*v + (1-beta2)*g^2
theta -= lr * m_hat/(sqrt(v_hat)+eps)
Momentum + taux d’apprentissage adaptatif, chaque paramètre ajuste sa taille de pas indépendamment

Fonction de test : \(f(x, y) = 0.5x^2 + 5y^2\) — une longue vallée étroite où la direction x est douce et la direction y est raide.


Exercices pratiques Python

Exemple

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("EXEMPLE comparaison de trois optimiseurs (point de départ [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 "non convergé")
    n_osc = np.sum(np.diff(np.sign(hist[:, 1])) != 0)
    print(f" {name:10s}: {str(conv):>6s} étapes pour converger, oscillation de y {n_osc} fois, perte={f(hist[-1]):.6f}")
EXAMPLE 三种优化器对比 (起点 [4,4]):

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

Scénarios d'application en IA

ScénarioOptimiseur recommandéRaison
La plupart des tâchesAdam/AdamWAdaptatif, convergence rapide, peu de paramètres à régler
Entraînement de TransformerAdamWGPT/BERT l'utilisent tous les deux
Lorsqu'une précision extrême est nécessaireSGD+MomentumLa capacité de généralisation est parfois meilleure
Autres extensions