Optimizers

August 2026Vladislav Kruglikov

This article focuses on how an optimizer converts an already computed gradient into a parameter update. It does not discuss whether that gradient was estimated using the full dataset, one sample, or a mini-batch. The optimizer is responsible for updating the trainable parameters of the model.

SGD

Stochastic Gradient Descent moves each parameter in the direction opposite to its current gradient:

θt+1=θtηgt\theta_{t+1}=\theta_t-\eta g_t

The negative gradient is the direction of the steepest local decrease for a sufficiently small step. The learning rate controls the distance moved. A rate that is too small wastes computation, while one that is too large can overshoot useful regions or make training diverge. Different parameters can have gradients with very different magnitudes, but SGD multiplies all of them by the same learning rate. More precisely, the loss can have steep and flat directions that combine changes to many parameters. Using one learning rate in every direction can cause SGD to oscillate across high-curvature directions while progressing slowly along low-curvature directions. Plain SGD stores no per-parameter optimizer state.

SGD with momentum

Momentum maintains an accumulated gradient that combines the current gradient with previous gradients:

mt=βmt1+gtm_t=\beta m_{t-1}+g_t θt=θt1ηmt\theta_t=\theta_{t-1}-\eta m_t

If gradients repeatedly point in a similar direction, their contributions accumulate and the optimizer moves faster in that direction. If a gradient alternates across a narrow valley, positive and negative contributions partially cancel, reducing oscillation. The momentum coefficient β\beta is commonly close to 0.90.9. Momentum stores one additional value per parameter.

NAG

Nesterov Accelerated Gradient (NAG) first moves to the point where the previous momentum is expected to take the parameters:

θ~t=θt1ηβmt1\widetilde\theta_t=\theta_{t-1}-\eta\beta m_{t-1} g~t=θL(θ~t)\widetilde g_t=\nabla_\theta L(\widetilde\theta_t)

It then updates the momentum with the gradient evaluated at that look-ahead point and applies the resulting direction:

mt=βmt1+g~tm_t=\beta m_{t-1}+\widetilde g_t θt=θt1ηmt\theta_t=\theta_{t-1}-\eta m_t

The difference from ordinary momentum is which gradient is added when computing mtm_t. Ordinary momentum adds gtg_t, evaluated at the current parameters θt1\theta_{t-1}. NAG adds g~t\widetilde g_t, evaluated at the future point where the previous momentum would move the parameters. This lets the gradient correct the direction before the complete momentum step is applied and can reduce overshooting. Its importance for deep-network optimization was examined by Sutskever et al. Like ordinary momentum, NAG stores one additional state value per parameter for the momentum buffer:

Nesterov momentum evaluates the gradient at the expected momentum look-ahead point.

AdaGrad

AdaGrad gives every parameter its own effective learning rate. It accumulates the squared gradients:

rt=rt1+gt2r_t=r_{t-1}+g_t^2 θt+1=θtηgtrt+ϵ\theta_{t+1}=\theta_t-\eta\frac{g_t}{\sqrt{r_t}+\epsilon}

A parameter that repeatedly receives large gradients builds a large denominator and takes smaller steps. A parameter with rare or small gradients retains larger effective steps, which makes AdaGrad useful for sparse features. However, rtr_t only increases, so the effective learning rates continually decrease and can become too small during a long training run. AdaGrad stores one additional state value per parameter for the accumulated squared gradients.

RMSProp

RMSProp replaces AdaGrad's cumulative sum with an exponential moving average of squared gradients:

rt=ρrt1+(1ρ)gt2r_t=\rho r_{t-1}+(1-\rho)g_t^2 θt+1=θtηgtrt+ϵ\theta_{t+1}=\theta_t-\eta\frac{g_t}{\sqrt{r_t}+\epsilon}

Old squared gradients gradually decay instead of remaining in the denominator forever. Each parameter is still scaled according to the recent magnitude of its gradients, but its effective learning rate no longer has to shrink monotonically. RMSProp was presented in Geoffrey Hinton's neural-network lecture notes. It stores one additional state value per parameter for the moving average of squared gradients.

Adam

Adam combines momentum with RMSProp-style scaling. It tracks an exponential moving average of gradients, called the first moment, and an exponential moving average of squared gradients, called the second raw moment:

mt=β1mt1+(1β1)gtm_t=\beta_1m_{t-1}+(1-\beta_1)g_t vt=β2vt1+(1β2)gt2v_t=\beta_2v_{t-1}+(1-\beta_2)g_t^2

Both averages start at zero and are biased toward zero during the first steps. Adam corrects this initialization bias:

m^t=mt1β1t,v^t=vt1β2t\widehat m_t=\frac{m_t}{1-\beta_1^t},\qquad \widehat v_t=\frac{v_t}{1-\beta_2^t}

It then uses the first moment as a smoothed direction and the second moment to scale each coordinate:

θt+1=θtηm^tv^t+ϵ\theta_{t+1}=\theta_t-\eta\frac{\widehat m_t}{\sqrt{\widehat v_t}+\epsilon}

The original defaults are β1=0.9\beta_1=0.9, β2=0.999\beta_2=0.999, and ϵ=108\epsilon=10^{-8}. Adam stores two state values per parameter, twice as many as SGD with momentum.

AdamW

Weight decay directly shrinks the parameters. With decay coefficient λ\lambda, a decoupled AdamW update is:

θt+1=θtηm^tv^t+ϵAdam updateηλθtWeight decay\theta_{t+1}=\theta_t -\underbrace{\eta\frac{\widehat m_t}{\sqrt{\widehat v_t}+\epsilon}}_{\text{Adam update}} -\underbrace{\eta\lambda\theta_t}_{\text{Weight decay}}

In common implementations, the default decay coefficient is λ=0.01\lambda=0.01 although it should be tuned for the model and training setup. Weight decay discourages unnecessarily large weights by continuously pulling them toward zero. Gradients can still push useful weights away from zero, producing a balance between learning and decay. AdamW stores the same two state values per parameter as Adam. Decoupled weight decay does not require another state value.

Muon

Some good posts:

Muon stores one additional state value per optimized parameter element in its momentum buffer. The Newton-Schulz iterations use temporary working memory during each update but do not add another persistent state value.

Miscellaneous

Different parameter groups can use different optimizers. For example, the weights of linear layers could be updated with Adam while the remaining parameters use SGD.

Different optimizers can also be used at different stages of training. For example, training can begin with SGD, which requires less optimizer-state memory than Adam, to reduce GPU memory usage. It can later switch to Adam when adaptive per-parameter updates become more valuable.