Worked examples — Reparameterization trick
This is the "roll up your sleeves" companion to the parent note. There we built the transform and saw why it lets gradients flow. Here we hit every kind of input the trick can face — positive and negative noise, the mean at zero, the variance collapsing to zero, many dimensions, and even the case where the trick cannot be used at all.
The scenario matrix
Every situation the trick can be handed falls into one of these cells. The examples below are labelled with the cell they cover, so by the end no cell is left dark.
| # | Cell class | What is special | Example |
|---|---|---|---|
| C1 | , ordinary | baseline sign of gradient | Ex 1 |
| C2 | sign of flips | Ex 2 | |
| C3 | shift term vanishes | Ex 3 | |
| C4 | (degenerate) | distribution collapses to a point | Ex 4 |
| C5 | Multivariate, diagonal | element-wise trick, Jacobian | Ex 5 |
| C6 | Monte-Carlo, samples | averaging, variance of estimate | Ex 6 |
| C7 | Real-world word problem | end-to-end VAE gradient step | Ex 7 |
| C8 | Exam twist — discrete latent | trick fails, needs alternative | Ex 8 |
Recall Why these are the only cells
has exactly two learnable knobs () and one random driver (). The behaviour changes only with the sign of (C1/C2), the boundary values of the knobs ( in C3, in C4), the dimension (C5), how we estimate the expectation (C6), and whether the latent is even continuous at all (C8). That exhausts the space.
We reuse one loss throughout so the arithmetic stays comparable: This loss just says "we want near the target ."
Example 1 — Cell C1: positive noise, ordinary parameters
Forecast: lands a bit above (the nudge is positive), still below target , so both gradients should be negative (we want to push up to raise toward 3).
- Compute . . Why this step? The deterministic transform turns the abstract "sample" into a concrete number we can differentiate.
- Loss. . Why this step? We need the current error to know how hard to push.
- Upstream gradient. . Why this step? The chain rule needs "how loss changes with " before we split into and .
- Local Jacobian. , . Why this step? These are the only derivatives the trick introduces — differentiating , a shift contributes and a stretch contributes ; without them the chain rule has no link from back to the parameters.
- Chain. ; .
Verify: Both negative, matching the forecast. Sanity: nudging up by a tiny gives , loss , whose slope at is . ✓

Example 2 — Cell C2: negative noise flips the gradient
Forecast: Now dips below , further from , so stays negative — but since , raising now lowers , so should flip positive.
- . . Why this step? Negative pulls the sample below the mean; we need the concrete before any derivative.
- . . Why this step? The chain rule always starts from "how the loss reacts to "; here we are much further below target, so the pull is stronger.
- Jacobian. , . Why this step? Same transform as Ex 1, so the same two derivatives — but the stretch derivative now carries the sign of the noise, which is exactly what will flip the -gradient.
- Chain. ; . Why this step? Multiplying the upstream derivative by each local derivative is the chain rule that carries the loss's demand all the way back to and .
Verify: — the sign flipped exactly as forecast, because a bigger stretch drags this particular sample down and away from the target. This is the whole point of C2: the same encoder gets opposite -advice depending on the sign of the noise, and averaging over many (Ex 6) is what makes the direction reliable. ✓
Example 3 — Cell C3: mean sitting at zero
Forecast: With the shift term disappears, so is pure scaled noise. We want , so we expect gradients that push down.
- . . Why this step? The term is literally ; is entirely the stretched nudge, and we still need its value to differentiate.
- . . Why this step? A new loss means a new upstream derivative; everything downstream reuses this number.
- Jacobian. , . Why this step? Differentiating gives the same two local slopes as always; note does not change them, which is the whole lesson of this cell.
- Chain. ; . Why this step? The chain rule multiplies upstream by local; this converts "loss wants smaller " into concrete parameter directions.
Verify: → gradient descent decreases , shrinking the noise so hugs . Exactly the "collapse toward the target" behaviour we forecast. Note did not break anything: the Jacobian is independent of the value of . ✓
Example 4 — Cell C4: variance collapsing (), the degenerate limit
Forecast: As spread vanishes, the "bell" narrows to a spike at ; the sample becomes deterministic. The -gradient should survive. The -gradient does not vanish — it settles at a finite value — but as we will qualify, that gradient can no longer buy much loss reduction per unit of -movement because has stopped wandering.
- Sample limit. for every . Why this step? Any finite times is , so the shift term is all that remains.
- Distribution limit. a Dirac spike at — no randomness left. Why this step? Variance means all probability mass piles onto one point; this is what "degenerate" means.
- -gradient. , unchanged by . Why this step? regardless of , so the mean channel is always alive — the trick never loses its grip on .
- -gradient. . At the limit , this — a nonzero, finite value for any . Why this step? We differentiate the same product and take the limit of ; the derivative itself does not disappear.
Verify: The trick stays perfectly differentiable in the degenerate limit — no division by anywhere (contrast the density of a Variational Autoencoder (VAE), which does divide by ). Careful qualification: the -gradient is not zero, so an optimizer step would still move . What is really happening at is that different noise draws produce almost identical samples , so the per-draw gradients scatter symmetrically about ; their expectation is what fades, not any individual gradient. Thus receives conflicting single-sample pushes that average out, while keeps a clean, consistent signal. This is one practical reason we optimize (keeping ) and never land exactly on the spike. At the single-draw -gradient limit is , matching Ex 1. ✓

Example 5 — Cell C5: multivariate diagonal Gaussian
Forecast: Because the covariance is diagonal, every dimension is its own copy of the 1-D trick — no cross-terms. The Jacobian is diagonal, so unless .
- Element-wise sample. : . Why this step? The Hadamard form (using the just defined) applies the scalar trick coordinate by coordinate, because a diagonal covariance means the coordinates are independent.
- Upstream. . Why this step? is a sum of squares, so its derivative w.r.t. each touches only that coordinate — the loss separates across dimensions.
- -gradient. . Why this step? Each coordinate's shift derivative is and, crucially, for , so the chain rule keeps every dimension in its own lane.
- -gradient. . Why this step? The stretch derivative for coordinate is its own noise ; the diagonal Jacobian means no coordinate's noise leaks into another's gradient, which is why backprop here is cheap.
Verify: Dimensions and landed exactly on the target , so their gradients are — the optimizer leaves them alone. Only dimension (off target at ) produces a push. The diagonal Jacobian means each coordinate's gradient depends only on its own . ✓

Example 6 — Cell C6: Monte-Carlo gradient over samples
Forecast: Each sample gives . Positive/negative noises spread around ; averaging should give a stable " is below , push it up" signal near .
- Samples. . Why this step? One transform per drawn noise gives the concrete latents we will differentiate at.
- Per-sample -gradients. . Why this step? so the -gradient equals the upstream derivative at each sample.
- Average. . Why this step? Monte-Carlo integration: the mean of samples is an unbiased estimate of the expectation we cannot compute in closed form for real networks.
Verify: The exact expectation is , because . Our 4-sample estimate hit on the nose here (the symmetric noises cancelled perfectly). In real training often suffices because the estimate is unbiased and mini-batches supply extra averaging. ✓

Example 7 — Cell C7: real-world word problem (one VAE step)
Forecast: The two loss terms fight: reconstruction pulls up, prior pulls down, so should settle between and . We expect to move toward that balance point () and to shrink (prior discourages large spread).
- Recover . . Why this step? The network stores precisely so automatically; we must convert to a real spread before we can sample.
- Sample. . Why this step? The reparameterized transform turns the stored parameters plus fixed noise into a differentiable latent.
- Upstream. . Why this step? is a sum of two squared terms; differentiating each and adding gives how the total loss reacts to — the start of every chain.
- -gradient. . Why this step? The shift derivative passes the upstream signal straight through to .
- -gradient. Chain twice: . Why this step? depends on (through the stretch ), and depends on ; because we optimize the log, we need this extra link , which is exactly why the log-parameterization stays differentiable.
- Update. ; . Why this step? Gradient descent subtracts learning-rate times gradient; updating (not ) keeps the spread positive no matter how many steps we take.
Verify: Both gradients positive ⇒ decreased (from sample , above the balance , so pull down) and decreased (spread shrinks under prior pressure), matching the forecast. Every step flowed through using ordinary backprop — no non-differentiable sampling anywhere. ✓
Example 8 — Cell C8: exam twist, when the trick cannot be used
Forecast: The location–scale trick needs a continuous variable you can smoothly shift and stretch. A category index is discrete — nudging a parameter can't move "half a category." Expect the trick to fail and a relaxation to step in.
First, name the encoder's outputs. The encoder produces class probabilities — one non-negative number per category, summing to — the softmax of the encoder's raw scores. So is simply "the model's believed probability that the latent equals category ." (In our worked check we use .)
- Test the requirement. The identity produces a real number; a class label is an integer with no meaningful in-between. Sampling a category from is a step function of — flat, then a sudden jump to a different label — so is almost everywhere and undefined at the jumps. Why this step? This is precisely the non-differentiability the parent note warned about: a gradient of everywhere carries no direction to improve .
- Replacement — Gumbel-Softmax. Introduce a temperature (a knob that controls how "soft" the output is; small = crisp, large = blurry). Draw one Gumbel noise per class, with , then form a soft one-hot vector whose -th entry is Why this step? The Gumbel noise plays the role of (parameter-free randomness), and the softmax with temperature makes a continuous, differentiable stand-in for the discrete pick. Crucially by construction (a normalized softmax), so is a valid probability vector we can backprop through — see 5.2.03-Gumbel-Softmax.
- Hard vs soft, and the limits. As , one entry of rushes to and the rest to : becomes a hard one-hot vector, recovering the true categorical draw. As , all logits are crushed together and , a uniform blur. Why this step? Covering both limits shows why we train at a moderate : small enough that resembles a real category, large enough that gradients still flow. (A common trick — "straight-through" — uses the hard one-hot in the forward pass but the soft 's gradient in the backward pass.)
- The other classic alternative. The score-function / REINFORCE estimator (see 6.1.02-Policy-Gradients) works for any distribution — discrete included — but has much higher variance than reparameterization. That trade-off is exactly why reparameterization is preferred whenever the latent is continuous, and Gumbel-Softmax is used to make a discrete latent continuous-ish.
Verify: With , any Gumbel draw and any , the soft one-hot sums to (a genuine probability distribution), so the relaxed sample is well-defined and differentiable — confirming the replacement is valid where the plain trick was not. This example marks the boundary of the matrix: outside it, we switch tools rather than force . ✓
Recall Self-check
In Ex 2, why did become positive while it was negative in Ex 1? ::: Because , and flipped sign (); a larger now pulls the sample away from the target. In the limit (Ex 4), does any single-sample -gradient vanish? ::: No — each stays a finite ; it is the expectation over that goes to , so gets conflicting pushes that cancel while keeps a clean signal. Why must , and how do we guarantee it in code? ::: A spread cannot be zero or negative; we output and set , which is always positive. Why does the Monte-Carlo estimate in Ex 6 equal the exact value? ::: The symmetric pairs made cancel exactly; in general it is only an unbiased estimate. Which single property of a distribution decides whether the trick applies at all? ::: Whether it is continuous and reparameterizable as a smooth function of parameter-free noise (Ex 8).
See also: 4.5.02-ELBO-Derivation · 4.5.04 Reparameterization trick (Hinglish)