Why SGD / Mini-Batch SGD Matters
For an objective built from millions of training examples, computing the full gradient before every update can be expensive. Stochastic gradient descent, or SGD, uses one sampled example; mini-batch SGD averages gradients from a small sample and makes one update. The estimate can be much cheaper than a full pass, while introducing noise into the direction.
The central tradeoff is work versus uncertainty. A larger batch averages more gradient information at the same point, often improving hardware utilization and reducing variance under suitable sampling. It also costs more gradient evaluations per update. Smaller batches make more updates under the same example-work budget, but their trajectories can fluctuate and the full objective can increase on a valid step.
This lesson uses explicit sampling with replacement, an integer-seeded random stream, and a squared-distance objective with a known minimizer. The programs implement both SGD and mini-batch SGD through the batch-size parameter. Full-dataset loss monitoring is optional and counted separately, so the demonstration does not conceal the cost of printing a full objective after each update.
SGD and mini-batch SGD replace a full empirical-risk gradient with a sampled mean of component gradients, then update the parameter vector once. State the sampling rule and batch normalization explicitly: an unbiased ideal estimate supports expectation-based analysis, while individual updates need not decrease the full objective and monitoring costs must be counted separately.
Core Concepts and Terminology
Let the empirical objective be the mean of $n$ component losses:
$$F(\mathbf w)=\frac1n\sum_{i=0}^{n-1}\ell_i(\mathbf w).$$
For update $t$, sample $b$ indices $I_{t,1},\ldots,I_{t,b}$ independently and uniformly with replacement in the ideal random model. Repeats are allowed. Compute every component gradient at the same old parameter vector, form their mean, and update once:
$$\widehat{\mathbf g}_t=\frac1b\sum_{r=1}^b\nabla\ell_{I_{t,r}}(\mathbf w_t),\qquad\mathbf w_{t+1}=\mathbf w_t-\eta\widehat{\mathbf g}_t.$$
Batch size $b=1$ gives ordinary SGD. A full gradient instead evaluates every example once at the same point. Merely setting $b=n$ in a with-replacement sampler does not produce a full gradient: some examples can appear repeatedly while others are omitted. The program permits $b\gt n$ for the same reason.
An epoch usually denotes one traversal of a finite dataset, often with reshuffling. This with-replacement implementation has no epochs or shuffled permutations. Processing $n$ sampled gradient examples gives a work-equivalent pass, not a guarantee that every example has been visited.
The teaching loss is $\ell_i(\mathbf w)=\tfrac12\lVert\mathbf w-\mathbf c_i\rVert_2^2$, with component gradient $\mathbf w-\mathbf c_i$. If $\boldsymbol\mu=n^{-1}\sum_i\mathbf c_i$, then
$$F(\mathbf w)=\frac12\lVert\mathbf w-\boldsymbol\mu\rVert_2^2+\frac1{2n}\sum_i\lVert\mathbf c_i-\boldsymbol\mu\rVert_2^2.$$
Thus the unique minimizer is $\boldsymbol\mu$, but the minimum loss need not be zero. In the worked one-dimensional data, centers $[-2,0,2,4]$ have mean $1$ and variance $5$, so $F(w)=\tfrac12(w-1)^2+2.5$, its full gradient is $w-1$, and its minimum is $F(1)=2.5$.
| Term | Worked example | Meaning |
|---|---|---|
| Dataset / component | Center $c_2=2$ defines $\ell_2(w)=(w-2)^2/2$ | One contribution to mean empirical loss |
| Parameter | $w_0=5$ | Shared value updated by optimization |
| Batch indices | First mini-batch is $(2,2)$ | With-replacement sampling allows duplicates |
| Component gradient | $5-2=3$ for each occurrence | Derivative evaluated at the old parameter |
| Mean batch gradient | $(3+3)/2=3$ | Divide by actual sample count, including repeats |
| Learning rate | $\eta=0.5$ | Scales one mean-gradient update |
| Full gradient | $w-1$ | Derivative of the complete empirical mean |
| Full-loss monitoring | Four component losses per displayed full objective | Diagnostic work, separate from sampled gradients |
| Gradient-example budget | Eight evaluations for four batches of size $2$ | Counts repeated sampled examples separately |
| Gradient noise | At $w=2$, sampling center $2$ gives $0$ while full gradient is $1$ | Explains why one sampled residual is not a convergence certificate |
How SGD / Mini-Batch SGD Works, Step by Step
Inputs are the initial parameter vector, a finite list of center vectors, seed, batch size $b$, constant learning rate $\eta$, update limit $K$, gradient-example budget $B$, and a full-monitoring flag.
- Validate and copy. Check shapes, numeric ranges, seed, and controls. Copy parameters and data. Initialize the seeded generator. Full monitoring, when enabled, evaluates the full objective at the starting point and counts $n$ example-loss evaluations. It uses no sampled gradients and consumes no randomness.
- Record the start. Step $0$ has an empty batch and empty gradient because no update has occurred. It always contains the starting point. If monitoring is off, the stored full-loss field is a dummy zero, and output explicitly prints
OFF. - Check limits before sampling.
STEP_LIMITtakes precedence when $K$ updates have completed. Otherwise require room for all $b$ gradient examples; if unavailable, returnGRAD_BUDGETbefore drawing indices. A leftover budget smaller than $b$ does not create a partial batch. - Sample a full batch. Draw $b$ indices with replacement, in order. Every occurrence counts as a component-gradient evaluation, even when the same index repeats. The order also fixes floating-point accumulation.
- Accumulate at one frozen point. Initialize the gradient sum to zero. For each sampled index, add $\mathbf w-\mathbf c_i$ coordinate by coordinate without changing $\mathbf w$. Divide each accumulated coordinate by $b$ exactly once.
- Make one update. Multiply the mean gradient by $\eta$ and subtract it from the old point. Count one update and $b$ gradient examples. Zero-gradient batches and unchanged numerical proposals are counted, but they do not stop this stochastic run: the next sampled batch can have a different gradient.
- Monitor and record. If enabled, evaluate the full objective at the new point, charging another $n$ example-loss evaluations. Record the batch, mean gradient, new point, loss or monitoring flag, counters, and generator state, then repeat.
The algorithm does not use the monitored loss to accept or reject an update, change the learning rate, select a historical best, or stop. Consequently turning monitoring off preserves the training trajectory and random stream. There is no line search, epoch reshuffling, momentum, adaptive rate, gradient clipping, or convergence-tolerance exit in these programs.
flowchart TD
A["Validate, copy parameters and data, initialize RNG"] --> B["Optionally monitor full starting loss and record step zero"]
B --> C{"Update limit reached?"}
C -->|Yes| Y["Return STEP_LIMIT"]
C -->|No| D{"Budget covers a complete batch?"}
D -->|No| Z["Return GRAD_BUDGET"]
D -->|Yes| E["Sample b indices with replacement"]
E --> F["Sum gradients at the same old parameters"]
F --> G["Divide by b and update parameters once"]
G --> H["Count zero or unchanged updates without stopping"]
H --> I["Optionally monitor full loss and record state"]
I --> C
Worked Example with a Full Trace
Use centers $[-2,0,2,4]$, start $w_0=5$, seed $13$, batch size $b=2$, rate $\eta=0.5$, update limit $K=4$, gradient budget $B=100$, and full monitoring enabled. The initial full objective is $F(5)=10.5$.
The portable random generator follows
$$z_{k+1}=48271z_k\bmod2147483647,\qquad z_0=13.$$
Let $R=2147483646$. For a dataset of size $n$, map a raw state by $v=z-1$: reject and retry if $v\ge R-(R\bmod n)$, otherwise use index $v\bmod n$. Under a uniform raw-input model this balances residue classes. The seeded generator itself is deterministic and does not supply independent mathematical randomness. Its first state is $627523$, giving index $(627523-1)\bmod4=2$.
All four mini-batch updates are:
| Update | Old w | Indices / centers | Component gradients at old w | Mean gradient | New w | Full F(new w) |
|---|---|---|---|---|---|---|
| $1$ | $5$ | 2,2 / 2,2 | 3,3 | $3$ | $3.5$ | $5.625000000$ |
| $2$ | $3.5$ | 0,3 / -2,4 | 5.5,-0.5 | $2.5$ | $2.25$ | $3.281250000$ |
| $3$ | $2.25$ | 0,0 / -2,-2 | 4.25,4.25 | $4.25$ | $0.125$ | $2.882812500$ |
| $4$ | $0.125$ | 2,1 / 2,0 | -1.875,0.125 | $-0.875$ | $0.5625$ | $2.595703125$ |
The repeated first batch $(2,2)$ evaluates the same component twice, each time at $w=5$. Both gradients equal $3$, so their mean is $3$ and the new point is $3.5$. The second batch uses centers $-2$ and $4$, giving gradients $5.5$ and $-0.5$ at the same old point $3.5$; their average is $2.5$, producing $2.25$.
At step $3$, both samples are center $-2$. Their gradients are both $4.25$, and their mean is $4.25$, not the sum $8.5$. One update moves from $2.25$ to $0.125$. At step $4$, sampled centers $2$ and $0$ give gradients $-1.875$ and $0.125$; their mean is $-0.875$, so subtracting the scaled negative gradient increases the parameter to $0.5625$.
Final status is STEP_LIMIT, with $4$ updates, $8$ gradient-example evaluations, $20$ monitoring loss-example evaluations, $8$ raw random draws, no retries, no zero-gradient batches, and final random state $373896330$. The exact final full loss is $2.595703125$, above the known minimum $2.5$.
The batch-end generator states and cumulative draw counts are:
| Update | Batch-end state | Cumulative raw draws |
|---|---|---|
| $1$ | $226391675$ | $2$ |
| $2$ | $1269048164$ | $4$ |
| $3$ | $1000656585$ | $6$ |
| $4$ | $373896330$ | $8$ |
For comparison, the batch-size-$1$ run uses the same seed and four updates, producing:
| Update | Index | Old w | Sample gradient | New w | Full objective |
|---|---|---|---|---|---|
| $1$ | $2$ | $5$ | $3$ | $3.5$ | $5.625$ |
| $2$ | $2$ | $3.5$ | $1.5$ | $2.75$ | $4.03125$ |
| $3$ | $0$ | $2.75$ | $4.75$ | $0.375$ | $2.6953125$ |
| $4$ | $3$ | $0.375$ | $-3.625$ | $2.1875$ | $3.205078125$ |
The fourth SGD step increases the full objective. This is a valid sampled update, not an implementation error. The comparison uses equal update counts but unequal gradient work: batch size $2$ spends eight gradient examples, while batch size $1$ spends four. It is an illustration of the mechanisms, not evidence that one wins under equal work.
Budget $B=3$ allows one complete size-$2$ batch, leaving one gradient evaluation unused; no second batch is sampled. With zero gradient budget, the parameter is still the valid supplied start and full monitoring still evaluates its four losses. Turning monitoring off spends no full-loss evaluations and preserves every training update.
Trace It by Hand
At $w=2.25$, both sampled indices are $0$, whose center is $-2$. With batch size $2$ and rate $0.5$, predict the two component gradients, mean gradient, new parameter, and full objective.
Reveal: each component gradient is $2.25-(-2)=4.25$. The mean is $(4.25+4.25)/2=4.25$, so $w_{\mathrm{next}}=2.25-0.5(4.25)=0.125$. The full objective is $0.5(0.125-1)^2+2.5=2.8828125$. Using the unnormalized sum would instead jump to $-2$, whose full objective is $7$.
Implementation in Python, C++, and Java
Each language panel is complete and independent. Use Python $3.10+$, C++17, or Java $17+$. Compile C++ with g++ -std=c++17 -O2 -ffp-contract=off main.cpp -o sgd and avoid fast-math transformations when comparing binary64 decisions. Save the Java panel as Main.java.
The solver accepts $1\le d\le16$ coordinates, $1\le n\le64$ center vectors, a seed in $1,\ldots,2147483646$, $1\le b\le64$, finite $0\lt\eta\le1$, $0\le K\le500$, and integer $0\le B\le10^6$. All coordinates must be finite and have magnitude at most $10^6$. Batch size may exceed dataset size because sampling is with replacement. The range for $\eta$ suits this common-Hessian quadratic; it is not a generic safe-learning-rate rule for arbitrary training losses.
Python rejects booleans as numeric data, requires actual integers for seed/batch/update/budget controls, and requires an actual Boolean monitoring flag. Inputs must be ordinary finite sequences; Java arrays and rows must be non-null. Invalid inputs raise an exception before training. The optimizer copies inputs and snapshots, preserving recorded points and gradients.
Result holds the final point, monitor flag, final monitored full loss, status, update and example-work counts, zero-gradient and unchanged-update counts, generator state/draw/retry counts, and full history. When monitoring is disabled, the numeric full-loss fields are dummy zeros, and output prints OFF; they must not be interpreted as a zero objective. Step $0$ has empty indices and gradient because no batch was sampled yet. Later history rows store the gradient computed at the preceding row's point and the new point reached by that update.
Training and monitoring budgets are intentionally separate. $B$ limits sampled component-gradient evaluations only. Monitoring at initialization and after every update, when enabled, still costs full-dataset loss evaluations, including with $B=0$. The program reports both costs explicitly. STEP_LIMIT takes precedence when both limits would stop; otherwise it stops before sampling a batch that cannot fit. It performs no partial batch and never silently drops repeated samples.
Arithmetic order is fixed: draw all batch indices, accumulate component gradients in sampled order at the unchanged old point, divide by actual batch size, multiply by rate, and subtract. Monitoring iterates data rows then coordinates, subtracts, squares, sums, multiplies by $1/2$, and divides by $n$. Java's BigDecimal helper only provides eight-place half-even display rounding; optimization uses double. The tested cross-language histories match at binary64 precision, while theoretical unbiasedness and variance claims refer to ideal sampling and exact arithmetic.
The common-Hessian loss is a transparent verification problem with an analytic answer, not a general model-training library. For other losses, provide correct per-example gradients, review their smoothness and numeric ranges, and define policies for non-finite values, constraints, and failures. The monitor flag is included so production-style training need not pay for a full objective after every update.
Expected standard output, identical in all three languages:
mini-batchk=0 x=(5.00000000) batch=- grad=- full=10.50000000 grad_examples=0 loss_examples=4k=1 x=(3.50000000) batch=2,2 grad=(3.00000000) full=5.62500000 grad_examples=2 loss_examples=8k=2 x=(2.25000000) batch=0,3 grad=(2.50000000) full=3.28125000 grad_examples=4 loss_examples=12k=3 x=(0.12500000) batch=0,0 grad=(4.25000000) full=2.88281250 grad_examples=6 loss_examples=16k=4 x=(0.56250000) batch=2,1 grad=(-0.87500000) full=2.59570312 grad_examples=8 loss_examples=20status=STEP_LIMIT updates=4 grad_examples=8 loss_examples=20 zero_batches=0 unchanged=0 draws=8 rejections=0 rng=373896330sgdk=0 x=(5.00000000) batch=- grad=- full=10.50000000 grad_examples=0 loss_examples=4k=1 x=(3.50000000) batch=2 grad=(3.00000000) full=5.62500000 grad_examples=1 loss_examples=8k=2 x=(2.75000000) batch=2 grad=(1.50000000) full=4.03125000 grad_examples=2 loss_examples=12k=3 x=(0.37500000) batch=0 grad=(4.75000000) full=2.69531250 grad_examples=3 loss_examples=16k=4 x=(2.18750000) batch=3 grad=(-3.62500000) full=3.20507812 grad_examples=4 loss_examples=20status=STEP_LIMIT updates=4 grad_examples=4 loss_examples=20 zero_batches=0 unchanged=0 draws=4 rejections=0 rng=1269048164budgetk=0 x=(5.00000000) batch=- grad=- full=10.50000000 grad_examples=0 loss_examples=4k=1 x=(3.50000000) batch=2,2 grad=(3.00000000) full=5.62500000 grad_examples=2 loss_examples=8status=GRAD_BUDGET updates=1 grad_examples=2 loss_examples=8 zero_batches=0 unchanged=0 draws=2 rejections=0 rng=226391675monitor-offk=0 x=(5.00000000) batch=- grad=- full=OFF grad_examples=0 loss_examples=0k=1 x=(3.50000000) batch=2,2 grad=(3.00000000) full=OFF grad_examples=2 loss_examples=0k=2 x=(2.25000000) batch=0,3 grad=(2.50000000) full=OFF grad_examples=4 loss_examples=0status=STEP_LIMIT updates=2 grad_examples=4 loss_examples=0 zero_batches=0 unchanged=0 draws=4 rejections=0 rng=1269048164zero-budgetk=0 x=(5.00000000) batch=- grad=- full=10.50000000 grad_examples=0 loss_examples=4status=GRAD_BUDGET updates=0 grad_examples=0 loss_examples=4 zero_batches=0 unchanged=0 draws=0 rejections=0 rng=13
Complexity, Correctness, and Invariants
Let $T$ be completed updates. This program has no early convergence exit, so
$$T=\min\left(K,\left\lfloor\frac{B}{b}\right\rfloor\right),\qquad G=bT.$$
Here $G$ counts component-gradient examples, including repeated indices. Full monitoring separately costs $H=n(T+1)$ component-loss examples; with monitoring off, $H=0$. If $J$ raw draws are rejected, random draw count is $Q=bT+J$. Checks occur before sampling, so an unaffordable batch consumes no random draws and no gradient work.
For this generator and bounds $n\le64$, a rejected state is followed by an accepted one: it is $2147483647-a$ for $1\le a\le63$, whose successor $2147483647-48271a$ lies outside every relevant rejection interval. Thus mapping has bounded constant cost here. Input validation and copying cost $\Theta(nd)$. Training costs $\Theta(Tbd)$, and optional full monitoring adds $\Theta((T+1)nd)$. Including these components, actual runtime is
$$\Theta\bigl(nd+Tbd+\mathbf1_{\mathrm{monitor}}(T+1)nd\bigr).$$
Best, average, and worst objective landscapes do the same amount of work for fixed valid sizes and controls; attained quality can differ. Best work for zero updates still includes input validation and any requested initial full-loss pass. For a general loss, substitute actual per-example gradient and loss costs. Wall-clock speed also depends on vectorization, memory traffic, and hardware utilization, so increasing batch size does not automatically improve quality or time to target.
Live training state needs $O(b+d)$ auxiliary space beyond data, and this implementation copies the $O(nd)$ dataset. It retains history, so total auxiliary storage is $O(nd+(T+1)(b+d))$, including sampled indices, parameter vectors, and mean gradients. Removing or thinning history reduces that extra trace storage. Full monitoring does not use a training gradient or alter randomness.
The implementation invariant is that each committed update uses the arithmetic mean of exactly $b$ sampled component gradients evaluated at the same preceding point. Its counters satisfy $G=bT$, histories contain $T+1$ coherent states, and a monitored score belongs to the point stored in its row. A history gradient belongs to the previous point, so its provenance is explicit. These are consistency guarantees, not monotone-loss or optimality guarantees.
Under independent uniform sampling with replacement and exact arithmetic,
$$\mathbb E[\widehat{\mathbf g}_t\mid\mathbf w_t]=\nabla F(\mathbf w_t).$$
If the conditional single-example squared noise is bounded by $\sigma^2$, averaging $b$ independent samples gives conditional squared noise at most $\sigma^2/b$. This needs the sampling assumptions: random reshuffling within an epoch has a different conditional distribution, and nonuniform sampling generally needs appropriate weighting to target the same empirical objective.
For the teaching family these facts can be proved directly. Let $\sigma_c^2=n^{-1}\sum_i\lVert\mathbf c_i-\boldsymbol\mu\rVert_2^2$. A sampled mean center $\overline{\mathbf c}_t$ satisfies $\widehat{\mathbf g}_t=\mathbf w_t-\overline{\mathbf c}_t$, so error $\mathbf e_t=\mathbf w_t-\boldsymbol\mu$ obeys
$$\mathbf e_{t+1}=(1-\eta)\mathbf e_t+\eta(\overline{\mathbf c}_t-\boldsymbol\mu).$$
The sampled-center noise has mean zero and squared norm expectation $\sigma_c^2/b$, giving the exact conditional recurrence
$$\mathbb E[\lVert\mathbf e_{t+1}\rVert_2^2\mid\mathbf w_t]=(1-\eta)^2\lVert\mathbf e_t\rVert_2^2+\frac{\eta^2\sigma_c^2}{b}.$$
For constant $0\lt\eta\le1$ and nonzero variance, the limiting expected squared parameter error is $\eta\sigma_c^2/[b(2-\eta)]$. Expected objective gap is half that value. For the worked data, $\sigma_c^2=5$, $\eta=1/2$, and $b=2$, the ideal limiting expected objective gap is $5/12$. A lucky short run can have a smaller gap; the limit describes an expectation over random runs, not a lower bound on every iterate. Fixed-rate stochastic iterates generally fluctuate rather than converge exactly to the minimizer.
This also explains why $b=n$ with replacement retains variance $\sigma_c^2/n$, whereas averaging every example once at a fixed point has no sampling variance. Decreasing learning rates, increasing batch sizes, or iterate averaging can improve asymptotic behavior under appropriate assumptions, but none is implemented silently here. The finite deterministic generator and floating-point arithmetic support reproducibility, not a proof that the ideal probability model holds for its sequence.
| Method / policy | Typical gradient work per update | Sampling and diagnostic implications |
|---|---|---|
| Full gradient descent | $n$ component gradients | Every example once at one point; no sampling noise |
| SGD | One component gradient | Fresh with-replacement draw in this lesson; noisy individual updates |
| Mini-batch SGD | $b$ component gradients | Mean of a sampled batch; repeats allowed; ideal variance shrinks by $b$ |
| Random reshuffling | Usually $b$ gradients per batch, one shuffled pass per epoch | No repeats within the pass; conditional sampling assumptions differ |
| Gradient accumulation | Sum of several micro-batches before one update | Matches one large mean gradient only with correct scaling, frozen parameters, and compatible model behavior |
| Momentum / adaptive optimizer | Batch-gradient cost plus parameter-state work | Additional update state; not identical to plain SGD |
| This full monitor | $n$ component-loss evaluations, separate from gradients | Optional at initialization and every update; can dominate small-batch training |
Every update uses the mean of exactly the sampled batch's gradients at one unchanged old point, and counters separately account for training gradients and full-loss monitoring. Ideal independent uniform sampling makes that mean an unbiased estimate with reduced variance, but does not make each update a descent step for the full loss; a single zero estimate is not a convergence certificate.
Variants, Pitfalls, and Optimizations
Mean versus sum matters. Dividing by batch size keeps the update scale consistent with a mean empirical objective. Using a sum silently multiplies the effective rate by $b$. A final smaller batch in an epoch-based implementation must use its actual size. This reference implementation instead requires a complete fixed-size batch and stops before an unaffordable one; it does not divide a short batch by an unrelated nominal size.
Freeze parameters throughout a batch. Accumulating several gradients and then updating once is different from taking an SGD step after each example. Gradient accumulation across micro-batches can reproduce a larger mean gradient when parameters remain unchanged and normalization is correct. Stateful operations such as batch normalization, independently sampled dropout, or updates to other model state can prevent exact equivalence even when the algebraic scaling looks right.
Do not stop on one zero sampled gradient. At $w=2$, the component centered at $2$ has zero gradient while the full objective's gradient is $1$. With the two-center dataset $[2,0]$, seed $1$ first samples center $2$ and then center $0$: the first update is unchanged, but the second reaches the true mean $1$ at rate $0.5$. A small or unchanged stochastic step can also reflect rounding, a tiny rate, or sampling noise. Use a defined diagnostic and stopping policy rather than calling that one batch converged.
Define sampling, epochs, and unbiasedness together. Sampling with replacement can repeat an example even inside one batch. Shuffling a finite dataset once per epoch is a different schedule; the next draw conditioned on past draws is no longer uniform over all examples. Importance sampling and class balancing change probabilities and may require weights to preserve the desired objective. Duplicate sampling is not inherently a bug, but an unintended sampling rule is.
Do not require monotone full loss. An unbiased direction is an expectation statement, not a guarantee about a particular draw. Constant step sizes can maintain a noise neighborhood even on strongly convex quadratics. Decay schedules or averaging require their own choices and assumptions. Comparing only a smoothed training curve can hide transient increases, and comparing only batch losses can conflate changing data with parameter progress.
Count the expensive work. Computing the full training loss after every small-batch update can erase much of its computational advantage. Use periodic full diagnostics or other stated metrics in larger systems and report their costs. Compare methods at equal sampled-example budgets, wall-clock budgets, or a clearly chosen target criterion; equal update counts are not equal work when batch sizes differ. Larger batches can improve hardware utilization without implying a universal linear learning-rate scaling rule.
Keep objectives and regularization consistent. Sum versus mean reduction, example weights, and penalty scaling affect gradients. A regularizer included identically in every component remains once after averaging; adding it incorrectly per example outside that averaging can overcount it. Check model gradients with suitable finite differences or an independent reference on small cases, and separate training optimization from validation performance and data leakage.
Use the right comparison. Momentum, Adam, variance-reduced methods, distributed sampling, and data-parallel gradient averaging add policies beyond plain SGD. Synchronization, averaging weights for unequal batch sizes, and random streams affect reproducibility. Cornell's primary mini-batch analysis and SGD notes explain how variance and learning-rate assumptions enter convergence reasoning; match those assumptions before carrying a theorem into an implementation.
Average using the actual batch size, evaluate all batch gradients at the same old parameters, and state whether sampling uses replacement or reshuffling. Separate monitored full loss from sampled training work, and never infer convergence from one zero or unchanged stochastic update; noise can increase full loss even when the implementation is correct.
Practice Problems and Real-World Use
Start with the center-fitting family, whose minimizer is the center mean. Exhaustively enumerate all possible small batches to verify expected gradients and variances, then compare repeated seeds at matched gradient-example budgets. Turn monitoring on and off to verify that diagnostic work does not alter the training path.
For a realistic learning task, derive the per-example loss and gradient before choosing the sampling and batch policy. Record reduction, regularization, initialization, seed streams, update schedule, partial-batch handling, monitoring cadence, training work, and validation protocol. Linear and logistic models make useful next steps before introducing model state, autodifferentiation, distributed execution, or adaptive optimizers.
| Problem or application | Exercise | Main idea tested | Difficulty |
|---|---|---|---|
| Mean-center fitting | Reproduce both traces and compare with the analytic mean | Batch averaging, duplicates, and noise | Easy |
| Zero-gradient trap | Sample a component whose gradient vanishes away from the full optimum | Stopping-policy correctness | Easy |
| Exact small-batch enumeration | Enumerate with-replacement tuples and compute moments | Unbiasedness and variance reduction | Medium |
| Mini-batch linear regression | Derive residual gradients and compare with a full-gradient reference | Matrix batches, reduction, and gradient work | Medium |
| Regularized logistic regression | Check stable per-example loss and penalty scaling | Correct objectives and validation | Hard |
| Reshuffling laboratory | Compare sampling schedules under equal gradient work | Epoch coverage and conditional distributions | Medium |
| Micro-batch accumulation | Match a larger frozen-parameter batch on a simple model | Normalization and update timing | Hard |
| Monitoring and parallel training | Separate diagnostics and define worker averaging | Cost accounting and reproducibility | Advanced |