top of page

What Is Stochastic Gradient Descent (SGD)?

  • 1 day ago
  • 28 min read
SGD path descending a 3D loss landscape.

Every time a neural network learns to recognize a face, translate a sentence, or predict a house price, something has to nudge millions of numbers, one small step at a time, toward values that make fewer mistakes — and for most of the history of modern machine learning, that nudging is done by stochastic gradient descent, an idea that started as a 1951 statistics paper and quietly became the engine room of the deep learning era.


TL;DR


  • Stochastic gradient descent (SGD) updates a model's parameters using the gradient estimated from one example or a small mini-batch, instead of the whole dataset at once.

  • SGD traces back to the Robbins–Monro stochastic approximation method from 1951, long before it became the default way to train neural networks [1].

  • Mini-batch SGD, not strict single-example SGD, is what most frameworks like PyTorch, TensorFlow, and scikit-learn actually run when you call "SGD" today [4][5][6].

  • The learning rate and batch size are the two hyperparameters that most affect training speed, stability, and final model quality.

  • Variants like momentum, Nesterov momentum, and Adam build on SGD's core idea to speed up convergence, but none of them guarantee the global minimum on non-convex problems [7][8].


What Is Stochastic Gradient Descent (SGD)?


Stochastic gradient descent (SGD) is an optimization algorithm that trains machine learning models by repeatedly updating their parameters in the direction that reduces prediction error, using the gradient calculated from a randomly selected training example or small batch rather than the entire dataset at once.





The Model Failure Fieldbook: Learn AI/ML Through 50 Things That Break
$39.00$19.00
See What’s Inside

Table of Contents



Plain-English Definition


Training a machine learning model is really a search problem. The model has a set of parameters — numbers such as weights and biases — and the goal is to find the values of those parameters that make the model's predictions as close as possible to the correct answers. This search is called optimization, and the object being minimized is usually called a loss function or objective function: a single number that gets smaller as the model gets better.


Stochastic gradient descent is the algorithm most commonly used to do this search. At each step, SGD looks at how the loss would change if each parameter moved slightly in one direction or the other — that information is the gradient — and then moves every parameter a small amount in the direction that reduces the loss. The word "stochastic" refers to the fact that this gradient is not computed from the entire training set every time. Instead, it is estimated from a randomly chosen single example or a small random subset of examples, called a mini-batch. That randomness introduces noise into each individual update, but it also means each update is dramatically cheaper to compute, which is what allows SGD to train models on datasets with millions or billions of examples.


SGD matters because nearly every widely used neural network, from image classifiers to large language models, and many classic linear models, are fitted using some form of stochastic gradient method. Understanding SGD is close to a prerequisite for understanding how modern AI systems are actually trained [2][3].


The Model Failure Fieldbook: Learn AI/ML Through 50 Things That Break
$39.00$19.00
See What’s Inside

Essential Foundations


Before going further, a few concepts need to be nailed down, because the rest of the article depends on them.


Model parameters and weights. A model's parameters (often called weights when referring to a neural network's connection strengths) are the internal numbers the model uses to turn inputs into predictions. Training means finding good values for these parameters.


Predictions. Given an input, such as an image or a row of tabular data, the model produces an output: a predicted class, a predicted number, or a probability distribution.


Loss functions and objective functions. A loss function scores how wrong a single prediction was compared to the true answer. Averaging (or summing) the loss over a set of examples gives the objective function that training tries to minimize. Common choices include mean squared error for regression and cross-entropy for classification.


Gradients and partial derivatives. For a function with many inputs (here, the parameters), the gradient is a vector containing the partial derivative of the loss with respect to each parameter. Each entry tells you, if you nudge that one parameter slightly while holding everything else fixed, whether the loss goes up or down, and by roughly how much.


The negative-gradient direction. The gradient points in the direction of steepest increase of the loss. Moving in the opposite direction — the negative gradient — is, locally, the direction that decreases the loss fastest. This is the entire mechanical idea behind gradient-based optimization.


Learning rates. The learning rate is a small positive number that controls how big a step is taken in the negative-gradient direction at each update. Framework defaults (such as 0.01 in several libraries) are implementation choices, not universally correct values.


Training examples and datasets. A training set is a collection of input–output pairs used to fit the model. A validation set and a test set are held out to check how well the model performs on data it did not train on.


Empirical risk minimization. In practice, you cannot compute the true expected loss over all possible data; you only have a finite sample. Empirical risk minimization is the strategy of minimizing the average loss over the training sample as a stand-in for minimizing the true, unknown risk.


The loss surface. If you imagine plotting the loss as a function of the model's parameters, you get a high-dimensional surface with hills, valleys, plateaus, and saddle points. Training is the process of walking across this surface toward a low point. For a simple two-parameter linear model, this surface can literally be drawn as a bowl-shaped or valley-shaped 3D plot; for a deep network with millions of parameters, it exists only mathematically, but the same intuition — walking downhill — still applies.


From Gradient Descent to SGD


Full-Batch Gradient Descent


Full-batch gradient descent computes the gradient of the loss using every example in the training set before making a single parameter update. If the loss for example $i$ is $L_i(\theta)$, where $\theta$ represents all model parameters, the full-batch objective is:


$$J(\theta) = \frac{1}{N}\sum_{i=1}^{N} L_i(\theta)$$


Here, $N$ is the number of training examples and $J(\theta)$ is the average loss. The update rule is:


$$\theta_{t+1} = \theta_t - \eta , \nabla J(\theta_t)$$


$\theta_t$ is the parameter vector at step $t$, $\eta$ (eta) is the learning rate, and $\nabla J(\theta_t)$ is the gradient of the full-batch loss. In plain English: compute the average error direction across the entire dataset, then take one careful step.


Single-Example Stochastic Gradient Descent


Strict single-example SGD instead picks one training example $i$ at random on each iteration and updates using only that example's gradient:


$$\theta_{t+1} = \theta_t - \eta , \nabla L_i(\theta_t)$$


This is dramatically cheaper per step — you touch one data point instead of the whole dataset — but each individual gradient $\nabla L_i(\theta_t)$ is a noisy estimate of the true gradient $\nabla J(\theta_t)$. Under standard assumptions (examples drawn independently and identically from the data distribution), this single-example gradient is an unbiased estimator of the full gradient, meaning its average over many random draws equals the true gradient, even though any one draw can be far off.


Mini-Batch Stochastic Gradient Descent


Mini-batch SGD samples a small batch $B$ of $m$ examples (commonly somewhere between 8 and a few thousand, depending on the task and hardware) and averages their gradients:


$$\theta_{t+1} = \theta_t - \eta , \frac{1}{m}\sum_{i \in B} \nabla L_i(\theta_t)$$


In modern deep-learning practice, when people say "we trained with SGD," they almost always mean mini-batch SGD, not strict single-example SGD. The terminology is used loosely, but the mechanics differ: batch size changes both the variance of the gradient estimate and the computational cost per update, and the two informal usages of "SGD" are not identical algorithms [2][4].


Comparison Table: Batch, Single-Example, and Mini-Batch Approaches


Property

Full-Batch GD

Single-Example SGD

Mini-Batch SGD

Data used per update

Entire dataset

One example

Small subset (e.g., 32–1,024)

Computational cost per update

High

Very low

Low to moderate

Update frequency per epoch

1

N (dataset size)

N / batch size

Gradient variance

None (exact)

High

Moderate, decreases as batch grows

Memory requirements

High (whole dataset in memory)

Very low

Low to moderate

Parallelism / hardware use

Good for large batches on accelerators

Poor (hard to vectorize)

Good; matches GPU/TPU throughput

Stability of the loss curve

Smooth

Noisy, oscillating

Smoother than single-example, noisier than full-batch

Typical use cases

Small datasets, convex problems, research analysis

Streaming/online learning, extremely constrained memory

Standard deep learning and large-scale linear model training


The Model Failure Fieldbook: Learn AI/ML Through 50 Things That Break
$39.00$19.00
See What’s Inside

How SGD Works Step by Step


A full SGD training run follows this cycle:


  1. Initialize parameters, typically with small random values chosen according to an initialization scheme suited to the network's architecture.

  2. Shuffle the training data so that each pass over the data is not biased by the original ordering.

  3. Select an example or mini-batch from the shuffled data.

  4. Perform the forward pass: feed the inputs through the model to generate predictions.

  5. Calculate the loss by comparing predictions to the true targets.

  6. Compute gradients of the loss with respect to every parameter, usually via backpropagation in neural networks.

  7. Update parameters by moving them a small step in the negative-gradient direction, scaled by the learning rate.

  8. Repeat steps 3–7 across all mini-batches; one full pass through the training data is called an epoch, and training typically runs for many epochs.

  9. Evaluate on a validation set periodically (for example, at the end of each epoch) to track how well the model generalizes to unseen data.

  10. Stop according to a chosen criterion: a fixed number of epochs, a validation metric that stops improving (early stopping), or a computational budget.


initialize parameters theta
for epoch in 1..max_epochs:
    shuffle(training_data)
    for batch in split_into_batches(training_data, batch_size):
        predictions = forward_pass(batch.inputs, theta)
        loss = compute_loss(predictions, batch.targets)
        gradients = backward_pass(loss, theta)
        theta = theta - learning_rate * gradients
    val_score = evaluate(theta, validation_data)
    if stopping_criterion_met(val_score):
        break
return theta

Each pass through the inner loop is one iteration and one optimizer step; a full pass through the outer loop is one epoch. These terms are frequently confused, but they describe different units of training progress.


Worked Numerical Example


To make this concrete, consider single-parameter linear regression through the origin: predict $\hat{y} = w x$, where $w$ is the one parameter being learned (no intercept, to keep the arithmetic simple).


Data (3 points):


$x$

$y$

1

2

2

3

3

6


Model: $\hat{y}_i = w x_i$


Loss (squared error) for one example: $L_i(w) = \tfrac{1}{2}(w x_i - y_i)^2$


Gradient of the loss with respect to $w$: $\dfrac{dL_i}{dw} = (w x_i - y_i), x_i$


Start with $w_0 = 1$ and a learning rate $\eta = 0.1$.


Update 1 — using example $(x=1, y=2)$:


  • Prediction: $\hat{y} = 1 \times 1 = 1$

  • Gradient: $(1 - 2) \times 1 = -1$

  • Update: $w_1 = 1 - 0.1 \times (-1) = 1 + 0.1 = 1.1$


Update 2 — using example $(x=2, y=3)$:


  • Prediction: $\hat{y} = 1.1 \times 2 = 2.2$

  • Gradient: $(2.2 - 3) \times 2 = (-0.8) \times 2 = -1.6$

  • Update: $w_2 = 1.1 - 0.1 \times (-1.6) = 1.1 + 0.16 = 1.26$


Notice the two updates moved $w$ by different amounts (+0.1, then +0.16) because each was computed from a different training example with a different gradient. This is the practical meaning of "stochastic": the direction and size of each step depend on which data point happened to be sampled. Before training, the prediction for $x=1$ was off by 1 unit; after two updates, $w=1.26$ predicts $\hat{y}=1.26$ for $x=1$ (true value 2) and $\hat{y}=2.52$ for $x=2$ (true value 3) — closer on the second point, illustrating that individual updates trade off performance across different examples rather than improving every point uniformly on every step. Running this same process, in shuffled order, across many epochs is what full-batch or mini-batch training generalizes into for models with many parameters.


The Model Failure Fieldbook: Learn AI/ML Through 50 Things That Break
$39.00$19.00
See What’s Inside

Why SGD Is Useful


SGD's biggest practical advantage is scalability. Because each update depends only on one example or a small batch, SGD can train on datasets that would never fit in memory all at once, and it can start improving the model after seeing just a fraction of the data rather than waiting to process everything first [2]. This makes it a natural fit for streaming and online-learning settings, where data arrives continuously and the model needs to update incrementally rather than retrain from scratch.


Mini-batch SGD also maps efficiently onto modern hardware: GPUs and TPUs are built to process many examples in parallel, so a well-chosen batch size can keep the hardware busy while still allowing frequent parameter updates. On large and sparse datasets, such as text or click-through data with millions of rare features, SGD's ability to update from a handful of examples at a time, rather than waiting for a full pass, is often the difference between a training run that finishes in hours and one that never finishes.


The noise introduced by sampling is not purely a downside. In non-convex problems, some researchers have argued that gradient noise may help models avoid or escape certain shallow local minima and can interact with the loss landscape in ways that affect which regions of parameter space training tends to settle in — but this is an active area of research, not a settled guarantee, and noise does not reliably escape all local minima or saddle points [2][3].


Balanced against these benefits are real costs: SGD requires more careful tuning of the learning rate than full-batch methods, produces noisier training curves, and its convergence behavior is harder to reason about precisely than deterministic full-batch descent.


Limitations and Failure Modes


Issue

Practical Remedy

Noisy or oscillating training/validation curves

Reduce learning rate, increase batch size, or apply a moving average to the loss for monitoring

High sensitivity to the learning rate

Run a small learning-rate sweep or use a warmup-plus-decay schedule

Slow convergence near the optimum

Apply a decaying learning rate or switch to momentum-based methods

Poor conditioning of the loss surface

Normalize/standardize input features; consider adaptive optimizers

Plateaus and saddle regions in non-convex loss surfaces

Use momentum to maintain velocity through flat regions

Exploding gradients

Apply gradient clipping; check for excessively high learning rates

Vanishing gradients

Use appropriate activation functions and initialization; consider architectural changes (e.g., residual connections)

Unscaled features

Standardize or normalize inputs before training

Bad initialization

Use initialization schemes suited to the architecture (e.g., Xavier/He initialization)

Data-order effects

Shuffle data every epoch

Non-representative mini-batches

Use stratified sampling for imbalanced data; increase batch size

Use class weighting, resampling, or stratified batches

Batch-size extremes (too small or too large)

Tune batch size alongside learning rate; monitor gradient variance

Overfitting and underfitting

Apply regularization, early stopping, or adjust model capacity

Training instability

Lower the learning rate, add gradient clipping, or check for data leakage

Premature stopping

Monitor validation performance rather than training loss alone before halting


The Model Failure Fieldbook: Learn AI/ML Through 50 Things That Break
$39.00$19.00
See What’s Inside

Learning Rate and Schedules


Of all SGD's hyperparameters, the learning rate typically has the largest effect on training outcomes. A learning rate that is too high can cause the loss to diverge or oscillate wildly; one that is too low can make training impractically slow or cause it to stall on a plateau long before reaching a good solution [2][3].


Constant learning rate. The simplest choice: $\eta$ stays fixed for the entire run. Easy to reason about, but often suboptimal, since a rate that is good early in training (when large steps are useful) may be too large later (when fine adjustments are needed).


Step decay. The learning rate is multiplied by a fixed factor (e.g., 0.1) every fixed number of epochs.


Exponential decay. The learning rate decreases continuously according to $\eta_t = \eta_0 e^{-kt}$, for some decay constant $k$.


Inverse-time decay. The learning rate follows $\eta_t = \eta_0 / (1 + kt)$, echoing the diminishing-step-size condition from the original stochastic approximation theory, where step sizes shrink over time to guarantee convergence under certain assumptions [1].


Cosine decay. The learning rate follows a cosine curve down to near zero over training, popular in modern deep learning because it tends to produce smooth, well-behaved final convergence.


Warmup. Training starts with a small learning rate that ramps up over the first few epochs before switching to the main schedule. This has been shown to stabilize training in large-batch settings, where a full-size learning rate applied immediately can cause early instability [13].


One-cycle-style schedules. The learning rate rises during an initial phase and then falls, often paired with an inverse pattern for momentum, aiming to combine fast early progress with careful late-stage convergence.


Reduce-on-plateau. The learning rate is cut only when a monitored validation metric stops improving for a set number of epochs, adapting the schedule to the specific training run rather than following a fixed clock.


Theoretical diminishing-step intuition. Classical stochastic approximation theory shows that, under conditions such as $\sum \eta_t = \infty$ and $\sum \eta_t^2 < \infty$, iterative stochastic updates can converge to a solution in probability, which is part of the theoretical motivation for decaying learning rates over time [1][9].


No single schedule is universally best; the right choice depends on the model, dataset size, and available compute budget, and batch size and learning rate interact — larger batches often tolerate or require different learning rates than smaller ones, a relationship discussed further below [13].


Batch Size


Batch size controls how many examples contribute to each gradient estimate, and it interacts with nearly every other part of training.


At one extreme, single-example updates produce the highest gradient variance and the noisiest steps. Large mini-batches average over more examples, producing a smoother, lower-variance gradient estimate, but each update costs more compute and touches the data less frequently per epoch. Full-batch gradient descent has zero sampling variance but is often computationally impractical for large datasets and can behave differently in terms of generalization than smaller batches.


Larger batches generally improve throughput on parallel hardware (more examples processed per second) up to a point, but this comes with increased memory demand and diminishing marginal benefit once hardware is saturated. Claims that larger batches always train faster, or that smaller batches always generalize better, are both oversimplifications; empirical results depend heavily on the model, dataset, and how the learning rate is adjusted alongside batch size [2][13].


One influential empirical heuristic is the linear scaling rule: when batch size is multiplied by some factor $k$, multiply the learning rate by approximately the same factor $k$, combined with a warmup period, as demonstrated in large-scale image classification training [13]. This is a practical heuristic validated in specific settings, not a universal law that applies unconditionally to every architecture and dataset.


Gradient accumulation lets you simulate a larger batch size than fits in memory by summing gradients across several smaller "micro-batches" before performing a single parameter update — useful when a model is too large to fit a full batch on the available hardware.


Distributed training splits a large batch across multiple devices, computing partial gradients on each device and then aggregating them (commonly via an all-reduce operation) before the shared update is applied — an approach directly connected to the large-minibatch scaling research discussed above [13].


The Model Failure Fieldbook: Learn AI/ML Through 50 Things That Break
$39.00$19.00
See What’s Inside

Momentum and Variants


Vanilla SGD, as already described, uses only the current gradient: $\theta_{t+1} = \theta_t - \eta \nabla L(\theta_t)$.


SGD with momentum adds a velocity term $v_t$ that accumulates a running average of past gradients:


$$v_{t+1} = \mu v_t + \nabla L(\theta_t), \qquad \theta_{t+1} = \theta_t - \eta , v_{t+1}$$


Here $\mu$ (mu) is the momentum coefficient (commonly around 0.9). Momentum helps carry the optimizer through flat regions and small bumps in the loss surface, in the same way a heavy ball rolling downhill keeps moving through small dips because of its accumulated velocity — though unlike a physical ball, momentum in SGD has no true "mass" or energy conservation, and this analogy stops being literal at that point.


Nesterov momentum evaluates the gradient at a position that accounts for the momentum step already taken, effectively looking ahead before computing the correction, which can improve convergence behavior over standard momentum in some settings [7].


Averaged SGD (Polyak–Ruppert averaging) keeps a running average of the parameter iterates themselves, $\bar\theta_T = \frac{1}{T}\sum_{t=1}^{T}\theta_t$, rather than only using the final iterate. Under certain statistical assumptions, this averaged estimate can achieve favorable asymptotic convergence properties compared with using the last iterate alone [9].


Weight decay with SGD adds a term that shrinks parameters toward zero at each step, commonly implemented as $\theta_{t+1} = \theta_t - \eta(\nabla L(\theta_t) + \lambda \theta_t)$, where $\lambda$ is the weight decay coefficient. For plain SGD, this form of weight decay is mathematically equivalent to adding an L2 penalty to the loss; that equivalence does not hold in the same simple form once adaptive optimizers like Adam are involved, which motivated decoupled weight decay approaches discussed later [12].


Variance-reduced methods such as SAG, SAGA, and SVRG modify the stochastic gradient estimate itself — for example, by periodically recomputing a full-batch gradient and correcting the stochastic estimate against it — to reduce gradient variance and, under certain conditions, achieve faster convergence rates than plain SGD on specific problem classes, though they are less commonly used in large-scale deep learning than in classical convex optimization.


Comparison Table: SGD Variants


Variant

What It Changes

Main Benefit

Main Trade-off

Vanilla SGD

Nothing extra; uses raw gradient

Simple, low memory

Can be slow through flat or oscillating regions

SGD with momentum

Adds accumulated velocity term

Smoother, often faster progress

One extra hyperparameter ($\mu$) and one extra state buffer

Nesterov momentum

Looks ahead before computing gradient

Can improve convergence over standard momentum

Slightly more complex update; sensitive to tuning

Averaged SGD (Polyak–Ruppert)

Averages parameter iterates over time

Favorable theoretical convergence in some regimes

Averaging window and start point need tuning

SGD with weight decay

Shrinks parameters each step

Helps control overfitting

Must be tuned jointly with learning rate

Variance-reduced (SAG/SAGA/SVRG)

Corrects the stochastic gradient estimate

Reduced gradient variance on suitable problems

Extra memory/computation; less common in large-scale deep learning


The Model Failure Fieldbook: Learn AI/ML Through 50 Things That Break
$39.00$19.00
See What’s Inside

SGD vs Other Optimizers


Adaptive optimizers such as AdaGrad, RMSProp, and Adam maintain per-parameter statistics of past gradients and use them to scale each parameter's effective learning rate individually, rather than applying one global rate to every parameter as plain SGD does [8][10][11].


AdaGrad accumulates the sum of squared past gradients for each parameter and divides the learning rate by the square root of that sum, which gives infrequently updated parameters (common with sparse features) relatively larger effective steps [10].


RMSProp modifies this idea by using a decaying (exponentially weighted) moving average of squared gradients instead of an ever-growing sum, addressing AdaGrad's tendency for the effective learning rate to shrink too aggressively over long training runs [11].


Adam combines a momentum-like moving average of the gradient itself with an RMSProp-like moving average of squared gradients, then uses both to compute an adaptive, bias-corrected update for each parameter [8].


AdamW decouples weight decay from the adaptive gradient update, addressing the fact that combining L2 regularization with Adam's per-parameter scaling does not behave the same way it does with plain SGD [12].


Comparison Table: Optimizer Landscape


Optimizer

Per-Parameter Adaptive Rates

Extra Optimizer State

Memory Overhead

Tuning Sensitivity

Sparse-Gradient Behavior

Common Use Cases

Potential Strengths

Potential Weaknesses

Full-batch GD

No

None

Low

Moderate

Poor for very sparse data

Small/medium convex problems, research analysis

Exact gradient, simple theory

Impractical at large scale

Mini-batch SGD

No

None (momentum optional)

Low

High (learning rate critical)

Moderate

Linear models, large-scale deep learning

Simple, well understood, often strong final generalization

Requires careful tuning, slower early progress on some problems

SGD + momentum

No

One velocity buffer

Low–moderate

Moderate–high

Moderate

Computer vision, many production deep-learning pipelines

Faster progress through flat regions

Extra hyperparameter, still learning-rate sensitive

AdaGrad

Yes

Per-parameter accumulator

Moderate

Lower for sparse problems

Strong (favors rare features)

Sparse, high-dimensional problems (e.g., text)

Good early behavior on sparse data

Learning rate can shrink too much over long runs

RMSProp

Yes

Per-parameter moving average

Moderate

Lower than AdaGrad

Strong

RNNs and other non-stationary objectives

Handles non-stationary objectives well

Extra hyperparameters; less theoretical grounding than Adam

Adam

Yes

Two per-parameter moving averages

Moderate–high

Generally lower

Strong

Wide range of deep learning tasks, fast prototyping

Often fast, robust default across many tasks

Can generalize worse than well-tuned SGD in some settings; not universally superior

AdamW

Yes

Two per-parameter moving averages

Moderate–high

Generally lower

Strong

Transformer training, modern large models

Cleaner weight-decay behavior than Adam

Same core sensitivities as Adam otherwise


No optimizer in this table is a universal winner; the right choice depends on data sparsity, model architecture, available compute, and how much tuning time is available.


The Model Failure Fieldbook: Learn AI/ML Through 50 Things That Break
$39.00$19.00
See What’s Inside

Practical Implementation


The following examples show SGD in four contexts: a from-scratch NumPy version, PyTorch's built-in optimizer, TensorFlow/Keras's built-in optimizer, and scikit-learn's linear estimator. The NumPy and PyTorch/Keras examples illustrate optimizer-level SGD as used to train models such as neural networks; the scikit-learn example is a distinct linear estimator that is fit via SGD rather than a general-purpose neural-network optimizer.


From-Scratch NumPy Implementation


import numpy as np

rng = np.random.default_rng(seed=42)
X = rng.normal(size=(200, 1))
true_w, true_b = 3.0, -1.0
y = true_w * X[:, 0] + true_b + rng.normal(scale=0.1, size=200)

w, b = 0.0, 0.0
lr = 0.05
epochs = 20
batch_size = 16

for epoch in range(epochs):
    perm = rng.permutation(len(X))
    X_shuffled, y_shuffled = X[perm], y[perm]
    for start in range(0, len(X), batch_size):
        xb = X_shuffled[start:start + batch_size, 0]
        yb = y_shuffled[start:start + batch_size]
        preds = w * xb + b
        error = preds - yb
        grad_w = np.mean(error * xb)
        grad_b = np.mean(error)
        w -= lr * grad_w
        b -= lr * grad_b

print(f"Learned w={w:.3f}, b={b:.3f}")

This script generates a noisy linear dataset with a known true slope and intercept, then runs mini-batch SGD by hand: each inner loop iteration samples one mini-batch, computes the mean-squared-error gradient with respect to w and b, and updates both parameters. The random seed makes results reproducible.


PyTorch: torch.optim.SGD


import torch
import torch.nn as nn

torch.manual_seed(42)
model = nn.Linear(1, 1)
optimizer = torch.optim.SGD(model.parameters(), lr=0.05, momentum=0.9)
loss_fn = nn.MSELoss()

X = torch.randn(200, 1)
y = 3.0 * X + (-1.0) + 0.1 * torch.randn(200, 1)

for epoch in range(20):
    optimizer.zero_grad()
    predictions = model(X)
    loss = loss_fn(predictions, y)
    loss.backward()
    optimizer.step()

print(f"Final loss: {loss.item():.4f}")

torch.optim.SGD is constructed with the model's parameters, a learning rate, and an optional momentum term; optimizer.zero_grad() clears old gradients before each step, loss.backward() computes new gradients via automatic differentiation, and optimizer.step() applies the update rule described earlier [4]. PyTorch's momentum implementation differs slightly in scaling convention from the original Sutskever et al. formulation, so mixing hyperparameters copied from other frameworks without checking the current documentation can produce different behavior [4][7].


TensorFlow/Keras: keras.optimizers.SGD


import tensorflow as tf

tf.random.set_seed(42)
model = tf.keras.Sequential([tf.keras.layers.Dense(1, input_shape=(1,))])
optimizer = tf.keras.optimizers.SGD(learning_rate=0.05, momentum=0.9, nesterov=True)
model.compile(optimizer=optimizer, loss="mse")

X = tf.random.normal((200, 1))
y = 3.0 * X + (-1.0) + 0.1 * tf.random.normal((200, 1))

model.fit(X, y, epochs=20, batch_size=16, verbose=0)
print("Training complete")

Here, keras.optimizers.SGD accepts learning_rate, momentum, and a nesterov flag directly; model.compile wires the optimizer to the mean-squared-error loss, and model.fit runs the full mini-batch training loop internally, handling shuffling and batching for you [5].


scikit-learn: SGDRegressor


import numpy as np
from sklearn.linear_model import SGDRegressor
from sklearn.preprocessing import StandardScaler

rng = np.random.default_rng(42)
X = rng.normal(size=(200, 1))
y = 3.0 * X[:, 0] - 1.0 + rng.normal(scale=0.1, size=200)

X_scaled = StandardScaler().fit_transform(X)
model = SGDRegressor(max_iter=1000, learning_rate="invscaling", eta0=0.05, random_state=42)
model.fit(X_scaled, y)

print(f"Coefficient: {model.coef_[0]:.3f}, Intercept: {model.intercept_[0]:.3f}")

SGDRegressor is a linear model fit via stochastic gradient descent rather than a generic neural-network optimizer; it is distinct from torch.optim.SGD or keras.optimizers.SGD, which optimize arbitrary differentiable models. StandardScaler is applied first because scikit-learn's SGD-based estimators are noted as sensitive to feature scaling [6].


The Model Failure Fieldbook: Learn AI/ML Through 50 Things That Break
$39.00$19.00
See What’s Inside

Practical Tuning Workflow


  1. Normalize or standardize input features so that no single feature dominates the gradient due to scale differences.

  2. Build a simple baseline (e.g., a small model with default hyperparameters) before optimizing further.

  3. Select an initial learning rate using a short range test or established defaults for the framework and task.

  4. Select a batch size based on available memory and hardware parallelism, then revisit the learning rate if the batch size changes substantially.

  5. Choose a momentum value (commonly in the 0.8–0.99 range for many neural-network tasks) if using SGD with momentum.

  6. Apply a learning-rate schedule appropriate to the training budget (e.g., step decay, cosine decay, or warmup for large batches).

  7. Add weight decay or other regularization if overfitting is observed on the validation set.

  8. Apply gradient clipping if gradients are unstable or exploding, particularly in recurrent architectures.

  9. Monitor training and validation curves together, not training loss alone, to detect overfitting or instability early.

  10. Use early stopping based on validation performance rather than a fixed epoch count when practical.

  11. Fix random seeds for reproducibility during development and debugging.

  12. Run a small hyperparameter search (grid, random, or Bayesian) over the most influential settings — usually learning rate first, then batch size and momentum.

  13. Log and checkpoint training runs so experiments can be compared and recovered.


Diagnostic Table


Symptom

Likely Cause

What to Inspect

Possible Fix

Loss explodes to NaN

Learning rate too high, exploding gradients

Gradient magnitudes, learning rate

Lower learning rate; add gradient clipping

Loss barely moves

Learning rate too low, poor initialization

Learning rate, initialization scheme

Raise learning rate; check initialization

Training loss low, validation loss high

Overfitting

Validation vs. training curves

Add regularization, more data, or early stopping

Very noisy training curve

Batch size too small, learning rate too high

Batch size, gradient variance

Increase batch size or reduce learning rate

Progress stalls mid-training

Plateau or poor conditioning

Learning-rate schedule, feature scaling

Add momentum or a decay schedule; standardize features

Good results only with specific seed

Fragile initialization or unstable optimization

Multiple seeds, variance across runs

Average results over several seeds; stabilize hyperparameters


The Model Failure Fieldbook: Learn AI/ML Through 50 Things That Break
$39.00$19.00
See What’s Inside

When to Use SGD


Plain SGD or SGD with momentum can be a strong choice for large linear models on sparse, high-dimensional data such as text classification, where scikit-learn's SGDClassifier and SGDRegressor are specifically designed for this regime [6]. It is also well suited to online-learning settings where data arrives continuously and the model needs incremental updates rather than full retraining.


In computer vision, SGD with momentum has a long track record of training convolutional and residual networks to strong final accuracy, and some practitioners favor it when predictable optimizer behavior and strong final generalization matter more than fastest possible early-epoch progress [2][13]. For general neural network training where rapid prototyping and robustness across architectures matter more, an adaptive optimizer such as Adam or AdamW is often more convenient, particularly for transformer-style models, though neither choice is universally superior across all tasks.


Common Misconceptions


"SGD always uses exactly one sample." In modern usage, "SGD" usually refers to mini-batch SGD, which uses small groups of examples per update, not strictly one [2][4].


"Stochastic means the optimizer moves randomly." The optimizer still moves in a gradient-informed direction; only the specific data used to estimate that gradient at each step is randomly sampled.


"SGD always finds the global minimum." On non-convex loss surfaces, such as those of deep neural networks, SGD is only guaranteed to converge to a stationary point under certain conditions, not the global minimum [2][3].


"More noise is always better." Gradient noise can sometimes help avoid certain shallow local minima, but excessive noise (from a learning rate that is too high or a batch size that is too small) commonly destabilizes training rather than helping it.


"A larger batch is always faster." Larger batches increase per-step compute and memory use; total wall-clock speedup depends on hardware utilization and whether the learning rate is adjusted accordingly [13].


"A smaller batch always generalizes better." Empirical results on this question vary by architecture, dataset, and how carefully the learning rate is tuned; it is an active research question, not a fixed rule [2].


"Momentum and learning rate do the same thing." The learning rate scales the raw gradient step; momentum accumulates a running average of past gradients. They interact but control different aspects of the update.


"Adam always beats SGD." Adam often converges faster in early training, but well-tuned SGD with momentum has, in various studies and practical settings, matched or exceeded Adam's final generalization performance on some tasks; neither is a universal winner [8].


"One epoch means one optimizer update." One epoch is one full pass through the training data, which typically corresponds to many mini-batch updates, not just one.


"A decreasing training loss proves the model generalizes." Training loss reflects fit to the training data only; generalization must be checked on a separate validation set or test set.


Advanced Perspective


A single stochastic gradient is best thought of as a random estimator of the true gradient: it has some expected value (ideally the true gradient, under standard sampling assumptions) and some variance around that expected value. The behavior of SGD over many steps can be analyzed in terms of expected descent — how much the loss is expected to decrease, on average, given the current gradient estimate's bias and variance [1][2].


Convergence guarantees differ sharply between convex and non-convex objectives. For convex or strongly convex problems, classical stochastic approximation theory provides conditions under which iterates converge in probability to the optimum, given appropriately shrinking step sizes [1][9]. For the non-convex objectives typical of deep neural networks, the standard results are weaker: under smoothness assumptions, SGD can be shown to converge to a stationary point — a point where the gradient is near zero, which could be a local minimum, saddle point, or other flat region — rather than provably reaching the global minimum [2][3].


It is also important to separate optimization from generalization. Minimizing training loss is an optimization problem; achieving good performance on new, unseen data is a generalization problem. A model can drive training loss very low while still generalizing poorly, which is why validation and test sets remain essential even when the training loss curve looks excellent [3].


Finally, modern distributed and large-batch training changes what a "batch" practically means: a single logical batch may be split across many accelerators, gradients aggregated across devices, and the effective batch size scaled up by orders of magnitude compared to single-machine training — all while relying on the same core mini-batch SGD update rule underneath, adjusted with techniques like the linear scaling rule and warmup discussed earlier [13].


The Model Failure Fieldbook: Learn AI/ML Through 50 Things That Break
$39.00$19.00
See What’s Inside

FAQ


What is stochastic gradient descent in simple terms?


Stochastic gradient descent is a method for training machine learning models by repeatedly nudging the model's parameters in the direction that reduces prediction error, using the gradient computed from a small, randomly chosen sample of the training data rather than the entire dataset at once.


Is SGD the same as gradient descent?


No. Gradient descent is the general family of algorithms that move parameters opposite to the gradient; full-batch gradient descent uses the entire dataset per update, while SGD uses a randomly sampled example or mini-batch, making SGD one specific, more scalable member of that family.


Does SGD always use one training example per update?


In its strict historical form, yes, but modern deep-learning frameworks and most practitioners use "SGD" to mean mini-batch SGD, which updates using a small batch of examples (commonly 32 to a few thousand) rather than a single example [2][4].


What is the difference between an epoch, a batch, and an iteration?


An epoch is one full pass through the entire training dataset. A batch (or mini-batch) is a subset of the data used for a single parameter update. An iteration (or optimizer step) is one such update; the number of iterations per epoch equals the dataset size divided by the batch size.


How do I choose a learning rate for SGD?


There is no single universally correct value; common practice is to try a range of learning rates on a small experiment or use a short learning-rate range test, then refine using a schedule such as step decay or cosine decay based on how training behaves.


What is the best batch size for SGD?


There is no single best batch size; it depends on available memory, hardware parallelism, and how the learning rate is adjusted alongside it. Smaller batches give noisier but more frequent updates; larger batches give smoother but less frequent updates and require more memory per step.


Why does my SGD training loss look noisy or jump around?


This is often expected behavior, since each update is based on a randomly sampled batch rather than the whole dataset. If the noise is extreme, it can indicate a learning rate that is too high or a batch size that is too small relative to the task.


What is momentum in SGD, and why use it?


Momentum accumulates a running average of past gradients so that the optimizer keeps moving through flat regions and small bumps in the loss surface, generally speeding up convergence compared to vanilla SGD, though it adds one extra hyperparameter to tune [7].


Is Adam always better than SGD?


No. Adam often converges faster in early training and requires less tuning, but well-tuned SGD with momentum has matched or outperformed Adam's final generalization on various tasks in different studies; the better choice depends on the specific model, dataset, and available tuning time [8].


Can SGD get stuck in a local minimum?


On non-convex problems such as deep neural network training, SGD can converge to a stationary point that is a local minimum, saddle point, or flat region rather than the global minimum; gradient noise may sometimes help it move past shallow traps, but this is not guaranteed [2][3].


What causes exploding or vanishing gradients in SGD training, and how do I fix them?


Exploding gradients often stem from a learning rate that is too high, poor initialization, or unstable architectures, and can be addressed with gradient clipping and lower learning rates; vanishing gradients often stem from deep architectures with poorly chosen activation functions or initializations, addressed through better initialization schemes or architectural changes such as residual connections.


Do I need to scale or normalize my features before using SGD?


Yes, in most cases. Unscaled features can distort the loss surface's conditioning, making training slower and less stable; both neural-network optimizers and scikit-learn's SGD-based estimators are documented as sensitive to feature scaling [6].


What is the difference between SGD in PyTorch/TensorFlow and SGDRegressor in scikit-learn?


torch.optim.SGD and keras.optimizers.SGD are general-purpose optimizers that can train any differentiable model, including deep neural networks. SGDRegressor and SGDClassifier in scikit-learn are specific linear model estimators fitted via stochastic gradient descent; they are not general-purpose optimizers for arbitrary architectures [4][5][6].


The Model Failure Fieldbook: Learn AI/ML Through 50 Things That Break
$39.00$19.00
See What’s Inside

Key Takeaways


  • SGD estimates the gradient from a single example or small mini-batch rather than the full dataset, trading exact accuracy for dramatically lower per-step cost.

  • The term traces back to Robbins and Monro's 1951 stochastic approximation method, long before its role in modern deep learning [1].

  • In practice, "SGD" in frameworks like PyTorch, TensorFlow, and scikit-learn almost always means mini-batch SGD, not strict single-example updates [4][5][6].

  • The learning rate is usually the most influential hyperparameter, and no single schedule or value works best for every task.

  • Batch size and learning rate interact; changing one often means revisiting the other, especially at large scale [13].

  • Momentum, Nesterov momentum, and averaged SGD are established ways to improve on vanilla SGD without switching to a fully adaptive optimizer.

  • Adaptive optimizers like Adam and AdamW are not universally better than SGD; the right choice depends on the task, architecture, and available tuning time [8][12].

  • SGD is not guaranteed to find the global minimum on non-convex problems, and training loss improvements do not by themselves prove good generalization.


Actionable Next Steps


  1. Pick one small dataset and implement the from-scratch NumPy example above to build direct intuition for how gradients and updates interact.

  2. Run the same training task with torch.optim.SGD or keras.optimizers.SGD at three different learning rates and compare the loss curves.

  3. Repeat the same experiment at two different batch sizes, keeping everything else fixed, and note how the training curve's smoothness changes.

  4. Add momentum (e.g., 0.9) to your SGD optimizer and compare the number of epochs needed to reach a similar loss value.

  5. If working with sparse, high-dimensional data such as text, try scikit-learn's SGDClassifier or SGDRegressor after standardizing your features.

  6. Apply one learning-rate schedule (step decay or cosine decay) to your best-performing configuration and check whether final validation performance improves.

  7. Log your experiments (learning rate, batch size, momentum, final validation score) so you can compare configurations systematically rather than by memory.


The Model Failure Fieldbook: Learn AI/ML Through 50 Things That Break
$39.00$19.00
See What’s Inside

Glossary


  • Batch: A group of training examples processed together before a parameter update.

  • Batch gradient descent: Optimization using the gradient computed from the entire training dataset per update.

  • Batch size: The number of training examples used in one mini-batch.

  • Convergence: The point at which further training produces little or no further improvement in the loss.

  • Empirical risk minimization: The practice of minimizing average loss over a finite training sample as a proxy for minimizing true expected loss.

  • Epoch: One complete pass through the entire training dataset.

  • Generalization: How well a trained model performs on new, unseen data.

  • Gradient: A vector of partial derivatives showing how the loss changes with respect to each parameter.

  • Gradient clipping: Capping the magnitude of gradients to prevent unstable, oversized parameter updates.

  • Iteration: One single parameter update, typically corresponding to one mini-batch.

  • Learning rate: A scalar controlling the size of each parameter update step.

  • Loss function: A function measuring how far a prediction is from the true target value.

  • Mini-batch: A small, randomly sampled subset of the training data used for one update in mini-batch SGD.

  • Momentum: A technique that accumulates a running average of past gradients to smooth and speed up optimization.

  • Nesterov momentum: A momentum variant that computes the gradient at a look-ahead position based on the current velocity.

  • Objective function: The function being minimized or maximized during training, often the average loss over the training data.

  • Optimizer: The algorithm responsible for updating model parameters based on gradients.

  • Overfitting: When a model fits training data very well but performs poorly on new data.

  • Parameter: A learnable numeric value inside a model, such as a weight or bias.

  • Regularization: Techniques that discourage overly complex models to improve generalization.

  • SGD (stochastic gradient descent): An optimization algorithm that updates parameters using gradients estimated from a random example or mini-batch rather than the full dataset.

  • Stationary point: A point where the gradient is zero or near-zero, which may be a minimum, maximum, or saddle point.

  • Stochastic gradient: An estimate of the true gradient computed from a random sample of the data.

  • Training set: The portion of data used to fit a model's parameters.

  • Validation set: Data held out from training, used to tune hyperparameters and monitor generalization.

  • Vanishing/exploding gradients: Conditions where gradients become extremely small or extremely large during training, disrupting learning.

  • Weight decay: A regularization technique that shrinks parameter values toward zero at each update.


The Model Failure Fieldbook: Learn AI/ML Through 50 Things That Break
$39.00$19.00
See What’s Inside

Sources & References


  1. Robbins, H., & Monro, S. (1951). A Stochastic Approximation Method. Annals of Mathematical Statistics, 22(3), 400–407. https://doi.org/10.1214/aoms/1177729586

  2. Bottou, L., Curtis, F. E., & Nocedal, J. (2018). Optimization Methods for Large-Scale Machine Learning. SIAM Review, 60(2), 223–311. https://doi.org/10.1137/16M1080173

  3. Goodfellow, I., Bengio, Y., & Courville, A. (2016). Deep Learning. MIT Press. https://www.deeplearningbook.org/ (Chapter 8: Optimization for Training Deep Models)

  4. PyTorch. torch.optim.SGD documentation. https://docs.pytorch.org/docs/stable/generated/torch.optim.SGD.html (accessed July 24, 2026)

  5. Keras. keras.optimizers.SGD documentation. https://keras.io/api/optimizers/sgd/ (accessed July 24, 2026)

  6. scikit-learn. 1.5. Stochastic Gradient Descent. https://scikit-learn.org/stable/modules/sgd.html (accessed July 24, 2026)

  7. Sutskever, I., Martens, J., Dahl, G., & Hinton, G. (2013). On the Importance of Initialization and Momentum in Deep Learning. Proceedings of the 30th International Conference on Machine Learning, PMLR 28, 1139–1147. http://proceedings.mlr.press/v28/sutskever13.html

  8. Kingma, D. P., & Ba, J. (2015). Adam: A Method for Stochastic Optimization. International Conference on Learning Representations. https://arxiv.org/abs/1412.6980

  9. Polyak, B. T., & Juditsky, A. B. (1992). Acceleration of Stochastic Approximation by Averaging. SIAM Journal on Control and Optimization, 30(4), 838–855. https://doi.org/10.1137/0330046

  10. Duchi, J., Hazan, E., & Singer, Y. (2011). Adaptive Subgradient Methods for Online Learning and Stochastic Optimization. Journal of Machine Learning Research, 12(61), 2121–2159. https://jmlr.org/papers/v12/duchi11a.html

  11. Tieleman, T., & Hinton, G. (2012). Lecture 6.5-RMSProp: Divide the Gradient by a Running Average of Its Recent Magnitude. COURSERA: Neural Networks for Machine Learning.

  12. Loshchilov, I., & Hutter, F. (2019). Decoupled Weight Decay Regularization. International Conference on Learning Representations. https://arxiv.org/abs/1711.05101

  13. Goyal, P., Dollár, P., Girshick, R., Noordhuis, P., Wesolowski, L., Kyrola, A., Tulloch, A., Jia, Y., & He, K. (2017). Accurate, Large Minibatch SGD: Training ImageNet in 1 Hour. arXiv preprint. https://arxiv.org/abs/1706.02677




bottom of page