Md. Asif Uddin

    Chapter 4 · I.4

    Problems

    A chapter that uses mathematics has to teach that mathematics by making the reader compute. A chapter that only displays equations has failed, however correct the equations are.

    M3Load-bearing

    7/5 problems6/4 variants10/10 exercisesquota met, and enforced

    The contract

    • 5 worked problems, minimum.
    • 4 distinct variants, and no variant more than half of them.
    • 10 exercises, every one with a published solution.
    • At least one numeric problem — present.
    • At least one symbolic problem — present.
    • At least one limit or counterexample problem — present.
    • At least one complexity or shape problem — present.
    • At least one ▲▲▲ problem — present.

    Numerical instantiationSymbolic derivationDifferentiationProbabilisticConstructed failureDimensional algebra

    Problem I.4.B01

    Three losses on the same five residuals

    numeric▲△△

    All values rounded to 4 d.p. The arithmetic is exact; only the display is rounded.

    STATEMENT

    Five residuals are given, one of them an outlier. Compute MSE, MAE and Huber with δ=1\delta = 1 on all five. Then determine, for each loss, what share of the total the outlier alone contributes, and what derivative each loss sends back for it.

    GIVEN

    The residuals ri=y^i−yir_i = \hat{y}_i - y_i:

    r=( 0.5, −0.8, 0.2, −0.3, 4.0 ),n=5r = (\,0.5,\ -0.8,\ 0.2,\ -0.3,\ 4.0\,), \qquad n = 5

    The three losses, as per-residual functions before any averaging:

    ℓMSE(r)=r2,ℓMAE(r)=∣r∣,Huberδ(r)={12r2∣r∣≤δδ ⁣(∣r∣−12δ)∣r∣>δ\ell_{\text{MSE}}(r) = r^{2}, \qquad \ell_{\text{MAE}}(r) = |r|, \qquad \mathrm{Huber}_{\delta}(r) = \begin{cases} \tfrac12 r^{2} & |r| \le \delta \\[2pt] \delta\!\left(|r| - \tfrac12\delta\right) & |r| > \delta \end{cases}

    with δ=1\delta = 1.

    FIND

    The per-residual contribution under each loss; the three totals and means; the outlier’s percentage share of each total; and dℓ/dr\mathrm{d}\ell/\mathrm{d}r evaluated at r=4.0r = 4.0 for each.

    STRATEGY

    Build one table column at a time rather than one row at a time. Each column is a single function applied five times, so a slip is visible as a break in the column’s pattern — whereas working row by row hides it.

    SOLUTION

    Step 0 — which branch of Huber each residual takes. The branch is decided by ∣r∣|r| against δ=1\delta = 1, so check all five before computing anything:

    ∣0.5∣=0.5≤1,∣−0.8∣=0.8≤1,∣0.2∣=0.2≤1,∣−0.3∣=0.3≤1,∣4.0∣=4.0>1|0.5| = 0.5 \le 1,\quad |{-0.8}| = 0.8 \le 1,\quad |0.2| = 0.2 \le 1,\quad |{-0.3}| = 0.3 \le 1,\quad |4.0| = 4.0 > 1

    Four take the quadratic branch; the fifth alone takes the linear one. Settling this first means the rest is arithmetic with no case analysis mixed in.

    Step 1 — the squared column. Squaring each residual:

    (0.5)2=0.25(−0.8)2=0.64(0.2)2=0.04(−0.3)2=0.09(4.0)2=16.00\begin{aligned} (0.5)^2 &= 0.25 \\ (-0.8)^2 &= 0.64 \\ (0.2)^2 &= 0.04 \\ (-0.3)^2 &= 0.09 \\ (4.0)^2 &= 16.00 \end{aligned}

    Note the sign has already vanished — squaring is why MSE never needs an absolute value. Summing:

    ∑ri2=0.25+0.64+0.04+0.09+16.00=17.02\sum r_i^2 = 0.25 + 0.64 + 0.04 + 0.09 + 16.00 = 17.02

    MSE=17.025=3.4040\text{MSE} = \frac{17.02}{5} = 3.4040

    Step 2 — the absolute column. Taking magnitudes:

    0.5,0.8,0.2,0.3,4.00.5,\quad 0.8,\quad 0.2,\quad 0.3,\quad 4.0

    ∑∣ri∣=0.5+0.8+0.2+0.3+4.0=5.8\sum |r_i| = 0.5 + 0.8 + 0.2 + 0.3 + 4.0 = 5.8

    MAE=5.85=1.1600\text{MAE} = \frac{5.8}{5} = 1.1600

    Step 3 — the Huber column. For the four quadratic-branch residuals, 12r2\tfrac12 r^2, which is just half of Step 1’s numbers:

    12(0.25)=0.1250,12(0.64)=0.3200,12(0.04)=0.0200,12(0.09)=0.0450\tfrac12(0.25) = 0.1250, \quad \tfrac12(0.64) = 0.3200, \quad \tfrac12(0.04) = 0.0200, \quad \tfrac12(0.09) = 0.0450

    For the outlier, the linear branch with δ=1\delta = 1:

    Huber1(4.0)=(1) ⁣(4.0−12(1))=4.0−0.5=3.5000\mathrm{Huber}_1(4.0) = (1)\!\left(4.0 - \tfrac12(1)\right) = 4.0 - 0.5 = 3.5000

    Summing:

    ∑Huber=0.1250+0.3200+0.0200+0.0450+3.5000=4.0100\sum \mathrm{Huber} = 0.1250 + 0.3200 + 0.0200 + 0.0450 + 3.5000 = 4.0100

    Huber‾=4.01005=0.8020\overline{\mathrm{Huber}} = \frac{4.0100}{5} = 0.8020

    The completed table.

    | rr | r2r^{2} | ∣r∣|r| | Huber1\mathrm{Huber}_1 | |---|---|---|---| | 0.50.5 | 0.25000.2500 | 0.50000.5000 | 0.12500.1250 | | −0.8-0.8 | 0.64000.6400 | 0.80000.8000 | 0.32000.3200 | | 0.20.2 | 0.04000.0400 | 0.20000.2000 | 0.02000.0200 | | −0.3-0.3 | 0.09000.0900 | 0.30000.3000 | 0.04500.0450 | | 4.04.0 | 16.000016.0000 | 4.00004.0000 | 3.50003.5000 | | sum | 17.020017.0200 | 5.80005.8000 | 4.01004.0100 | | mean | 3.40403.4040 | 1.16001.1600 | 0.80200.8020 |

    Step 4 — the outlier’s share. Divide the outlier’s own contribution by each total:

    MSE:16.000017.0200=0.9401=94.0%\text{MSE:}\quad \frac{16.0000}{17.0200} = 0.9401 = 94.0\%MAE:4.00005.8000=0.6897=69.0%\text{MAE:}\quad \frac{4.0000}{5.8000} = 0.6897 = 69.0\%Huber:3.50004.0100=0.8728=87.3%\text{Huber:}\quad \frac{3.5000}{4.0100} = 0.8728 = 87.3\%

    Step 5 — the derivatives, which are the operative quantity. The loss value is a diagnostic; the derivative is what training actually uses. Differentiating each per-residual loss at r=4.0r = 4.0:

    ddr r2=2r⟹2(4.0)=8.0000\frac{\mathrm{d}}{\mathrm{d}r}\,r^{2} = 2r \quad\Longrightarrow\quad 2(4.0) = 8.0000ddr ∣r∣=sign⁡(r)⟹sign⁡(4.0)=1.0000\frac{\mathrm{d}}{\mathrm{d}r}\,|r| = \operatorname{sign}(r) \quad\Longrightarrow\quad \operatorname{sign}(4.0) = 1.0000

    For Huber on the linear branch, d/dr [δ(r−12δ)]=δ\mathrm{d}/\mathrm{d}r\,[\delta(r - \tfrac12\delta)] = \delta:

    Huber1′(4.0)=δ=1.0000\mathrm{Huber}_1'(4.0) = \delta = 1.0000

    So the outlier pulls eight times harder under MSE than under either of the other two.

    Step 6 — what the two measurements say together. Compare the share of the value with the share of the pull:

    share of loss valuederivative at the outlier
    MSE94.0%94.0\%8.08.0
    MAE69.0%69.0\%1.01.0
    Huber87.3%87.3\%1.01.0

    Huber’s value share, 87.3%87.3\%, is close to MSE’s — because the four inliers are small and halving them makes the outlier look even more dominant. But its derivative is MAE’s. That combination is the entire design: Huber reports a large loss when there is a large error, while refusing to let that error dominate the step. A loss’s value and a loss’s gradient are different measurements and can disagree, and only the second one moves the model.

    Step 7 — the four inliers alone. Removing the outlier and averaging over n=4n = 4:

    MSE=0.984=0.2550,MAE=1.84=0.4500,Huber‾=0.514=0.1275\text{MSE} = \frac{0.98}{4} = 0.2550,\qquad \text{MAE} = \frac{1.8}{4} = 0.4500,\qquad \overline{\mathrm{Huber}} = \frac{0.51}{4} = 0.1275

    MSE fell by a factor of 3.4040/0.2550=13.353.4040/0.2550 = 13.35; MAE by 1.1600/0.4500=2.581.1600/0.4500 = 2.58. One point in five moved MSE more than thirteenfold.

    Answer

    MSE=3.4040,MAE=1.1600,Huber1‾=0.8020\text{MSE} = 3.4040, \qquad \text{MAE} = 1.1600, \qquad \overline{\mathrm{Huber}_1} = 0.8020

    Outlier share of the total: 94.0%94.0\%, 69.0%69.0\%, 87.3%87.3\% respectively.

    Derivative at r=4.0r = 4.0:   8.0\;8.0 (MSE),   1.0\;1.0 (MAE),   1.0\;1.0 (Huber).

    All values are dimensionless here; in general MSE carries the square of the target’s units while MAE and Huber carry the units themselves — which is why MSE is usually reported as its square root.

    Check — numeric · i-4-b01-three-losses.py
    def huber(t):
        a = abs(t)
        return 0.5 * t * t if a <= delta else delta * (a - 0.5 * delta)
    def d_huber(t):
        a = abs(t)
        return t if a <= delta else delta * (1.0 if t > 0 else -1.0)

    Prints every column, the three shares, the three derivatives, and the inliers-only means.

    Executed in CI. The digits above are the digits it printed.

    Check — sanity

    Huber sits between half-MSE and MAE, as its definition forces. Per residual, Huber1(r)≤12r2\mathrm{Huber}_1(r) \le \tfrac12 r^2 always (equality on the quadratic branch, strictly below on the linear one) and Huber1(r)≤∣r∣\mathrm{Huber}_1(r) \le |r| always. Check the totals: 4.0100≤12(17.02)=8.514.0100 \le \tfrac12(17.02) = 8.51 ✓ and 4.0100≤5.804.0100 \le 5.80 ✓.

    The two Huber branches meet. At ∣r∣=δ=1|r| = \delta = 1 the quadratic branch gives 12(1)2=0.5\tfrac12(1)^2 = 0.5 and the linear branch gives (1)(1−0.5)=0.5(1)(1 - 0.5) = 0.5. Equal, so the function is continuous. Their derivatives also meet: r=1r = 1 against δ=1\delta = 1. Continuity of the derivative is what makes Huber usable by a gradient method, and it is not automatic — it is what the −12δ-\tfrac12\delta term in the linear branch is for.

    MAE’s ordering is preserved. The residual magnitudes ordered 0.2<0.3<0.5<0.8<4.00.2 < 0.3 < 0.5 < 0.8 < 4.0, and the MAE column reproduces that order exactly, since ∣⋅∣|\cdot| is monotone in magnitude. A column out of order would signal a transcription error.

    Units check on the derivative. d(r2)/dr\mathrm{d}(r^2)/\mathrm{d}r has the units of rr; d∣r∣/dr\mathrm{d}|r|/\mathrm{d}r is dimensionless. That is why MSE’s pull grows with the error and MAE’s cannot — a dimensional argument reaching the same conclusion as the arithmetic.

    Where this breaks

    The comparison of shares depends on δ\delta being small relative to the outlier. Set δ=5\delta = 5 and every residual takes the quadratic branch, so Huber becomes exactly 12 \tfrac12\,MSE and its derivative at the outlier becomes 4.04.0, not 1.01.0. Huber is not robust; Huber with a well-chosen δ\delta is robust, and δ\delta has to be set against the scale of the residuals you are willing to treat as signal.

    That scale is not known before training and changes during it, which is the real difficulty. The usual answers are to set δ\delta from a robust spread estimate of the residuals — the median absolute deviation — or to recompute it each epoch. Neither is free, and both are a hyperparameter that MSE does not have.

    Variation

    Replace the outlier 4.04.0 by 40.040.0 and recompute all three means and all three derivatives at that residual. Predict, before computing, which of the three means changes by the largest factor — then check whether your prediction was right, and say what the factor is for each.

    Problem I.4.B02

    Every loss is a negative log-likelihood

    symbolic▲▲△

    Symbolic; constants are tracked explicitly rather than absorbed silently.

    STATEMENT

    Derive squared error as the negative log-likelihood of a Gaussian observation model with fixed variance, and cross-entropy as the negative log-likelihood of a categorical one. Track every constant that appears, and state exactly which ones may be discarded and why.

    GIVEN

    Gaussian model. Observations are generated as yi=f(xi;θ)+εiy_i = f(x_i;\theta) + \varepsilon_i with εi∼N(0,σ2)\varepsilon_i \sim \mathcal{N}(0, \sigma^2) independent, σ2\sigma^2 fixed and not learned. The density is

    p(y∣x,θ)=12πσ2exp⁡ ⁣(−(y−f(x;θ))22σ2)p(y \mid x, \theta) = \frac{1}{\sqrt{2\pi\sigma^{2}}}\exp\!\left(-\frac{(y - f(x;\theta))^{2}}{2\sigma^{2}}\right)

    Categorical model. A prediction is a distribution q=(q1,…,qK)\vec{q} = (q_1, \dots, q_K) on the simplex, the observation is a class c∈{1,…,K}c \in \{1,\dots,K\}, and

    p(c∣x,θ)=∏k=1Kqk yk,yk=1[k=c]p(c \mid x, \theta) = \prod_{k=1}^{K} q_k^{\,y_k}, \qquad y_k = \mathbb{1}[k = c]

    FIND

    −log⁡p(D∣θ)-\log p(\mathcal{D} \mid \theta) for each model, reduced to a loss, with every discarded term named.

    STRATEGY

    Write the likelihood of the whole dataset, take a logarithm to turn the product into a sum, negate, then separate the terms containing θ\theta from those that do not. Only the first group can affect the minimiser, and the second group is where the constants go.

    SOLUTION

    Part 1 — the Gaussian case

    Step 1 — the dataset likelihood. Independence turns a joint density into a product:

    p(D∣θ)=∏i=1np(yi∣xi,θ)=∏i=1n12πσ2exp⁡ ⁣(−ri22σ2)p(\mathcal{D}\mid\theta) = \prod_{i=1}^{n} p(y_i \mid x_i, \theta) = \prod_{i=1}^{n} \frac{1}{\sqrt{2\pi\sigma^{2}}}\exp\!\left(-\frac{r_i^{2}}{2\sigma^{2}}\right)

    writing ri=yi−f(xi;θ)r_i = y_i - f(x_i;\theta) for the ii-th residual.

    Step 2 — take the logarithm. A product becomes a sum, and log⁡(ab)=log⁡a+log⁡b\log(ab) = \log a + \log b splits each factor:

    log⁡p(D∣θ)=∑i=1n[log⁡12πσ2⏟no θ  +  log⁡exp⁡ ⁣(−ri22σ2)]\log p(\mathcal{D}\mid\theta) = \sum_{i=1}^{n}\left[\underbrace{\log \frac{1}{\sqrt{2\pi\sigma^{2}}}}_{\text{no }\theta} \;+\; \log \exp\!\left(-\frac{r_i^{2}}{2\sigma^{2}}\right)\right]

    The exponential and the logarithm are inverses, so the second term simplifies outright:

    =∑i=1n[−12log⁡ ⁣(2πσ2)−ri22σ2]= \sum_{i=1}^{n}\left[-\tfrac12\log\!\left(2\pi\sigma^{2}\right) - \frac{r_i^{2}}{2\sigma^{2}}\right]

    Step 3 — separate. The first term does not depend on ii, so summing it nn times gives a single constant:

    log⁡p(D∣θ)=−n2log⁡ ⁣(2πσ2)  −  12σ2∑i=1nri2\log p(\mathcal{D}\mid\theta) = -\frac{n}{2}\log\!\left(2\pi\sigma^{2}\right) \;-\; \frac{1}{2\sigma^{2}}\sum_{i=1}^{n} r_i^{2}

    Step 4 — negate.

    −log⁡p(D∣θ)=n2log⁡ ⁣(2πσ2)⏟A  +  12σ2⏟B∑i=1nri2-\log p(\mathcal{D}\mid\theta) = \underbrace{\frac{n}{2}\log\!\left(2\pi\sigma^{2}\right)}_{A} \;+\; \underbrace{\frac{1}{2\sigma^{2}}}_{B}\sum_{i=1}^{n} r_i^{2}

    Step 5 — account for AA and BB precisely.

    Term AA is additive and θ\theta-free. Adding a constant to a function shifts its graph vertically and moves no stationary point: ∇θ(g(θ)+A)=∇θg(θ)\nabla_\theta (g(\theta) + A) = \nabla_\theta g(\theta). So AA may be dropped without changing the minimiser or any gradient.

    Term BB is a positive multiplicative constant. Since σ2>0\sigma^2 > 0 we have B>0B > 0, and arg⁡min⁡θ Bg(θ)=arg⁡min⁡θg(θ)\arg\min_\theta\, Bg(\theta) = \arg\min_\theta g(\theta) for any B>0B > 0. So BB may be dropped from the objective. It may not be dropped from the gradient if the learning rate is fixed, because ∇(Bg)=B∇g\nabla(Bg) = B\nabla g — dropping BB rescales every step by 1/B1/B, which is a change of effective learning rate and nothing more.

    Step 6 — conclude.

    arg⁡min⁡θ[−log⁡p(D∣θ)]=arg⁡min⁡θ∑i=1n(yi−f(xi;θ))2\arg\min_{\theta} \left[-\log p(\mathcal{D}\mid\theta)\right] = \arg\min_{\theta} \sum_{i=1}^{n}\big(y_i - f(x_i;\theta)\big)^{2}

    ■\blacksquare Minimising squared error is maximum likelihood under a fixed-variance Gaussian.

    Part 2 — the categorical case

    Step 7 — one example. The indicator exponent means all but one factor is raised to the power zero:

    p(c∣x,θ)=∏k=1Kqk yk=qcp(c\mid x,\theta) = \prod_{k=1}^{K} q_k^{\,y_k} = q_c

    Step 8 — take the logarithm and negate.

    −log⁡p(c∣x,θ)=−log⁡∏kqk yk=−∑k=1Kyklog⁡qk-\log p(c\mid x,\theta) = -\log \prod_{k} q_k^{\,y_k} = -\sum_{k=1}^{K} y_k \log q_k

    using log⁡(ab)=blog⁡a\log(a^b) = b\log a on each factor. The right-hand side is exactly the cross-entropy H(y,q)H(\vec{y}, \vec{q}) of Definition 8.

    Step 9 — the dataset. By independence again,

    −log⁡p(D∣θ)=∑i=1nH(yi,qi)-\log p(\mathcal{D}\mid\theta) = \sum_{i=1}^{n} H(\vec{y}_i, \vec{q}_i)

    ■\blacksquare

    Note the asymmetry with Part 1: there is no constant to discard. The categorical density has no normalising factor outside the probabilities themselves, because ∑kqk=1\sum_k q_k = 1 is built into the parameterisation. Every term of the cross-entropy depends on θ\theta.

    What the correspondence costs

    Reading Steps 1–6 backwards is the uncomfortable direction. If minimising MSE is maximum likelihood under a Gaussian, then choosing MSE asserts a Gaussian, whether or not anyone intended to assert anything. Three properties come with that assertion:

    Symmetry. p(ε)=p(−ε)p(\varepsilon) = p(-\varepsilon), so over-prediction and under-prediction cost the same. False whenever the two have different consequences.

    Constant variance. One σ2\sigma^2 for every xx. False whenever the noise scales with the signal, which is the ordinary situation for counts, prices and concentrations.

    Unbounded support. ε\varepsilon may take any real value, so yy may too. False for anything bounded — a probability, a proportion, a nonnegative count.

    Chapter VII.2 will meet count data where all three fail at once, and will need a negative binomial likelihood instead. The route there is exactly this derivation run forwards with a different density.

    Answer

    −log⁡pGauss(D∣θ)=n2log⁡(2πσ2)+12σ2∑iri2-\log p_{\text{Gauss}}(\mathcal{D}\mid\theta) = \frac{n}{2}\log(2\pi\sigma^{2}) + \frac{1}{2\sigma^{2}}\sum_i r_i^{2}

    The first term is additive and θ\theta-free; the second’s prefactor is a positive constant. Discarding both leaves ∑iri2\sum_i r_i^2, so MSE is Gaussian maximum likelihood.

    −log⁡pcat(D∣θ)=−∑i∑kyiklog⁡qik-\log p_{\text{cat}}(\mathcal{D}\mid\theta) = -\sum_i \sum_k y_{ik}\log q_{ik}

    which is cross-entropy exactly, with no constant to discard.

    Check — sanity

    The Gaussian result reproduces the known optimum. For a constant model f=μf = \mu, minimising ∑(yi−μ)2\sum(y_i - \mu)^2 gives μ=yˉ\mu = \bar{y}, the sample mean — which is the maximum-likelihood estimate of a Gaussian mean. Two routes, one answer.

    Dropping BB is exactly a learning-rate change. With σ2=1\sigma^2 = 1, B=12B = \tfrac12. Training on ∑ri2\sum r_i^2 at rate η\eta and on 12∑ri2\tfrac12\sum r_i^2 at rate 2η2\eta produce identical parameter sequences. This is checkable in three lines of code, and it is why the factor of 12\tfrac12 in front of squared losses is a convention rather than a claim.

    The categorical result reduces to the binary case. At K=2K = 2 with q2=1−q1q_2 = 1 - q_1 and y\vec{y} one-hot, Step 8 becomes −[y1log⁡q1+(1−y1)log⁡(1−q1)]-[y_1\log q_1 + (1-y_1)\log(1-q_1)], which is binary cross-entropy — the identity established in I.1.B04, recovered here as a special case rather than assumed.

    The units are consistent. A log-likelihood is dimensionless (a log of a probability), and so is cross-entropy. But ∑ri2\sum r_i^2 carries the square of yy‘s units — the mismatch is absorbed by 1/(2σ2)1/(2\sigma^2), whose units are the inverse square of yy‘s. Discarding BB therefore discards the dimensional bookkeeping too, which is a small reason MSE values are hard to interpret across problems.

    Where this breaks

    Step 5 discards A=n2log⁡(2πσ2)A = \tfrac{n}{2}\log(2\pi\sigma^2) because it is θ\theta-free. That holds only while σ2\sigma^2 is fixed. Learn the variance — predict σ2(x)\sigma^2(x) as a second output head, as heteroscedastic regression does — and AA becomes 12∑ilog⁡σ2(xi)\tfrac12\sum_i \log \sigma^2(x_i), which depends on θ\theta and cannot be dropped.

    The resulting loss is ∑i[ri22σi2+12log⁡σi2]\sum_i\left[\frac{r_i^2}{2\sigma_i^2} + \tfrac12\log\sigma_i^2\right], and its behaviour is different in kind: the first term rewards predicting a large variance, the second punishes it, and the balance is what makes the model report calibrated uncertainty. Dropping AA there would let the model claim infinite variance everywhere and drive the loss to −∞-\infty. The constant was never inert; it was inert given an assumption.

    Variation

    Derive the loss implied by a Laplace observation model, p(ε)∝exp⁡(−∣ε∣/b)p(\varepsilon) \propto \exp(-|\varepsilon| / b) with bb fixed. Identify which of this chapter’s losses it is, and state what that tells you about when to prefer it.

    Problem I.4.B03

    Why softmax and cross-entropy compose to p − y

    gradient▲▲▲

    All values rounded to 4 d.p.

    STATEMENT

    Derive ∂L/∂z=p−y\partial L/\partial \vec{z} = \vec{p} - \vec{y} for softmax followed by cross-entropy. Do not quote the result: obtain the softmax Jacobian from the quotient rule, apply the chain rule through it in full, and show explicitly which terms cancel and why. Then instantiate the whole calculation on three logits.

    GIVEN

    Logits z∈RK\vec{z} \in \R^{K}, predictions and target

    pi=ezi∑j=1Kezj,L=−∑k=1Kyklog⁡pk,y one-hot at class cp_i = \frac{e^{z_i}}{\sum_{j=1}^{K} e^{z_j}}, \qquad L = -\sum_{k=1}^{K} y_k \log p_k, \qquad \vec{y}\ \text{one-hot at class } c

    For the numeric part, z=(2,1,0)\vec{z} = (2, 1, 0) and c=1c = 1 (the first entry).

    FIND

    ∂pi/∂zj\partial p_i / \partial z_j for all i,ji, j; then ∂L/∂zj\partial L/\partial z_j; then both evaluated at the given logits.

    STRATEGY

    Differentiate softmax by the quotient rule, splitting into the i=ji = j and i≠ji \neq j cases because the numerator depends on zjz_j only in the first. Then push the loss gradient through the Jacobian and use ∑kyk=1\sum_k y_k = 1 — that one identity is what collapses a K×KK \times K matrix product to a subtraction.

    SOLUTION

    Part 1 — the softmax Jacobian

    Step 1 — name the denominator. Let

    S=∑j=1Kezj,sopi=eziSS = \sum_{j=1}^{K} e^{z_j}, \qquad\text{so}\qquad p_i = \frac{e^{z_i}}{S}

    The key observation before any differentiation: SS depends on every logit. So pip_i depends on zjz_j even when i≠ji \neq j — through the denominator alone. That is the whole source of the off-diagonal terms.

    Differentiating SS:

    ∂S∂zj=∂∂zj∑mezm=ezj\frac{\partial S}{\partial z_j} = \frac{\partial}{\partial z_j}\sum_{m} e^{z_m} = e^{z_j}

    since every term but the jj-th is constant in zjz_j.

    Step 2 — the diagonal case, i=ji = j. Apply the quotient rule (uv)′=u′v−uv′v2\left(\frac{u}{v}\right)' = \frac{u'v - uv'}{v^2} with u=eziu = e^{z_i} and v=Sv = S. Here u′=eziu' = e^{z_i} and v′=eziv' = e^{z_i}:

    ∂pi∂zi=ezi S−ezi eziS2\frac{\partial p_i}{\partial z_i} = \frac{e^{z_i}\,S - e^{z_i}\,e^{z_i}}{S^{2}}

    Split the fraction into two, so each piece becomes a pp:

    =eziSS2−ezieziS2=eziS−eziS⋅eziS=pi−pi2=pi(1−pi)= \frac{e^{z_i}S}{S^{2}} - \frac{e^{z_i}e^{z_i}}{S^{2}} = \frac{e^{z_i}}{S} - \frac{e^{z_i}}{S}\cdot\frac{e^{z_i}}{S} = p_i - p_i^{2} = p_i(1 - p_i)

    Step 3 — the off-diagonal case, i≠ji \neq j. Now u=eziu = e^{z_i} does not depend on zjz_j, so u′=0u' = 0 and only the denominator contributes:

    ∂pi∂zj=0⋅S−eziezjS2=−eziS⋅ezjS=−pipj\frac{\partial p_i}{\partial z_j} = \frac{0\cdot S - e^{z_i}e^{z_j}}{S^{2}} = -\frac{e^{z_i}}{S}\cdot\frac{e^{z_j}}{S} = -p_i p_j

    Step 4 — combine. Using the Kronecker delta δij=1\delta_{ij} = 1 if i=ji=j and 00 otherwise, the two cases are one formula:

    ∂pi∂zj=pi(δij−pj)\frac{\partial p_i}{\partial z_j} = p_i\left(\delta_{ij} - p_j\right)

    This is the softmax Jacobian of The softmax Jacobian 0.MC.06, derived here rather than cited, because the two cancellations that follow depend on knowing where each factor came from.

    Check it reproduces both branches: at i=ji=j, pi(1−pi)p_i(1 - p_i) ✓; at i≠ji \ne j, pi(0−pj)=−pipjp_i(0 - p_j) = -p_ip_j ✓.

    Part 2 — the chain rule through it

    Step 5 — differentiate the loss with respect to the probabilities.

    ∂L∂pi=∂∂pi(−∑kyklog⁡pk)=−yipi\frac{\partial L}{\partial p_i} = \frac{\partial}{\partial p_i}\left(-\sum_k y_k \log p_k\right) = -\frac{y_i}{p_i}

    only the k=ik = i term surviving.

    Step 6 — assemble. The chain rule for a vector-to-vector map sums over the intermediate index (The chain rule 0.MC.03):

    ∂L∂zj=∑i=1K∂L∂pi ∂pi∂zj=∑i=1K(−yipi)pi(δij−pj)\frac{\partial L}{\partial z_j} = \sum_{i=1}^{K} \frac{\partial L}{\partial p_i}\,\frac{\partial p_i}{\partial z_j} = \sum_{i=1}^{K} \left(-\frac{y_i}{p_i}\right) p_i\left(\delta_{ij} - p_j\right)

    Step 7 — the first cancellation. The factor pip_i from the Jacobian meets the 1/pi1/p_i from the loss and they cancel exactly:

    =−∑i=1Kyi(δij−pj)= -\sum_{i=1}^{K} y_i\left(\delta_{ij} - p_j\right)

    This is the step that makes the whole thing work, and it is why softmax and cross-entropy are paired rather than chosen independently. Had the loss been anything but a logarithm, the 1/pi1/p_i would not have appeared and nothing would cancel — which is exactly what problem I.4.B06 shows happening with MSE.

    Step 8 — expand the bracket and use ∑iyi=1\sum_i y_i = 1.

    =−∑iyiδij+∑iyipj= -\sum_{i} y_i \delta_{ij} + \sum_{i} y_i p_j

    The first sum has exactly one non-zero term, at i=ji = j, giving yjy_j. In the second, pjp_j does not depend on ii, so it factors out:

    =−yj+pj∑iyi⏟= 1=pj−yj= -y_j + p_j \underbrace{\sum_{i} y_i}_{=\,1} = p_j - y_j ∂L∂z=p−y (I.4.4)\boxed{\ \frac{\partial L}{\partial \vec{z}} = \vec{p} - \vec{y}\ } \tag{I.4.4}

    ■\blacksquare

    Where each hypothesis was used. Step 7 needed the loss to be logarithmic. Step 8 needed y\vec{y} to sum to one — note it did not need y\vec{y} to be one-hot, so the result holds for soft targets and therefore for label smoothing unchanged. That is worth recording, because it is often stated as requiring one-hot labels and does not.

    Part 3 — the numbers

    Step 9 — softmax at z=(2,1,0)\vec{z} = (2,1,0). Subtract the maximum first, which changes nothing and prevents overflow (Log-sum-exp 0.NU.02):

    e2−2=1.000000,e1−2=0.367879,e0−2=0.135335e^{2-2} = 1.000000, \qquad e^{1-2} = 0.367879, \qquad e^{0-2} = 0.135335

    S=1.000000+0.367879+0.135335=1.503215S = 1.000000 + 0.367879 + 0.135335 = 1.503215

    p1=1.0000001.503215=0.6652,p2=0.3678791.503215=0.2447,p3=0.1353351.503215=0.0900p_1 = \frac{1.000000}{1.503215} = 0.6652, \quad p_2 = \frac{0.367879}{1.503215} = 0.2447, \quad p_3 = \frac{0.135335}{1.503215} = 0.0900

    Sum: 0.6652+0.2447+0.0900=0.9999≈10.6652 + 0.2447 + 0.0900 = 0.9999 \approx 1 ✓ (the last digit is rounding).

    Step 10 — the loss. y=(1,0,0)\vec{y} = (1,0,0), so

    L=−log⁡p1=−log⁡0.6652=0.4076 natsL = -\log p_1 = -\log 0.6652 = 0.4076 \text{ nats}

    Step 11 — the full Jacobian, entry by entry. Using pi(δij−pj)p_i(\delta_{ij} - p_j):

    ∂p1∂z1=0.6652(1−0.6652)=0.6652×0.3348=0.2227\frac{\partial p_1}{\partial z_1} = 0.6652(1 - 0.6652) = 0.6652 \times 0.3348 = 0.2227∂p1∂z2=−0.6652×0.2447=−0.1628\frac{\partial p_1}{\partial z_2} = -0.6652 \times 0.2447 = -0.1628∂p2∂z2=0.2447(1−0.2447)=0.2447×0.7553=0.1848\frac{\partial p_2}{\partial z_2} = 0.2447(1 - 0.2447) = 0.2447 \times 0.7553 = 0.1848

    and so on, giving

    J=[+0.2227−0.1628−0.0599−0.1628+0.1848−0.0220−0.0599−0.0220+0.0819]\mat{J} = \begin{bmatrix} +0.2227 & -0.1628 & -0.0599\\ -0.1628 & +0.1848 & -0.0220\\ -0.0599 & -0.0220 & +0.0819 \end{bmatrix}

    Step 12 — the long route, to confirm the short one. ∂L/∂p=(−1/0.6652, 0, 0)=(−1.5032, 0, 0)\partial L/\partial \vec{p} = (-1/0.6652,\ 0,\ 0) = (-1.5032,\ 0,\ 0). Multiplying by the Jacobian, only the first row contributes:

    ∂L∂z1=(−1.5032)(0.2227)=−0.3348\frac{\partial L}{\partial z_1} = (-1.5032)(0.2227) = -0.3348∂L∂z2=(−1.5032)(−0.1628)=+0.2447\frac{\partial L}{\partial z_2} = (-1.5032)(-0.1628) = +0.2447∂L∂z3=(−1.5032)(−0.0599)=+0.0900\frac{\partial L}{\partial z_3} = (-1.5032)(-0.0599) = +0.0900

    Step 13 — the short route.

    p−y=(0.6652−1, 0.2447−0, 0.0900−0)=(−0.3348, +0.2447, +0.0900)\vec{p} - \vec{y} = (0.6652 - 1,\ 0.2447 - 0,\ 0.0900 - 0) = (-0.3348,\ +0.2447,\ +0.0900)

    Identical to Step 12, entry for entry.

    Answer

    ∂pi∂zj=pi(δij−pj),∂L∂z=p−y\frac{\partial p_i}{\partial z_j} = p_i(\delta_{ij} - p_j), \qquad \frac{\partial L}{\partial \vec{z}} = \vec{p} - \vec{y}

    At z=(2,1,0)\vec{z} = (2,1,0) with the true class first: p=(0.6652,0.2447,0.0900)\vec{p} = (0.6652, 0.2447, 0.0900), L=0.4076L = 0.4076 nats, and

    ∂L∂z=(−0.3348, +0.2447, +0.0900)\frac{\partial L}{\partial \vec{z}} = (-0.3348,\ +0.2447,\ +0.0900)

    a dimensionless vector of length KK, summing to zero.

    Check — numeric · i-4-b03-softmax-ce-gradient.py
    J = [[p[i] * ((1.0 if i == j else 0.0) - p[j]) for j in range(3)] for i in range(3)]
    dL_dp = [-(y[k] / p[k]) for k in range(3)]
    dL_dz = [sum(dL_dp[i] * J[i][j] for i in range(3)) for j in range(3)]

    The snippet computes the gradient twice — once through the full Jacobian and once as p−y\vec{p} - \vec{y} — and prints agreement: True. That is the point of running it: the two routes are independent, so agreement is evidence rather than restatement.

    Executed in CI. The digits above are the digits it printed.

    Check — sanity

    The gradient sums to zero. −0.3348+0.2447+0.0900=−0.0001≈0-0.3348 + 0.2447 + 0.0900 = -0.0001 \approx 0. This must hold: softmax is invariant to adding a constant λ\lambda to every logit, so the directional derivative along (1,1,…,1)(1,1,\dots,1) is zero, which is exactly ∑j∂L/∂zj=0\sum_j \partial L/\partial z_j = 0. A gradient not summing to zero means an arithmetic slip.

    The signs are right. The true class has a negative gradient, so gradient descent raises its logit; every other class has a positive gradient, so their logits are lowered. That is the behaviour the loss should produce, read directly off the sign pattern.

    The magnitudes are bounded. Every entry of p−y\vec{p} - \vec{y} lies in [−1,1][-1, 1], since pj∈(0,1)p_j \in (0,1) and yj∈{0,1}y_j \in \{0,1\}. The gradient can never explode, whatever the logits. Contrast with the MSE-through-sigmoid gradient of I.4.B06, which is bounded too — but by a number that shrinks to zero exactly when it is needed.

    The Jacobian is symmetric with zero row sums. J12=J21=−0.1628J_{12} = J_{21} = -0.1628, and 0.2227−0.1628−0.0599=0.00000.2227 - 0.1628 - 0.0599 = 0.0000. Both properties follow from the formula: pi(δij−pj)p_i(\delta_{ij} - p_j) is symmetric because pipjp_ip_j is, and rows sum to pi(1−∑jpj)=pi(1−1)=0p_i(1 - \sum_j p_j) = p_i(1-1) = 0.

    Where this breaks

    The clean result needs softmax and cross-entropy to be fused. Computing p\vec{p} first, storing it, and then computing −log⁡pc-\log p_c gives the same number but a worse computation: when pcp_c underflows to 00 the logarithm is −∞-\infty, and the 1/pi1/p_i in Step 5 is a division by zero even though the final answer p−y\vec{p}-\vec{y} is perfectly well behaved.

    This is why every framework has a single cross_entropy(logits, target) rather than a softmax followed by a log — the fused version computes zc−log⁡∑jezjz_c - \log\sum_j e^{z_j} directly via log-sum-exp and never forms the intermediate that overflows. The mathematics is identical; the arithmetic is not, and I.4.B04 makes the same point for the binary case in detail.

    Variation

    Redo Steps 5–8 with a label-smoothed target y′=(1−ε)y+ε/K\vec{y}' = (1-\varepsilon)\vec{y} + \varepsilon/K. Verify the derivation still goes through, state the resulting gradient, and find the logit gap at which it vanishes for ε=0.1\varepsilon = 0.1, K=3K = 3.

    Problem I.4.B04

    The same loss, computed where the arithmetic survives

    numeric▲▲△

    6 d.p. where precision is the subject; otherwise 4 d.p.

    STATEMENT

    Evaluate binary cross-entropy at four logits by two routes: the naive one that forms a probability first, and the stable identity that never does. Derive the identity, show the naive route failing on two ordinary inputs, and state the logit at which each failure begins.

    GIVEN

    A logit z∈Rz \in \R, a label y∈{0,1}y \in \{0,1\}, and p=σ(z)=1/(1+e−z)p = \sigma(z) = 1/(1+e^{-z}). The naive computation is

    BCEnaive=−[ ylog⁡p+(1−y)log⁡(1−p) ]\mathrm{BCE}_{\text{naive}} = -\big[\,y\log p + (1-y)\log(1-p)\,\big]

    Test at (z,y)∈{(2,1), (0,1), (−5,1), (−50,1), (−800,1), (800,0)}(z, y) \in \{(2,1),\ (0,1),\ (-5,1),\ (-50,1),\ (-800,1),\ (800,0)\}. IEEE double precision: exe^{x} overflows for x>709.78x > 709.78, and σ(z)\sigma(z) rounds to exactly 1.01.0 once e−z<2−53≈1.11×10−16e^{-z} < 2^{-53} \approx 1.11\times10^{-16}.

    FIND

    The stable identity; both routes’ values at each test point; and the two thresholds at which the naive route breaks.

    STRATEGY

    Derive the identity by substituting σ\sigma into the definition and simplifying until no probability appears — only zz and a logarithm of something safely near one. Then evaluate both routes and watch where they part.

    SOLUTION

    Part 1 — deriving the stable form

    Step 1 — substitute for y=1y = 1. With p=1/(1+e−z)p = 1/(1+e^{-z}):

    −log⁡p=−log⁡11+e−z=log⁡(1+e−z)-\log p = -\log\frac{1}{1+e^{-z}} = \log\left(1 + e^{-z}\right)

    using −log⁡(1/a)=log⁡a-\log(1/a) = \log a.

    Step 2 — substitute for y=0y = 0. First simplify 1−p1 - p:

    1−p=1−11+e−z=(1+e−z)−11+e−z=e−z1+e−z1 - p = 1 - \frac{1}{1+e^{-z}} = \frac{(1+e^{-z}) - 1}{1+e^{-z}} = \frac{e^{-z}}{1+e^{-z}}

    so

    −log⁡(1−p)=−log⁡e−z+log⁡(1+e−z)=z+log⁡(1+e−z)-\log(1-p) = -\log e^{-z} + \log\left(1+e^{-z}\right) = z + \log\left(1+e^{-z}\right)

    Step 3 — one formula for both. Combining Steps 1 and 2:

    BCE(z,y)=−zy+z(1−y)⋅0+…\mathrm{BCE}(z,y) = -zy + z(1-y)\cdot 0 + \dots

    More carefully — write the two cases and look for the pattern:

    BCE={log⁡(1+e−z)y=1z+log⁡(1+e−z)y=0  =  z(1−y)+log⁡ ⁣(1+e−z)\mathrm{BCE} = \begin{cases} \log(1+e^{-z}) & y = 1\\ z + \log(1+e^{-z}) & y = 0 \end{cases} \;=\; z(1-y) + \log\!\left(1+e^{-z}\right)

    Step 4 — the remaining danger. This is exact, but e−ze^{-z} still overflows for z<−709.78z < -709.78. Fix it by pulling out the larger of the two terms inside the logarithm. For z<0z < 0 write 1+e−z=e−z(1+ez)1 + e^{-z} = e^{-z}(1 + e^{z}), so

    log⁡(1+e−z)=−z+log⁡(1+ez)\log(1+e^{-z}) = -z + \log(1+e^{z})

    Substituting into Step 3’s formula for z<0z < 0 and combining with the z≥0z \ge 0 case gives the symmetric form

     BCE(z,y)=max⁡(z,0)−zy+log⁡ ⁣(1+e−∣z∣) (I.4.5)\boxed{\ \mathrm{BCE}(z,y) = \max(z,0) - zy + \log\!\left(1 + e^{-|z|}\right)\ } \tag{I.4.5}

    Why this one is safe. The exponential’s argument is −∣z∣≤0-|z| \le 0, so e−∣z∣∈(0,1]e^{-|z|} \in (0, 1] and can never overflow. It can underflow to 00, but then log⁡(1+0)=0\log(1+0) = 0 exactly, which is the correct limit rather than an error. Every other term is elementary arithmetic on zz itself.

    Part 2 — the two routes side by side

    zzyyσ(z)\sigma(z)naivestable
    2.02.0118.807971e−18.807971\mathrm{e}{-1}0.1269280.1269280.1269280.126928
    0.00.0115.000000e−15.000000\mathrm{e}{-1}0.6931470.6931470.6931470.693147
    −5.0-5.0116.692851e−36.692851\mathrm{e}{-3}5.0067155.0067155.0067155.006715
    −50.0-50.0111.928750e−221.928750\mathrm{e}{-22}50.00000050.00000050.00000050.000000
    −800.0-800.011overflowOverflowError800.000000800.000000
    800.0800.0001.000000e+01.000000\mathrm{e}{+0}ValueError800.000000800.000000

    Step 5 — verifying agreement where both work. At the three safe points the two routes agree to ten decimal places, with ∣diff∣≤2.78×10−17|{\text{diff}}| \le 2.78\times10^{-17} — one unit in the last place of a double. So (I.4.5) is not an approximation; it is the same number computed differently.

    Step 6 — the first failure, z=−800z = -800, y=1y = 1. The naive route needs σ(−800)=1/(1+e800)\sigma(-800) = 1/(1 + e^{800}). But e800e^{800} exceeds the largest double (1.798×103081.798\times10^{308}) and overflows, raising OverflowError before any logarithm is reached.

    The stable route computes

    max⁡(−800,0)−(−800)(1)+log⁡ ⁣(1+e−800)=0+800+log⁡(1)=800.000000\max(-800, 0) - (-800)(1) + \log\!\left(1 + e^{-800}\right) = 0 + 800 + \log(1) = 800.000000

    which is correct: a logit of −800-800 with target 11 is wrong by 800800 nats.

    Step 7 — the second failure, z=800z = 800, y=0y = 0. Here e−800e^{-800} underflows to 00, so σ(800)\sigma(800) evaluates to exactly 1.01.0. The naive route then needs log⁡(1−1.0)=log⁡(0)=−∞\log(1 - 1.0) = \log(0) = -\infty, and Python raises ValueError. In a framework that returns −∞-\infty silently instead, the loss becomes inf, every gradient becomes nan, and the entire model is destroyed in one step with no message.

    The stable route gives max⁡(800,0)−(800)(0)+log⁡(1+e−800)=800+0=800.000000\max(800,0) - (800)(0) + \log(1+e^{-800}) = 800 + 0 = 800.000000.

    Step 8 — the thresholds.

    Overflow. e−ze^{-z} overflows when −z>709.78-z > 709.78, so the naive route fails for z<−709.78z < -709.78.

    Rounding to one. σ(z)\sigma(z) becomes exactly 1.01.0 once e−ze^{-z} falls below the spacing of doubles near 11, that is e−z<2−53e^{-z} < 2^{-53}, giving z>53ln⁡2=36.74z > 53\ln 2 = 36.74. This is the more dangerous of the two, because z=37z = 37 is an entirely ordinary logit — it appears whenever a model becomes confident — and the failure is a silent −∞-\infty rather than a raised exception.

    In float32 the corresponding threshold is z>24ln⁡2=16.6z > 24\ln 2 = 16.6, which is reached routinely within the first epoch of ordinary training.

    Answer

    BCE(z,y)=max⁡(z,0)−zy+log⁡ ⁣(1+e−∣z∣)\mathrm{BCE}(z,y) = \max(z,0) - zy + \log\!\left(1+e^{-|z|}\right)

    Both routes agree to within 2.78×10−172.78\times10^{-17} where the naive one works, and it fails at z=−800z = -800 (overflow) and z=800z = 800 (log of zero), where the stable form returns 800.000000800.000000 in both cases.

    Thresholds in double precision: overflow below z=−709.78z = -709.78; silent saturation to p=1p = 1 above z=36.74z = 36.74. In float32 the second is z=16.6z = 16.6.

    Check — numeric · i-4-b04-bce-in-logit-space.py
    def bce_stable(z, y):
        return max(z, 0.0) - z * y + log(1.0 + exp(-abs(z)))

    Prints the six-row table with both routes, the two exception names, and the ten-digit agreement check on the safe points.

    Executed in CI. The digits above are the digits it printed.

    Check — sanity

    The identity gives the right answer at z=0z = 0. There p=0.5p = 0.5 and the loss should be −log⁡0.5=log⁡2=0.693147-\log 0.5 = \log 2 = 0.693147. The formula gives max⁡(0,0)−0+log⁡(1+e0)=log⁡2\max(0,0) - 0 + \log(1+e^{0}) = \log 2 ✓.

    Large-∣z∣|z| behaviour is linear, as it must be. For z→−∞z \to -\infty with y=1y=1, −log⁡σ(z)=log⁡(1+e−z)≈−z-\log\sigma(z) = \log(1+e^{-z}) \approx -z. The table confirms it: z=−50⇒50.000000z = -50 \Rightarrow 50.000000 and z=−800⇒800.000000z = -800 \Rightarrow 800.000000, both equal to ∣z∣|z| to six decimals. A loss growing linearly rather than exponentially in the logit is exactly why cross-entropy’s gradient stays bounded.

    The two failures are the two ends of the same problem. Underflow of e−∣z∣e^{-|z|} is harmless — log⁡(1+0)=0\log(1+0) = 0 is correct. Overflow of e+∣z∣e^{+|z|} is fatal. The identity’s whole content is arranging that only the harmless one can occur.

    Symmetry check. BCE(z,1)=BCE(−z,0)\mathrm{BCE}(z, 1) = \mathrm{BCE}(-z, 0): predicting logit zz for a positive should cost the same as predicting −z-z for a negative. From the formula at z=2z = 2: BCE(2,1)=2−2+log⁡(1+e−2)=0.126928\mathrm{BCE}(2,1) = 2 - 2 + \log(1+e^{-2}) = 0.126928 and BCE(−2,0)=0−0+log⁡(1+e−2)=0.126928\mathrm{BCE}(-2,0) = 0 - 0 + \log(1+e^{-2}) = 0.126928 ✓.

    Where this breaks

    The identity is exact in exact arithmetic and nearly exact in floating point — the 2.78×10−172.78\times10^{-17} discrepancy is real, not a display artefact. It comes from log⁡(1+x)\log(1+x) losing precision when xx is tiny: the addition 1+x1 + x discards most of xx‘s bits before the logarithm sees it.

    The remedy is log1p(x), which computes log⁡(1+x)\log(1+x) accurately for small xx by a series expansion rather than by forming the sum. Every serious implementation uses it. The point generalises: this problem removed one catastrophic failure and left a benign one, and knowing which is which is the actual skill (Catastrophic cancellation 0.NU.04).

    Variation

    Derive the analogous stable form for the multi-class case, L=−zc+log⁡∑jezjL = -z_c + \log\sum_j e^{z_j}, and show that subtracting max⁡jzj\max_j z_j from every logit leaves it unchanged. Then evaluate at z=(1000,999,998)\vec{z} = (1000, 999, 998) with c=1c = 1, where the naive route overflows.

    Problem I.4.B05

    Weights that equalise what each class contributes

    probability▲▲△

    Weights to 4 d.p.; masses to 1 d.p.

    STATEMENT

    A binary dataset holds 950950 negatives and 5050 positives. Derive the class weights that make the two classes contribute equal gradient mass, compute them, verify the loss scale is unchanged, and compare with the effective-number weighting of Cui et al. (2019).

    GIVEN

    n−=950n_- = 950, n+=50n_+ = 50, so N=1000N = 1000 and K=2K = 2. The weighted empirical risk is

    R^(θ)=1N∑i=1Nwc(i)  ℓ(f(xi;θ),yi)\hat{R}(\theta) = \frac{1}{N}\sum_{i=1}^{N} w_{c(i)}\;\ell\big(f(x_i;\theta), y_i\big)

    where c(i)c(i) is example ii‘s class. Assume each example’s loss has comparable magnitude, so that a class’s contribution is proportional to its count times its weight.

    FIND

    Weights w−w_- and w+w_+ equalising the two contributions; their ratio; a check that the mean weight is 11; and the same quantities under effective-number weighting at β=0.999\beta = 0.999.

    STRATEGY

    Write the condition “the two classes contribute equally” as one equation, add the normalisation “the average weight is one” as a second, and solve the pair. Two conditions, two unknowns — the weights are then determined, not chosen.

    SOLUTION

    Step 1 — the unweighted imbalance. Without weights, class cc contributes ncn_c of the NN terms, so its share of the gradient is

    n−N=9501000=95%,n+N=501000=5%\frac{n_-}{N} = \frac{950}{1000} = 95\%, \qquad \frac{n_+}{N} = \frac{50}{1000} = 5\%

    The negatives outvote the positives nineteen to one. A model that predicts “negative” always achieves 95%95\% accuracy and a low loss, and the gradient pushing it away from that solution is one-nineteenth of the gradient holding it there.

    Step 2 — the equalisation condition. Class cc‘s weighted contribution is ncwcn_c w_c. Requiring the two to be equal:

    n_- w_- = n_+ w_+ \tag{i}

    Step 3 — the normalisation condition. Requiring the mean weight over the dataset to be 11, so the weighted loss has the same scale as the unweighted one and the learning rate need not be retuned:

    \frac{1}{N}\sum_{i=1}^{N} w_{c(i)} = \frac{n_- w_- + n_+ w_+}{N} = 1 \tag{ii}

    Step 4 — solve. Substitute (i) into (ii). Writing MM for the common value n−w−=n+w+n_-w_- = n_+w_+:

    M+MN=1⟹2M=N⟹M=N2\frac{M + M}{N} = 1 \quad\Longrightarrow\quad 2M = N \quad\Longrightarrow\quad M = \frac{N}{2}

    Then from ncwc=Mn_c w_c = M for each class,

     wc=NK nc (I.4.6)\boxed{\ w_c = \frac{N}{K\,n_c}\ } \tag{I.4.6}

    with K=2K = 2 classes. Note the derivation generalises unchanged to KK classes: KK equal contributions summing to NN gives M=N/KM = N/K.

    Step 5 — evaluate.

    w−=10002×950=10001900=0.5263w_- = \frac{1000}{2 \times 950} = \frac{1000}{1900} = 0.5263w+=10002×50=1000100=10.0000w_+ = \frac{1000}{2 \times 50} = \frac{1000}{100} = 10.0000w+w−=10.00000.5263=19.0000\frac{w_+}{w_-} = \frac{10.0000}{0.5263} = 19.0000

    The ratio equals the imbalance ratio, 950/50=19950/50 = 19, which it must: dividing (i) by n+w−n_+w_- gives w+/w−=n−/n+w_+/w_- = n_-/n_+ directly.

    Step 6 — check both conditions.

    Equal contributions. n−w−=950×0.5263=500.0n_-w_- = 950 \times 0.5263 = 500.0 and n+w+=50×10.0000=500.0n_+w_+ = 50 \times 10.0000 = 500.0. Equal ✓

    Unit mean weight. (500.0+500.0)/1000=1.0000(500.0 + 500.0)/1000 = 1.0000 ✓ — so a loss of 0.50.5 before weighting is a loss of about 0.50.5 after, and the learning rate carries over.

    Step 7 — effective-number weighting. The inverse-frequency weight assumes each example contributes independent information. Cui et al. argue that examples of the same class overlap, so the nn-th example of a class adds less than the first. Modelling the effective number of examples as a geometric sum,

    En=1−β n1−β,and weighting wc∝1Enc=1−β1−β ncE_n = \frac{1 - \beta^{\,n}}{1 - \beta}, \qquad\text{and weighting } w_c \propto \frac{1}{E_{n_c}} = \frac{1-\beta}{1-\beta^{\,n_c}}

    The parameter β∈[0,1)\beta \in [0,1) says how fast the overlap sets in: β=0\beta = 0 gives En=1E_n = 1 for all nn (every example redundant beyond the first, so uniform weights), and β→1\beta \to 1 gives En→nE_n \to n (no overlap, recovering inverse frequency).

    At β=0.999\beta = 0.999:

    β950=0.999950=0.3873⟹1−β1−β950=0.0010.6127=1.630144×10−3\beta^{950} = 0.999^{950} = 0.3873 \quad\Longrightarrow\quad \frac{1-\beta}{1-\beta^{950}} = \frac{0.001}{0.6127} = 1.630144\times10^{-3}β50=0.99950=0.9512⟹1−β1−β50=0.0010.0488=2.049417×10−2\beta^{50} = 0.999^{50} = 0.9512 \quad\Longrightarrow\quad \frac{1-\beta}{1-\beta^{50}} = \frac{0.001}{0.0488} = 2.049417\times10^{-2}

    Normalising so the two average to 11 across classes:

    w−=0.1474,w+=1.8526,w+w−=12.5720w_- = 0.1474, \qquad w_+ = 1.8526, \qquad \frac{w_+}{w_-} = 12.5720

    Step 8 — compare.

    Schemew−w_-w+w_+ratio
    none1.00001.00001.00001.00001.001.00
    inverse frequency0.52630.526310.000010.000019.0019.00
    effective number, β=0.999\beta = 0.9990.14740.14741.85261.852612.5712.57

    Effective-number weighting is less aggressive: 12.5712.57 against 1919. Its argument is that the 950950 negatives are not 950950 independent facts, so down-weighting them to one-nineteenth over-corrects. Whether that is right is an empirical question about the data, and β\beta is the knob that encodes the answer.

    Answer

    wc=NKnc⟹w−=0.5263,w+=10.0000,w+w−=19w_c = \frac{N}{K n_c} \quad\Longrightarrow\quad w_- = 0.5263,\qquad w_+ = 10.0000,\qquad \frac{w_+}{w_-} = 19

    Each class then contributes 500.0500.0 of weighted mass, and the mean weight is exactly 1.00001.0000, so the loss scale is preserved.

    Effective-number weighting at β=0.999\beta = 0.999 gives w−=0.1474w_- = 0.1474, w+=1.8526w_+ = 1.8526, a ratio of 12.572012.5720 — a deliberately weaker correction.

    Check — numeric · i-4-b05-class-weights.py
    w_neg = N / (K * n_neg)
    w_pos = N / (K * n_pos)
    eff = lambda n: (1 - beta) / (1 - beta ** n)

    Prints both schemes, the two weighted masses, the mean weight and both ratios.

    Executed in CI. The digits above are the digits it printed.

    Check — sanity

    A balanced dataset gives unit weights. With n−=n+=500n_- = n_+ = 500, wc=1000/(2×500)=1w_c = 1000/(2 \times 500) = 1 for both. A weighting scheme that changed anything on balanced data would be wrong, and this one does not.

    The ratio is forced by the counts alone. w+/w−=n−/n+=19w_+/w_- = n_-/n_+ = 19 follows from (i) without reference to NN or KK. So the ratio is a property of the imbalance and the scale is a property of the normalisation — two independent choices that are easy to confuse.

    The two limits of β\beta behave. At β=0\beta = 0: En=1E_n = 1 for every nn, so both weights are equal and the ratio is 11 — no correction. As β→1\beta \to 1: En→nE_n \to n by L’Hôpital, so wc∝1/ncw_c \propto 1/n_c and the ratio approaches 1919 — inverse frequency. The computed 12.5712.57 lies between 11 and 1919 as it must.

    Dimensional check. N/(Knc)N/(Kn_c) is a count over a count, so weights are dimensionless and the weighted loss carries the loss’s own units. A weighting scheme with units would be a rescaling in disguise.

    Where this breaks

    Step 2’s premise is that a class’s gradient contribution is proportional to its count. That holds when every example’s loss has comparable magnitude — true at initialisation, and false soon after.

    Once the model has learned to classify the majority easily, those 950950 examples have small losses and, by (I.4.4), small gradients p−yp - y. Their actual contribution collapses well below 95%95\%, and the fixed weight w−=0.5263w_- = 0.5263 keeps suppressing them anyway. Static weights correct a static imbalance in a dynamic quantity.

    That observation is precisely the argument for focal loss (Lin et al., 2017), which multiplies each example’s loss by (1−pt)γ(1 - p_t)^{\gamma} — a factor computed from the current prediction rather than from the class count. It down-weights easy examples whichever class they belong to, and needs no counts at all.

    Variation

    A three-class problem has counts (900,90,10)(900, 90, 10). Compute the inverse-frequency weights and verify each class contributes N/3N/3. Then find the β\beta at which effective-number weighting gives the rarest class exactly half the weight inverse frequency would give it.

    Problem I.4.B06

    Where squared loss stops sending a gradient

    counterexample▲▲△

    Gradients in scientific notation to 6 s.f.; ratios to 1 d.p.

    STATEMENT

    Construct a classification case in which squared loss produces a vanishing gradient and cross-entropy does not. Derive both gradients with respect to the logit, evaluate them at five logits, and identify precisely which factor is responsible.

    GIVEN

    A binary classifier emitting a logit zz, with p=σ(z)p = \sigma(z) and target y=1y = 1. Two candidate losses:

    LMSE=12(p−y)2,LBCE=−[ylog⁡p+(1−y)log⁡(1−p)]L_{\text{MSE}} = \tfrac12 (p - y)^{2}, \qquad L_{\text{BCE}} = -\big[y\log p + (1-y)\log(1-p)\big]

    Recall σ′(z)=σ(z)(1−σ(z))=p(1−p)\sigma'(z) = \sigma(z)\big(1-\sigma(z)\big) = p(1-p) from I.3.B02.

    FIND

    dL/dz\mathrm{d}L/\mathrm{d}z for each loss in closed form; both evaluated at z∈{−1,−3,−5,−10,−20}z \in \{-1, -3, -5, -10, -20\}; and their ratio.

    STRATEGY

    Differentiate each loss with respect to pp, then apply the chain rule through σ\sigma. The whole result turns on whether the σ′(z)\sigma'(z) factor survives or cancels, so keep it visible rather than simplifying early.

    SOLUTION

    Step 1 — MSE’s gradient. Differentiating with respect to pp first:

    ∂LMSE∂p=∂∂p 12(p−y)2=(p−y)\frac{\partial L_{\text{MSE}}}{\partial p} = \frac{\partial}{\partial p}\,\tfrac12 (p-y)^2 = (p - y)

    Then the chain rule through the sigmoid (The chain rule 0.MC.03):

    dLMSEdz=∂LMSE∂p⋅dpdz=(p−y) p(1−p)⏟σ′(z)(a)\frac{\mathrm{d}L_{\text{MSE}}}{\mathrm{d}z} = \frac{\partial L_{\text{MSE}}}{\partial p}\cdot\frac{\mathrm{d}p}{\mathrm{d}z} = (p - y)\,\underbrace{p(1-p)}_{\sigma'(z)} \tag{a}

    The factor σ′(z)\sigma'(z) is present, and it is the problem. Chapter I.3 established that σ′≤1/4\sigma' \le 1/4 always, and that it collapses toward zero as ∣z∣|z| grows.

    Step 2 — BCE’s gradient. Differentiating with respect to pp:

    ∂LBCE∂p=−[yp−1−y1−p]=p−yp(1−p)\frac{\partial L_{\text{BCE}}}{\partial p} = -\left[\frac{y}{p} - \frac{1-y}{1-p}\right] = \frac{p - y}{p(1-p)}

    To see the last equality, put the bracket over a common denominator:

    yp−1−y1−p=y(1−p)−p(1−y)p(1−p)=y−yp−p+pyp(1−p)=y−pp(1−p)\frac{y}{p} - \frac{1-y}{1-p} = \frac{y(1-p) - p(1-y)}{p(1-p)} = \frac{y - yp - p + py}{p(1-p)} = \frac{y - p}{p(1-p)}

    and negating gives (p−y)/[p(1−p)](p-y)/[p(1-p)].

    Now the chain rule:

    dLBCEdz=p−yp(1−p)⋅p(1−p)=p−y(b)\frac{\mathrm{d}L_{\text{BCE}}}{\mathrm{d}z} = \frac{p-y}{p(1-p)}\cdot p(1-p) = p - y \tag{b}

    The σ′\sigma' factor cancelled exactly. The logarithm in the loss produced a 1/[p(1−p)]1/[p(1-p)] that met the p(1−p)p(1-p) from the sigmoid. This is the same cancellation as I.4.B03’s Step 7, in the binary case.

    Step 3 — compare the two closed forms.

    dLMSEdz=(p−y) σ′(z),dLBCEdz=(p−y)\frac{\mathrm{d}L_{\text{MSE}}}{\mathrm{d}z} = (p-y)\,\sigma'(z), \qquad \frac{\mathrm{d}L_{\text{BCE}}}{\mathrm{d}z} = (p-y)

    They differ by exactly one factor, σ′(z)∈(0,1/4]\sigma'(z) \in (0, 1/4]. So

    ∣dLBCE/dzdLMSE/dz∣=1σ′(z)=1p(1−p)\left|\frac{\mathrm{d}L_{\text{BCE}}/\mathrm{d}z}{\mathrm{d}L_{\text{MSE}}/\mathrm{d}z}\right| = \frac{1}{\sigma'(z)} = \frac{1}{p(1-p)}

    Step 4 — evaluate. With y=1y = 1:

    zzp=σ(z)p = \sigma(z)MSE dL/dz\mathrm{d}L/\mathrm{d}zBCE dL/dz\mathrm{d}L/\mathrm{d}zratio
    −1-12.689414e−12.689414\mathrm{e}{-1}−1.437348e−1-1.437348\mathrm{e}{-1}−0.731059-0.7310595.15.1
    −3-34.742587e−24.742587\mathrm{e}{-2}−4.303412e−2-4.303412\mathrm{e}{-2}−0.952574-0.95257422.122.1
    −5-56.692851e−36.692851\mathrm{e}{-3}−6.603562e−3-6.603562\mathrm{e}{-3}−0.993307-0.993307150.4150.4
    −10-104.539787e−54.539787\mathrm{e}{-5}−4.539375e−5-4.539375\mathrm{e}{-5}−0.999955-0.99995522,028.522{,}028.5
    −20-202.061154e−92.061154\mathrm{e}{-9}−2.061154e−9-2.061154\mathrm{e}{-9}−1.000000-1.000000485,165,197.4485{,}165{,}197.4

    Step 5 — read the two columns. As zz becomes more negative the model becomes more wrong: p→0p \to 0 while y=1y = 1.

    Cross-entropy’s gradient grows toward its maximum magnitude of 11. At z=−20z = -20 it is −1.000000-1.000000: the loss is shouting.

    MSE’s gradient shrinks toward zero. At z=−20z = -20 it is −2.06×10−9-2.06\times10^{-9}. In float32, where the smallest normal value is about 1.18×10−381.18\times10^{-38}, this is still representable — but multiplied through a few more layers of I.3’s saturation factors it is not, and in fp16 it underflowed long before.

    The model is as wrong as it is possible to be, and MSE reports almost nothing. That is the counterexample.

    Step 6 — which factor is responsible. Not the squaring. Substituting y=1y = 1 into (a):

    dLMSEdz=(p−1) p(1−p)=−p(1−p)2\frac{\mathrm{d}L_{\text{MSE}}}{\mathrm{d}z} = (p-1)\,p(1-p) = -p(1-p)^2

    As p→0p \to 0 this behaves as −p-p, and p=σ(z)→0p = \sigma(z) \to 0 exponentially in zz. The culprit is the σ′\sigma' factor that (b) cancels and (a) keeps — exactly the saturation of Chapter I.3, reaching the loss instead of a hidden layer.

    Step 7 — the other end, which is the honest caveat. At a point the model already gets right:

    | zz | MSE ∣dL/dz∣|\mathrm{d}L/\mathrm{d}z| | BCE ∣dL/dz∣|\mathrm{d}L/\mathrm{d}z| | |---|---|---| | +5+5 | 4.449445e−54.449445\mathrm{e}{-5} | 6.692851e−36.692851\mathrm{e}{-3} | | +10+10 | 2.060873e−92.060873\mathrm{e}{-9} | 4.539787e−54.539787\mathrm{e}{-5} |

    Both shrink, and MSE shrinks faster. So MSE is not uniformly worse — it is quieter everywhere. The asymmetry that matters is that cross-entropy stays loud where the model is wrong and goes quiet where it is right, while MSE goes quiet in both directions.

    Answer

    dLMSEdz=(p−y) p(1−p),dLBCEdz=p−y\frac{\mathrm{d}L_{\text{MSE}}}{\mathrm{d}z} = (p - y)\,p(1-p), \qquad \frac{\mathrm{d}L_{\text{BCE}}}{\mathrm{d}z} = p - y

    They differ by the factor σ′(z)=p(1−p)≤1/4\sigma'(z) = p(1-p) \le 1/4, which cross-entropy’s logarithm cancels and squared loss does not.

    At z=−10z = -10, y=1y = 1: MSE gives −4.539×10−5-4.539\times10^{-5} against BCE’s −0.999955-0.999955, a ratio of 22,02922{,}029. At z=−20z = -20 the ratio is 4.85×1084.85\times10^{8}.

    Check — numeric · i-4-b06-mse-vanishes.py
    d_mse = (p - y) * p * (1 - p)        # chain rule through sigma'
    d_bce = p - y                        # sigma' cancels

    Prints both columns at all five logits, their ratios, and the two already-correct points.

    Executed in CI. The digits above are the digits it printed.

    Check — sanity

    BCE’s gradient is bounded by 1. Every entry satisfies ∣p−y∣≤1|p - y| \le 1 since p∈(0,1)p \in (0,1) and y∈{0,1}y \in \{0,1\}. The table’s largest is −1.000000-1.000000, approached but not exceeded ✓

    The ratio equals 1/[p(1−p)]1/[p(1-p)] exactly. At z=−5z = -5: 1/(6.692851×10−3×0.993307)=150.41/(6.692851\times10^{-3} \times 0.993307) = 150.4, matching the table’s ratio column — computed from the closed form rather than by dividing the two columns, so it is an independent check.

    The two gradients agree where σ′\sigma' is largest. At z=0z = 0, σ′=1/4\sigma' = 1/4, so the ratio would be 44 — the smallest it can ever be. The table’s smallest ratio, 5.15.1 at z=−1z = -1, is consistent with approaching 44 as z→0z \to 0.

    Signs are correct throughout. With y=1y = 1 and p<1p < 1, both gradients are negative, so descent raises zz — which is what should happen when the model under-predicts the positive class.

    Where this breaks

    The vanishing is a property of the pair, not of squared loss alone. Remove the sigmoid — regress on an unbounded output with squared loss, as in I.1.B03 — and the gradient is (y^−y)(\hat{y} - y) with no saturating factor anywhere. Squared loss is entirely well behaved for regression; it is squared loss composed with a saturating output that fails.

    The general lesson is worth stating in its own right: check what the loss and the output nonlinearity do together, not separately. Cross-entropy pairs with softmax and sigmoid because the logarithm inverts the exponential in them. Any other pairing has to be checked, and the check is one line — differentiate and see whether the output’s derivative cancels.

    Variation

    Repeat the derivation for MSE composed with a linear output on a classification target in {0,1}\{0,1\}. Show the gradient no longer vanishes, then say what new problem appears instead — and why it makes the arrangement unusable anyway.

    Problem I.4.B07

    From a logit tensor to one scalar, with every shape named

    shape▲▲△

    Memory to 1 d.p.; counts exact.

    STATEMENT

    A language model emits logits of shape (B,T,∣V∣)(B, T, |V|). Trace every shape on the path from that tensor to the single number the optimiser differentiates. Compute the memory the logits occupy, and determine what masking does to the reduction — including the size of the error if it is done wrongly.

    GIVEN

    Batch B=4B = 4, sequence length T=512T = 512, vocabulary ∣V∣=32,000|V| = 32{,}000. Targets are token indices, shape (B,T)(B, T). Fifteen per cent of positions are padding and must be excluded. Cross-entropy is applied per position and then reduced to one scalar.

    FIND

    The shape after each stage; the element count and memory of the logits in fp32 and bf16; and the two possible reductions under masking, with the discrepancy between them.

    STRATEGY

    Follow the rank down. The logits are rank 33; the loss is rank 00. Two things remove a rank — indexing away the vocabulary axis, and reducing away the position axes — and the whole trace is deciding where each happens.

    SOLUTION

    Step 1 — the incoming pair.

    logits:(B,T,∣V∣)=(4,512,32000),targets:(B,T)=(4,512)\text{logits} : (B, T, |V|) = (4, 512, 32000), \qquad \text{targets} : (B, T) = (4, 512)

    The shapes do not match, and they should not. The targets are indices, not one-hot vectors: integers in [0,∣V∣)[0, |V|), one per position. A one-hot target of shape (4,512,32000)(4, 512, 32000) would hold the same information in 65,536,00065{,}536{,}000 numbers instead of 2,0482{,}048, of which all but 2,0482{,}048 are zero. Frameworks index rather than multiply for exactly this reason.

    Step 2 — the element count.

    B×T×∣V∣=4×512×32,000=65,536,000B \times T \times |V| = 4 \times 512 \times 32{,}000 = 65{,}536{,}000

    Step 3 — flatten the position axes. Cross-entropy treats every position independently, so the batch and time axes carry no meaning for it and can be merged:

    (4,512,32000)⟶(2048, 32000),(4,512)⟶(2048,)(4, 512, 32000) \longrightarrow (2048,\ 32000), \qquad (4, 512) \longrightarrow (2048,)

    2048=4×5122048 = 4 \times 512, and the element count is unchanged — a reshape moves no data. Every framework’s cross-entropy expects exactly this two-dimensional form, which is why calling it on rank-3 logits requires an explicit reshape.

    Step 4 — the per-position loss. For each of the 2,0482{,}048 rows, take the row’s 32,00032{,}000 logits and its one target index and produce one number:

    (2048,32000)×(2048,)⟶(2048,)(2048, 32000) \times (2048,) \longrightarrow (2048,)

    The vocabulary axis is gone. This is where −zc+log⁡∑jezj-z_c + \log\sum_j e^{z_j} is evaluated per row — never by forming probabilities first, for the reasons of I.4.B04.

    Step 5 — the reduction. (2048,)⟶()(2048,) \longrightarrow (), rank 00. This is the one number ∇θ\nabla_\theta is taken of, and Step 7 shows it is the step most often got wrong.

    The complete trace.

    StageShapeValues
    logits(4,512,32000)(4, 512, 32000)65,536,00065{,}536{,}000
    targets(4,512)(4, 512)2,0482{,}048
    flattened logits(2048,32000)(2048, 32000)65,536,00065{,}536{,}000
    flattened targets(2048,)(2048,)2,0482{,}048
    per-token loss(2048,)(2048,)2,0482{,}048
    reduced loss()()11

    Step 6 — memory.

    fp32:65,536,000×4 bytes=262.1 MB\text{fp32:}\quad 65{,}536{,}000 \times 4\ \text{bytes} = 262.1\ \text{MB}bf16:65,536,000×2 bytes=131.1 MB\text{bf16:}\quad 65{,}536{,}000 \times 2\ \text{bytes} = 131.1\ \text{MB}

    And if softmax probabilities are materialised as a separate tensor of the same shape — which the naive route of I.4.B04 requires — that doubles to 524.3524.3 MB in fp32 and 262.1262.1 MB in bf16.

    This single tensor is often the largest in the model. At B=4B = 4 it already rivals the activations of an entire transformer block, and it grows linearly in both BB and ∣V∣|V|. It is why the loss is computed in chunks over the batch for large vocabularies, and why ∣V∣|V| appears in memory budgets as prominently as depth does.

    Step 7 — masking, and the reduction it changes. With 15%15\% padding:

    total positions=2,048,valid positions=round(2048×0.85)=1,741\text{total positions} = 2{,}048, \qquad \text{valid positions} = \text{round}(2048 \times 0.85) = 1{,}741

    Padded positions contribute a loss of 00, having been masked. But there are two different things one can then divide by.

    Mean over all positions. 12048∑iℓi\displaystyle \frac{1}{2048}\sum_i \ell_i — divides by the number of slots.

    Mean over valid positions. 11741∑iℓi\displaystyle \frac{1}{1741}\sum_i \ell_i — divides by the number of real tokens.

    The ratio is

    20481741=1.1763\frac{2048}{1741} = 1.1763

    so the first understates the loss by 17.6%17.6\% relative to the second.

    Why this matters more than it looks. The reported loss is wrong by a fixed factor, which is merely embarrassing. The gradient is wrong by the same factor, which is an unintended 17.6%17.6\% reduction in effective learning rate. And the factor is not fixed across batches: it depends on how much padding each batch happens to contain, so the effective learning rate fluctuates from step to step with the batch’s sequence-length distribution. Sorting examples by length into buckets — done for speed — changes the padding fraction systematically, and so silently changes the learning rate schedule.

    Dividing by the valid count is the correct choice, and it is not the default in every framework.

    Answer

    (4,512,32000)→(2048,32000)→(2048,)→()(4, 512, 32000) \to (2048, 32000) \to (2048,) \to ()

    Logits hold 65,536,00065{,}536{,}000 values: 262.1262.1 MB in fp32, 131.1131.1 MB in bf16, and double that if probabilities are materialised too.

    With 15%15\% padding, 1,7411{,}741 of 2,0482{,}048 positions are valid. Reducing over all positions rather than valid ones understates the loss and the gradient by a factor of 2048/1741=1.17632048/1741 = 1.1763, or 17.6%\mathbf{17.6\%}.

    Check — numeric · i-4-b07-loss-shapes.py
    logits = B * T * V
    valid  = round(B * T * (1 - PAD_FRACTION))
    print(f"ratio {total / valid:.4f}")

    Prints the full shape trace, both memory figures, and the 1.17631.1763 ratio.

    Executed in CI. The digits above are the digits it printed.

    Check — sanity

    The reshape conserves elements. 4×512×32000=65,536,0004 \times 512 \times 32000 = 65{,}536{,}000 and 2048×32000=65,536,0002048 \times 32000 = 65{,}536{,}000. A reshape that changed the count would be a copy or a truncation, not a reshape.

    Rank falls exactly twice. Rank 3→23 \to 2 by the flatten, 2→12 \to 1 by indexing away the vocabulary, 1→01 \to 0 by the reduction. Three drops, three identifiable operations, no rank lost silently.

    bf16 is exactly half of fp32. 262.1/131.1=2.0262.1 / 131.1 = 2.0, as two bytes against four requires.

    The masking ratio bounds correctly. 1≤2048/1741≤1/0.85=1.17651 \le 2048/1741 \le 1/0.85 = 1.1765. The computed 1.17631.1763 sits just inside, the difference being the rounding of 1741.1741. At zero padding the ratio would be exactly 11 and the two reductions would agree — which is why this bug is invisible on fixed-length data.

    Where this breaks

    The trace assumes every position has exactly one target. Two common cases break it, and both are worth recognising by their shapes.

    Soft targets. With label smoothing or distillation the target is a full distribution, shape (2048,32000)(2048, 32000) rather than (2048,)(2048,). The indexing step of Step 4 becomes a contraction over the vocabulary axis, the targets now cost the same memory as the logits, and the total doubles again.

    Multi-label. When a position may carry several correct classes, softmax is wrong outright — it forces the outputs to sum to one, and KK independent sigmoids with binary cross-entropy is the right structure instead. The shape (2048,32000)(2048, 32000) survives but the reduction is over ∣V∣|V| as well as over positions, and the loss is a sum of 32,00032{,}000 binary terms per position rather than one categorical term.

    Variation

    Recompute every figure for ∣V∣=128,000|V| = 128{,}000 at the same BB and TT. State the new fp32 memory, and find the batch size at which the logit tensor alone exceeds 1010 GB.

    Exercises

    Every one has a published solution. A hidden solution is a solution; a missing one is an abandonment.

    I.4.X01Three losses, two moderate outliersnumeric▲△△

    Compute MSE, MAE and Huber1\mathrm{Huber}_1 on the residuals (1.0, −1.5, 0.4, −2.5, 0.1)(1.0,\ -1.5,\ 0.4,\ -2.5,\ 0.1). Say which branch of Huber each residual takes, and what share of each total the two residuals with ∣r∣>1|r| > 1 take together.

    Hint

    Decide the branches before computing anything, as in I.4.B01.

    Solution

    Branches first. ∣1.0∣=1.0≤1|1.0| = 1.0 \le 1 — quadratic, exactly at the join. ∣−1.5∣>1|{-1.5}| > 1 and ∣−2.5∣>1|{-2.5}| > 1 — linear. ∣0.4∣|0.4| and ∣0.1∣|0.1| — quadratic.

    | rr | r2r^2 | ∣r∣|r| | Huber1\mathrm{Huber}_1 | branch | |---|---|---|---|---| | 1.01.0 | 1.00001.0000 | 1.00001.0000 | 0.50000.5000 | quadratic | | −1.5-1.5 | 2.25002.2500 | 1.50001.5000 | 1.00001.0000 | linear | | 0.40.4 | 0.16000.1600 | 0.40000.4000 | 0.08000.0800 | quadratic | | −2.5-2.5 | 6.25006.2500 | 2.50002.5000 | 2.00002.0000 | linear | | 0.10.1 | 0.01000.0100 | 0.10000.1000 | 0.00500.0050 | quadratic | | sum | 9.67009.6700 | 5.50005.5000 | 3.58503.5850 | | | mean | 1.93401.9340 | 1.10001.1000 | 0.71700.7170 | |

    Working the two linear-branch entries. Huber1(−1.5)=(1)(1.5−0.5)=1.0000\mathrm{Huber}_1(-1.5) = (1)(1.5 - 0.5) = 1.0000 and Huber1(−2.5)=(1)(2.5−0.5)=2.0000\mathrm{Huber}_1(-2.5) = (1)(2.5 - 0.5) = 2.0000.

    The shares. The two large residuals contribute 2.25+6.25=8.502.25 + 6.25 = 8.50 of 9.679.67; 1.5+2.5=4.01.5 + 2.5 = 4.0 of 5.55.5; and 1.0+2.0=3.01.0 + 2.0 = 3.0 of 3.5853.585:

    MSE 87.9%,MAE 72.7%,Huber 83.7%\text{MSE } 87.9\%, \qquad \text{MAE } 72.7\%, \qquad \text{Huber } 83.7\%

    What is different from I.4.B01. There, one extreme outlier at r=4r = 4 took 94%94\% of MSE. Here two moderate ones at 1.51.5 and 2.52.5 take 87.9%87.9\%. The concentration is milder because the outliers are milder — MSE’s dominance grows with the square of how unusual the outlier is, so it is a problem of degree, not a switch that flips.

    The residual at exactly ∣r∣=1|r| = 1 is worth noticing. It sits on the join, and both branches give 0.50.5: quadratic 12(1)2=0.5\tfrac12(1)^2 = 0.5, linear (1)(1−0.5)=0.5(1)(1 - 0.5) = 0.5. Continuity holds, as I.4.B01’s sanity check argued it must. An implementation that used << where it should use ≤\le would still give the right answer here — which is exactly why such a bug survives testing.

    I.4.X02Why Huber has that $-\tfrac12\delta$ in itsymbolic▲△△

    Show that Huberδ\mathrm{Huber}_\delta is continuous and has a continuous derivative at ∣r∣=δ|r| = \delta. Then show that removing the −12δ-\tfrac12\delta term — using δ∣r∣\delta|r| on the outer branch — destroys continuity of the value while leaving the derivative continuous, and say why that is the worse of the two failures.

    Hint

    Evaluate both branches, and both their derivatives, at r=δr = \delta exactly.

    Solution

    Continuity of the value. At r=δr = \delta, approaching from inside:

    12r2∣r=δ=12δ2\tfrac12 r^2 \big|_{r=\delta} = \tfrac12\delta^2

    and from outside:

    δ ⁣(r−12δ)∣r=δ=δ ⁣(δ−12δ)=δ⋅12δ=12δ2\delta\!\left(r - \tfrac12\delta\right)\Big|_{r=\delta} = \delta\!\left(\delta - \tfrac12\delta\right) = \delta \cdot \tfrac12\delta = \tfrac12\delta^2

    Equal, so the function is continuous. The −12δ-\tfrac12\delta is precisely the offset that makes the two branches meet.

    Continuity of the derivative. Differentiating each branch:

    ddr 12r2=r⟶δ at r=δ\frac{\mathrm{d}}{\mathrm{d}r}\,\tfrac12 r^2 = r \quad\longrightarrow\quad \delta \text{ at } r = \deltaddr δ ⁣(r−12δ)=δ⟶δ everywhere on that branch\frac{\mathrm{d}}{\mathrm{d}r}\,\delta\!\left(r - \tfrac12\delta\right) = \delta \quad\longrightarrow\quad \delta \text{ everywhere on that branch}

    Both give δ\delta. So Huberδ∈C1\mathrm{Huber}_\delta \in C^{1}: value and slope both match, and the function has no kink. It is not C2C^2 — the second derivative jumps from 11 to 00 — but C1C^1 is what a first-order optimiser needs.

    Removing the offset. Define H~(r)=12r2\tilde{H}(r) = \tfrac12 r^2 for ∣r∣≤δ|r| \le \delta and δ∣r∣\delta|r| beyond. Its derivative on the outer branch is still δ\delta, so the derivative is still continuous. But the value jumps:

    lim⁡r→δ−H~=12δ2,lim⁡r→δ+H~=δ2\lim_{r\to\delta^{-}}\tilde{H} = \tfrac12\delta^{2}, \qquad \lim_{r\to\delta^{+}}\tilde{H} = \delta^{2}

    a discontinuity of size 12δ2\tfrac12\delta^2.

    Why the value discontinuity is worse than a derivative one. This is the part worth thinking about, because the naive ranking is the other way round.

    A discontinuous derivative — a kink, as MAE has at zero — is survivable. The subgradient convention of I.2.X09 covers it, the set of points where it matters has measure zero, and every ReLU network already lives with it.

    A discontinuous value is not survivable, for a reason that has nothing to do with differentiability. The reported loss becomes uninterpretable: two models whose residuals differ infinitesimally, one just inside δ\delta and one just outside, report losses differing by 12δ2\tfrac12\delta^2. Loss curves acquire jumps that look like instability and are not. Comparisons between runs with different δ\delta are meaningless. And any early-stopping or model-selection rule reading the loss inherits the artefact.

    Worse, gradient descent does not even notice: the gradients are identical to Huber’s, so the optimisation proceeds normally while the number reported about it is wrong. A bug that changes the metric but not the training is harder to find than one that breaks training, because nothing fails.

    The general form. Whenever a piecewise loss is defined, check the value and the derivative at every join, separately. Continuity of one does not imply the other, and they fail in different ways.

    I.4.X03Squared loss asks for the conditional meanproof▲▲△

    Prove that the constant cc minimising E[(Y−c)2]\mathbb{E}[(Y - c)^2] is c⋆=E[Y]c^\star = \mathbb{E}[Y], and that the minimum value is Var(Y)\mathrm{Var}(Y). Then state the conditional version and say what it implies about what a squared-loss-trained network is estimating.

    Hint

    Add and subtract E[Y]\mathbb{E}[Y] inside the square, then expand and use linearity of expectation.

    Solution

    Step 1 — decompose. Write μ=E[Y]\mu = \mathbb{E}[Y] and insert μ−μ\mu - \mu:

    E[(Y−c)2]=E[((Y−μ)+(μ−c))2]\mathbb{E}\big[(Y-c)^2\big] = \mathbb{E}\Big[\big((Y - \mu) + (\mu - c)\big)^2\Big]

    Step 2 — expand the square.

    =E[(Y−μ)2+2(Y−μ)(μ−c)+(μ−c)2]= \mathbb{E}\Big[(Y-\mu)^2 + 2(Y-\mu)(\mu-c) + (\mu-c)^2\Big]

    Step 3 — take expectations term by term, using linearity (Expectation 0.PR.02) and noting (μ−c)(\mu - c) is a constant:

    =E[(Y−μ)2]⏟Var(Y)+2(μ−c)E[Y−μ]⏟= 0+(μ−c)2= \underbrace{\mathbb{E}\big[(Y-\mu)^2\big]}_{\mathrm{Var}(Y)} + 2(\mu-c)\underbrace{\mathbb{E}[Y-\mu]}_{=\,0} + (\mu-c)^2

    The middle term vanishes because E[Y−μ]=E[Y]−μ=0\mathbb{E}[Y - \mu] = \mathbb{E}[Y] - \mu = 0 by the definition of μ\mu. That cancellation is the whole proof.

    Step 4 — read off the minimum.

    E[(Y−c)2]=Var(Y)+(μ−c)2\mathbb{E}\big[(Y-c)^2\big] = \mathrm{Var}(Y) + (\mu - c)^2

    The first term does not involve cc; the second is a square, so non-negative, and is zero exactly when c=μc = \mu. Hence

    c⋆=E[Y],min⁡cE[(Y−c)2]=Var(Y)c^\star = \mathbb{E}[Y], \qquad \min_c \mathbb{E}\big[(Y-c)^2\big] = \mathrm{Var}(Y)

    ■\blacksquare

    Step 5 — the conditional version. Applying the same argument at each xx separately, with all expectations conditioned on X=xX = x:

    f⋆(x)=E[Y∣X=x]f^\star(x) = \mathbb{E}[Y \mid X = x]

    What this says about a trained network. Three things, in order of how often they are missed.

    The target of training is the conditional mean, not a sample. Given a dataset with two identical inputs and different labels — say y=0y = 0 and y=10y = 10 — the squared-loss optimum predicts 55, a value that appears nowhere in the data and may be impossible. On a bimodal conditional distribution, the mean can sit in a region of zero density.

    The irreducible loss is the conditional variance. Var(Y∣X=x)\mathrm{Var}(Y \mid X = x) cannot be reduced by any model whatsoever. A training loss that has plateaued at a nonzero value may be at the optimum, and no architecture change will move it. Knowing that number — estimable from repeated measurements at the same input — tells you when to stop trying.

    The optimum is over all functions, not over the hypothesis class. The network approaches E[Y∣X]\mathbb{E}[Y|X] only insofar as that function lies in its class and the optimiser finds it. I.4.T2’s scope note says exactly this, and it is the same gap I.1.T1 identified between existence and reachability.

    The connection to blurry generative outputs. A model trained with squared loss to produce images predicts the pixel-wise conditional mean. Where several sharp outputs are equally plausible, their mean is a blur. This is not a failure of capacity or of data — it is the loss doing exactly what this proof says it does, and no amount of training fixes it. Changing the loss does.

    I.4.X04Absolute loss asks for the medianproof▲▲△

    Prove that the constant minimising E∣Y−c∣\mathbb{E}|Y - c| is a median of YY. Then contrast with I.4.X03 on a concrete skewed example, and state which loss to choose when the two answers differ.

    Hint

    Differentiate under the expectation. The derivative of ∣y−c∣|y - c| with respect to cc is −sign(y−c)-\mathrm{sign}(y - c), which takes only two values.

    Solution

    Step 1 — differentiate. For YY with a density, differentiating under the expectation:

    ddc E∣Y−c∣=E ⁣[∂∂c∣Y−c∣]=E[−sign⁡(Y−c)]\frac{\mathrm{d}}{\mathrm{d}c}\,\mathbb{E}|Y - c| = \mathbb{E}\!\left[\frac{\partial}{\partial c}|Y-c|\right] = \mathbb{E}\big[-\operatorname{sign}(Y - c)\big]

    Step 2 — write the sign as a difference of probabilities. Since sign⁡\operatorname{sign} takes only ±1\pm 1 (ignoring the measure-zero tie):

    E[sign⁡(Y−c)]=(+1) P(Y>c)+(−1) P(Y<c)=P(Y>c)−P(Y<c)\mathbb{E}\big[\operatorname{sign}(Y-c)\big] = (+1)\,P(Y > c) + (-1)\,P(Y < c) = P(Y > c) - P(Y < c)

    so

    ddc E∣Y−c∣=P(Y<c)−P(Y>c)\frac{\mathrm{d}}{\mathrm{d}c}\,\mathbb{E}|Y - c| = P(Y < c) - P(Y > c)

    Step 3 — set to zero.

    P(Y<c)=P(Y>c)P(Y < c) = P(Y > c)

    which, with the two probabilities summing to 11, gives P(Y<c)=P(Y>c)=12P(Y < c) = P(Y > c) = \tfrac12. That is the definition of a median. ■\blacksquare

    Step 4 — confirm it is a minimum. The derivative P(Y<c)−P(Y>c)P(Y<c) - P(Y>c) is non-decreasing in cc (as cc rises, P(Y<c)P(Y<c) rises and P(Y>c)P(Y>c) falls), so it crosses zero from below: negative then positive. That is a minimum, and the objective is convex.

    Step 5 — the contrast, made concrete. Take YY taking values 1,2,3,4,1001, 2, 3, 4, 100 with equal probability 1/51/5.

    Mean. (1+2+3+4+100)/5=110/5=22(1 + 2 + 3 + 4 + 100)/5 = 110/5 = 22.

    Median. The middle of five ordered values: 33.

    Squared loss would have the model predict 2222; absolute loss, 33. Four of the five actual values are closer to 33 than to 2222, and 2222 is not near any of them.

    Step 6 — why the difference is structural, not a quirk. From Step 2, each observation contributes ±1\pm 1 to the derivative of E∣Y−c∣\mathbb{E}|Y-c| — its magnitude is irrelevant, only which side it is on. Changing 100100 to 10610^6 leaves the median at 33 and moves the mean to 200,002200{,}002. Under squared loss the derivative contribution is (c−y)(c - y), proportional to distance, so one distant point can outvote many near ones. This is the same fact as I.4.B01’s derivative column, stated in expectation instead of on a sample.

    Which to choose. The question is not which is more robust; it is which summary you actually want reported.

    If the quantity of interest is a total — total revenue, total dose, total count — the mean is correct, because means add and medians do not. Predicting the median and summing gives the wrong total.

    If the quantity of interest is a typical case — a typical delivery time, a typical house price — the median is correct, and the mean is distorted by a tail you were never asking about.

    If large errors are disproportionately costly, squared loss encodes that directly, and choosing it is a statement about consequences rather than about robustness.

    The honest summary. “MAE is robust to outliers” is true and is the wrong framing. Both losses answer a well-posed question exactly; they answer different well-posed questions. Deciding between them means deciding which question you are asking, which is a modelling decision and not a numerical one.

    I.4.X05The finite logit gap label smoothing asks forsymbolic▲▲△

    With one-hot targets, cross-entropy is minimised only as the true-class logit goes to infinity. Show that label smoothing replaces that with a finite optimum, derive the optimal logit gap, and evaluate it for ε=0.1\varepsilon = 0.1, K=3K = 3.

    Hint

    The gradient is still p−y′\vec{p} - \vec{y}' by I.4.B03 — that derivation never needed y\vec{y} to be one-hot, only to sum to one.

    Solution

    Step 1 — the smoothed target. For true class cc,

    yk′=(1−ε) 1[k=c]+εKy'_k = (1-\varepsilon)\,\mathbb{1}[k=c] + \frac{\varepsilon}{K}

    Check it sums to one: (1−ε)(1)+K⋅ε/K=1−ε+ε=1(1-\varepsilon)(1) + K\cdot\varepsilon/K = 1 - \varepsilon + \varepsilon = 1 ✓. That is the only property I.4.B03’s Step 8 used, so the gradient result carries over unchanged:

    ∂L∂z=p−y′\frac{\partial L}{\partial \vec{z}} = \vec{p} - \vec{y}'

    Step 2 — set the gradient to zero. The stationary point is p=y′\vec{p} = \vec{y}':

    pc=1−ε+εK,pj=εK  (j≠c)p_c = 1 - \varepsilon + \frac{\varepsilon}{K}, \qquad p_j = \frac{\varepsilon}{K} \ \ (j \neq c)

    These are attainable probabilities, both strictly inside (0,1)(0,1). Contrast with ε=0\varepsilon = 0, where the requirement is pc=1p_c = 1 and pj=0p_j = 0 — values softmax approaches but never reaches for finite logits.

    Step 3 — convert to a logit gap. From pi=ezi/Sp_i = e^{z_i}/S, the ratio of two probabilities has the shared denominator cancel:

    pcpj=ezcezj=e zc−zj\frac{p_c}{p_j} = \frac{e^{z_c}}{e^{z_j}} = e^{\,z_c - z_j}

    Taking logarithms,

    zc−zj=log⁡pcpj=log⁡ ⁣(1−ε+ε/Kε/K)z_c - z_j = \log\frac{p_c}{p_j} = \log\!\left(\frac{1 - \varepsilon + \varepsilon/K}{\varepsilon/K}\right)

    Step 4 — simplify. Multiply numerator and denominator by KK:

     zc−zj=log⁡ ⁣(K(1−ε)+εε) \boxed{\ z_c - z_j = \log\!\left(\frac{K(1-\varepsilon) + \varepsilon}{\varepsilon}\right)\ }

    Step 5 — evaluate at ε=0.1\varepsilon = 0.1, K=3K = 3.

    pc=1−0.1+0.13=0.9+0.0333=0.9333,pj=0.13=0.0333p_c = 1 - 0.1 + \frac{0.1}{3} = 0.9 + 0.0333 = 0.9333, \qquad p_j = \frac{0.1}{3} = 0.0333pcpj=0.93330.0333=28.0⟹zc−zj=log⁡28.0=3.3322\frac{p_c}{p_j} = \frac{0.9333}{0.0333} = 28.0 \quad\Longrightarrow\quad z_c - z_j = \log 28.0 = 3.3322

    Or from the closed form: (3(0.9)+0.1)/0.1=2.8/0.1=28\big(3(0.9) + 0.1\big)/0.1 = 2.8/0.1 = 28 ✓.

    Step 6 — the limits. As ε→0+\varepsilon \to 0^{+} the argument of the logarithm is K/ε→∞K/\varepsilon \to \infty, so the gap diverges — recovering the unsmoothed case where no finite logit configuration is optimal. As ε→1\varepsilon \to 1 the argument tends to 11 and the gap to 00: the target becomes uniform and the model is asked to predict nothing at all.

    What this buys, and what it costs.

    Bounded logits. The optimum is at a gap of 3.333.33 rather than at infinity, so there is no incentive to keep growing the weights. That is a regularisation effect, obtained without a penalty term.

    Better calibration. An unsmoothed model driven toward pc=1p_c = 1 is systematically overconfident. Smoothing caps the confidence at a chosen value, and 0.93330.9333 is a defensible one.

    Worse for distillation. Müller et al. (2019) show smoothing collapses the geometry of the penultimate layer: the logits of the wrong classes are pushed to be equally wrong, destroying the relative information a student model would learn from. A smoothed teacher is a worse teacher, and this is the standard reason not to smooth when distillation is planned.

    A caution on reading the loss. The minimum value is no longer zero. At the optimum the loss equals the entropy of y′\vec{y}', which for ε=0.1\varepsilon = 0.1, K=3K = 3 is −0.9333log⁡0.9333−2(0.0333)log⁡0.0333=0.0644+0.2266=0.2910-0.9333\log 0.9333 - 2(0.0333)\log 0.0333 = 0.0644 + 0.2266 = 0.2910 nats. A smoothed run that plateaus at 0.290.29 has converged; comparing it to an unsmoothed run’s 0.050.05 is comparing two different objectives.

    I.4.X06A step that improves the loss and worsens the accuracycounterexample▲▲△

    Construct a two-example case in which cross-entropy strictly decreases while accuracy strictly decreases as well. Give both numbers before and after, and explain the mechanism in one sentence.

    Hint

    Accuracy counts only which side of 0.50.5 each prediction is on. Cross-entropy also counts how far.

    Solution

    The construction. Two examples, both with label y=1y = 1.

    beforeafter
    example Ap=0.51p = 0.51p=0.49p = 0.49
    example Bp=0.10p = 0.10p=0.60p = 0.60

    Accuracy. With threshold 0.50.5:

    Before. A is correct (0.51>0.50.51 > 0.5), B is wrong (0.10<0.50.10 < 0.5). Accuracy =1/2=50%= 1/2 = 50\%.

    After. A is now wrong (0.49<0.50.49 < 0.5), B is now correct (0.60>0.50.60 > 0.5). Accuracy =1/2=50%= 1/2 = 50\%.

    That is a tie, so push it further. Take three examples, all y=1y = 1:

    beforeafter
    A0.510.510.490.49
    B0.510.510.490.49
    C0.100.100.980.98

    Accuracy before: A ✓, B ✓, C ✗ — 2/3=66.7%2/3 = 66.7\%. Accuracy after: A ✗, B ✗, C ✓ — 1/3=33.3%1/3 = 33.3\%. Halved.

    Cross-entropy. With y=1y = 1 the loss per example is −log⁡p-\log p.

    Before:

    −log⁡0.51=0.6733,−log⁡0.51=0.6733,−log⁡0.10=2.3026-\log 0.51 = 0.6733, \quad -\log 0.51 = 0.6733, \quad -\log 0.10 = 2.3026L‾=0.6733+0.6733+2.30263=3.64923=1.2164\overline{L} = \frac{0.6733 + 0.6733 + 2.3026}{3} = \frac{3.6492}{3} = 1.2164

    After:

    −log⁡0.49=0.7133,−log⁡0.49=0.7133,−log⁡0.98=0.0202-\log 0.49 = 0.7133, \quad -\log 0.49 = 0.7133, \quad -\log 0.98 = 0.0202L‾=0.7133+0.7133+0.02023=1.44683=0.4823\overline{L} = \frac{0.7133 + 0.7133 + 0.0202}{3} = \frac{1.4468}{3} = 0.4823

    The loss fell from 1.21641.2164 to 0.48230.4823 — a 60%60\% improvement — while accuracy fell from 66.7%66.7\% to 33.3%33.3\%.

    The mechanism in one sentence. Accuracy is a step function of each prediction and cannot see the difference between 0.510.51 and 0.980.98, while cross-entropy is a smooth function of it and rewards the enormous gain on C far more than it punishes the two tiny losses on A and B.

    Why this is not a pathology. Gradient descent requires a differentiable objective, and accuracy has zero gradient almost everywhere — its derivative is zero wherever it is defined, and undefined at the threshold. It is unoptimisable by any first-order method. So the loss is not an approximation to accuracy that occasionally goes wrong; it is a different objective, chosen because it is differentiable, and the two agreeing most of the time is a convenience rather than a guarantee.

    What follows in practice. Three habits.

    Report both. A run whose loss improves while its validation accuracy stalls is not necessarily broken, and is not necessarily fine either. Only both numbers together say which.

    Select on the metric you care about. Early stopping on validation loss and early stopping on validation accuracy choose different checkpoints, and the gap widens with calibration effects. Choose deliberately.

    Do not read a small loss improvement as a small accuracy improvement. There is no monotone relationship between them, as this construction shows in three lines.

    Chapter VIII.5 makes this quantitative for model comparison; the same disconnect between a differentiable surrogate and the quantity of interest reappears there as the difference between AUROC and clinical utility.

    I.4.X07When the implied noise model is falsecounterexample▲▲△

    The first assumption of this chapter is that the loss’s implied noise model matches the data. Take count data, show all three Gaussian properties fail, quantify one of the failures, and name the loss that does not fail.

    Hint

    I.4.B02 identified three properties the Gaussian asserts. Check each against a Poisson count.

    Solution

    The data. Read counts from an RNA-sequencing experiment: a gene’s expression in one cell, a non-negative integer, typically between 00 and a few thousand, with most genes at 00 in most cells.

    The three Gaussian assertions, checked in turn.

    Symmetry — false. If the model predicts y^=3\hat{y} = 3, the residual can be −3-3 at most (the count cannot go below zero) but can be +100+100 or more. The error distribution is right-skewed by construction, and squared loss treats −3-3 and +3+3 as equally likely and equally costly.

    Constant variance — false, and quantifiably so. For a Poisson count, Var(Y)=E[Y]\mathrm{Var}(Y) = \mathbb{E}[Y]: the variance equals the mean. A gene expressed at 1010 has standard deviation 10=3.16\sqrt{10} = 3.16; one expressed at 10001000 has 1000=31.6\sqrt{1000} = 31.6. Squared loss assumes one σ2\sigma^2 for both.

    Quantify what that costs. Maximum likelihood weights each residual by 1/σi21/\sigma_i^2; squared loss weights every residual equally. So relative to the correct weighting, squared loss over-weights the high-expression gene by

    σhigh2σlow2=100010=100\frac{\sigma^2_{\text{high}}}{\sigma^2_{\text{low}}} = \frac{1000}{10} = 100

    A hundredfold. The fit is dominated by a handful of highly expressed genes whose residuals are large only because their noise is large. In practice these are housekeeping genes, and the model spends its capacity on the least informative part of the data.

    Unbounded support — false. The Gaussian assigns positive density to y=−5y = -5, an impossible count, and a squared-loss model will happily predict negative values. Every such prediction is not merely inaccurate but meaningless.

    A fourth failure specific to this data. Counts are discrete and heavily zero-inflated: a typical single-cell matrix is over 90%90\% zeros. A continuous symmetric density is a poor description of a distribution with an atom at zero holding most of its mass.

    The loss that does not fail. The negative log-likelihood of a negative binomial:

    p(y∣μ,ϕ)=(y+ϕ−1−1y)(μμ+ϕ−1)y(ϕ−1μ+ϕ−1)ϕ−1p(y \mid \mu, \phi) = \binom{y + \phi^{-1} - 1}{y}\left(\frac{\mu}{\mu + \phi^{-1}}\right)^{y}\left(\frac{\phi^{-1}}{\mu + \phi^{-1}}\right)^{\phi^{-1}}

    with mean μ\mu and variance μ+ϕμ2\mu + \phi\mu^2. It is discrete, supported on non-negative integers, right-skewed, and its variance grows with its mean — with ϕ\phi tuning how much faster than Poisson. Chapter VII.2 derives it as a Poisson–Gamma mixture and Chapter VII.5 builds a model on it.

    The route from here to there is I.4.B02 run forwards. Write the density, take the negative logarithm, discard the terms free of θ\theta, and what remains is the loss. That is the general procedure, and squared error is only the instance of it where the density happens to be Gaussian.

    The habit this exercise is for. Before choosing a loss, write down the noise model it implies and ask whether you believe it. Two minutes of that catches most of the failures in this exercise — and the failure mode when it is skipped is not a crash but a model that trains, converges, and is quietly fitting the wrong thing.

    I.4.X08The reduction is a choice, and it moves the learning rateshape▲▲△

    The second assumption of this chapter is that the reduction is a plain mean over examples. Show that summing instead of averaging changes the effective learning rate, quantify it for two batch sizes, and identify a case where the choice varies within a training run.

    Hint

    The gradient of a sum is nn times the gradient of a mean.

    Solution

    Step 1 — the two reductions.

    Lmean=1n∑i=1nℓi,Lsum=∑i=1nℓi=n LmeanL_{\text{mean}} = \frac{1}{n}\sum_{i=1}^{n}\ell_i, \qquad L_{\text{sum}} = \sum_{i=1}^{n}\ell_i = n\,L_{\text{mean}}

    Step 2 — the gradients. Differentiation is linear, so the factor passes straight through:

    ∇θLsum=n ∇θLmean\nabla_\theta L_{\text{sum}} = n\,\nabla_\theta L_{\text{mean}}

    Step 3 — the update. With learning rate η\eta:

    θ←θ−η ∇Lsum=θ−(nη) ∇Lmean\theta \leftarrow \theta - \eta\,\nabla L_{\text{sum}} = \theta - (n\eta)\,\nabla L_{\text{mean}}

    Summing rather than averaging is exactly training at learning rate nηn\eta. Not approximately, and not “roughly like a bigger step” — identically.

    Step 4 — quantify. At n=32n = 32 and η=10−3\eta = 10^{-3}, the effective rate under summation is 3.2×10−23.2\times10^{-2}; at n=256n = 256 it is 2.56×10−12.56\times10^{-1}. The same code, the same η\eta, and an eightfold difference in effective rate purely from the batch size. A configuration tuned at n=32n = 32 diverges at n=256n = 256, and the reduction is nowhere in the hyperparameter file.

    Step 5 — the case that varies within a run. This is the part worth remembering, because it is invisible.

    Consider token-level cross-entropy over variable-length sequences with padding, as in I.4.B07. Suppose the implementation sums the per-token losses and divides by the batch size rather than by the token count:

    L=1B∑b∑tℓbtL = \frac{1}{B}\sum_{b}\sum_{t}\ell_{bt}

    Then a batch of long sequences has more tokens contributing to the same denominator, so its gradient is larger. With B=4B = 4:

    A batch averaging 500500 tokens per sequence contributes about 2,0002{,}000 token losses over a denominator of 44 — an effective per-token weight of 500500.

    A batch averaging 5050 tokens contributes 200200 losses over the same denominator — an effective weight of 5050.

    A tenfold swing in effective learning rate, batch to batch, driven entirely by the sequence lengths that happened to be sampled. And length-bucketing — grouping similar lengths together for throughput — makes it systematic rather than random: early buckets of short sequences train at one rate and later buckets of long ones at another.

    Step 6 — the correct reduction, and the check. Divide by the number of valid tokens:

    L=∑b,tmbt ℓbt∑b,tmbtL = \frac{\sum_{b,t} m_{bt}\,\ell_{bt}}{\sum_{b,t} m_{bt}}

    with mm the mask. Then the denominator tracks the numerator and the effective per-token weight is 11 regardless of lengths or padding.

    The check is one line: log the denominator. If it varies across steps by more than the padding fraction should allow, the reduction is wrong. Nothing else in the run will tell you.

    Why this belongs with the losses rather than with the engineering. The reduction does not appear in the loss’s formula and is not part of its definition — which is exactly why it is assumed rather than stated, and why the assumption is worth writing down as this chapter does.

    I.4.X09Focal loss, and the gradient it reshapesgradient▲▲△

    Focal loss is FL=−(1−pt)γlog⁡pt\mathrm{FL} = -(1-p_t)^{\gamma}\log p_t, where ptp_t is the probability assigned to the true class. Tabulate the modulating factor, derive d FL/dz\mathrm{d}\,\mathrm{FL}/\mathrm{d}z for the binary case, evaluate at five logits with γ=2\gamma = 2, and say how it differs from the class weighting of I.4.B05.

    Hint

    Use the product rule on −(1−p)γlog⁡p-(1-p)^{\gamma}\log p, then chain through dp/dz=p(1−p)\mathrm{d}p/\mathrm{d}z = p(1-p).

    Solution

    Step 1 — the modulating factor.

    ptp_tγ=0\gamma = 0γ=1\gamma = 1γ=2\gamma = 2γ=5\gamma = 5
    0.100.101.000001.000000.900000.900000.810000.810000.590490.59049
    0.500.501.000001.000000.500000.500000.250000.250000.031250.03125
    0.900.901.000001.000000.100000.100000.010000.010000.000010.00001
    0.990.991.000001.000000.010000.010000.000100.000100.000000.00000

    At γ=0\gamma = 0 the factor is 11 everywhere and focal loss is cross-entropy. As γ\gamma grows, well-classified examples (ptp_t near 11) are suppressed sharply while hard ones (ptp_t near 00) are barely touched: at γ=2\gamma = 2 the suppression is 100×100\times at pt=0.9p_t = 0.9 and only 1.23×1.23\times at pt=0.1p_t = 0.1.

    Step 2 — derive the gradient. Write L=−(1−p)γlog⁡pL = -(1-p)^{\gamma}\log p with y=1y=1, so pt=pp_t = p. By the product rule on the two pp-dependent factors:

    ∂L∂p=γ(1−p)γ−1log⁡p⏟from (1−p)γ  −  (1−p)γp⏟from log⁡p\frac{\partial L}{\partial p} = \underbrace{\gamma(1-p)^{\gamma-1}\log p}_{\text{from }(1-p)^\gamma} \;\underbrace{-\;\frac{(1-p)^{\gamma}}{p}}_{\text{from }\log p}

    taking care with the sign: ddp(1−p)γ=−γ(1−p)γ−1\frac{\mathrm{d}}{\mathrm{d}p}(1-p)^{\gamma} = -\gamma(1-p)^{\gamma-1}, and the leading minus of LL flips it back.

    Step 3 — chain through the sigmoid. With dp/dz=p(1−p)\mathrm{d}p/\mathrm{d}z = p(1-p):

    dLdz=[γ(1−p)γ−1log⁡p−(1−p)γp]p(1−p)\frac{\mathrm{d}L}{\mathrm{d}z} = \left[\gamma(1-p)^{\gamma-1}\log p - \frac{(1-p)^{\gamma}}{p}\right] p(1-p)

    Distribute p(1−p)p(1-p) into the bracket:

    =γ p (1−p)γlog⁡p  −  (1−p)γ+1= \gamma\,p\,(1-p)^{\gamma}\log p \;-\; (1-p)^{\gamma+1}

    and factor out (1−p)γ(1-p)^{\gamma}:

     dLdz=(1−p)γ(γ plog⁡p+p−1) \boxed{\ \frac{\mathrm{d}L}{\mathrm{d}z} = (1-p)^{\gamma}\Big(\gamma\,p\log p + p - 1\Big)\ }

    Check it reduces correctly. At γ=0\gamma = 0: (1)(0+p−1)=p−1=p−y(1)(0 + p - 1) = p - 1 = p - y, which is I.4.4 ✓.

    Step 4 — evaluate at γ=2\gamma = 2, y=1y = 1.

    zzppCEFLdCE/dz\mathrm{dCE}/\mathrm{d}zdFL/dz\mathrm{dFL}/\mathrm{d}z
    −4.0-4.00.017990.017994.018154.018153.8749073.874907−0.98201-0.98201−1.086396-1.086396
    −2.0-2.00.119200.119202.126932.126931.6500781.650078−0.88080-0.88080−1.076714-1.076714
    0.00.00.500000.500000.693150.693150.1732870.173287−0.50000-0.50000−0.298287-0.298287
    2.02.00.880800.880800.126930.126930.0018040.001804−0.11920-0.11920−0.004871-0.004871
    4.04.00.982010.982010.018150.018150.0000060.000006−0.01799-0.01799−0.000017-0.000017

    Step 5 — read the last column. At z=4z = 4 — an example the model already gets right — cross-entropy still sends −0.01799-0.01799, while focal loss sends −0.000017-0.000017: a thousandfold smaller. At z=−4z = -4 — an example it gets wrong — focal loss sends −1.086-1.086, larger in magnitude than cross-entropy’s −0.982-0.982.

    So focal loss does not merely rescale; it reorders. Under cross-entropy the hard example’s gradient is 55×55\times the easy one’s; under focal loss it is 64,000×64{,}000\times.

    Step 6 — how this differs from class weighting.

    class weighting (I.4.B05)focal loss
    computed fromthe class countsthe current prediction
    fixed during trainingyesno
    distinguishes easy from hardnoyes
    needs countsyesno

    Class weighting asks which class is this? and applies a constant. Focal loss asks how wrong is the model here, right now? and applies a factor that changes every step.

    That difference is exactly the objection raised in I.4.B05’s Where this breaks: static weights correct a static imbalance in a quantity that is not static. Once the model has learned the majority class, those examples’ gradients have already collapsed by (I.4.4), and the fixed weight keeps suppressing them anyway. Focal loss suppresses them because they are easy, and stops suppressing anything that becomes hard again.

    The cost. γ\gamma is a new hyperparameter with no principled setting — the original paper’s γ=2\gamma = 2 was chosen by sweep — and the loss no longer has the log-likelihood interpretation of I.4.T1. It is a heuristic reshaping of a principled loss, and worth using with that clearly in view.

    I.4.X10What a per-example loss cannot encodelimit▲▲▲

    The chapter’s open exercise. Every loss in this chapter has the form 1n∑iℓ(y^i,yi)\frac1n\sum_i \ell(\hat{y}_i, y_i) — a mean of a function of one prediction and one target. Determine what objectives that form structurally cannot express, and give a worked case for at least two of them.

    Hint

    Ask what happens to ℓ\ell if you shuffle the examples, or if you change the prediction for one example while holding the rest fixed.

    Solution

    The structural constraint. Two properties follow from the form alone, before any particular ℓ\ell is chosen.

    Permutation invariance. The mean is unchanged by reordering, so no objective that depends on the order or grouping of examples can be expressed.

    Separability. ∂L/∂y^i\partial L/\partial \hat{y}_i depends on example ii alone. No objective in which the right prediction for one example depends on the predictions made for others can be expressed.

    Everything below is a consequence of one of these two.

    Case 1 — a ranking objective (separability fails)

    The objective. Rank documents so relevant ones come above irrelevant ones. What matters is the relative order of scores, not their values.

    Why it cannot be written per example. Take two documents with true relevance 11 and 00 and scores y^A=0.6\hat{y}_A = 0.6, y^B=0.4\hat{y}_B = 0.4. The ranking is correct. Now consider 0.90.9 and 0.80.8: also correct. And 0.30.3, 0.20.2: also correct. A per-example loss must assign each of these six predictions a value based on that prediction alone, yet the quantity of interest — is AA above BB? — is identical in all three.

    Worse, it can be destroyed by changing only BB: with y^A=0.6\hat{y}_A = 0.6 fixed, y^B=0.4\hat{y}_B = 0.4 is correct and y^B=0.7\hat{y}_B = 0.7 is not. So the correct value for BB depends on AA‘s prediction, which separability forbids.

    Worked numbers. Under per-example squared loss with targets (1,0)(1, 0):

    (0.6,0.4): 12[(0.4)2+(0.4)2]=0.1600(0.6, 0.4): \ \tfrac12\big[(0.4)^2 + (0.4)^2\big] = 0.1600(0.9,0.8): 12[(0.1)2+(0.8)2]=0.3250(0.9, 0.8): \ \tfrac12\big[(0.1)^2 + (0.8)^2\big] = 0.3250

    The loss prefers the first, though both rank correctly and the second is more confident. And:

    (0.5,0.5): 12[(0.5)2+(0.5)2]=0.2500(0.5, 0.5): \ \tfrac12\big[(0.5)^2 + (0.5)^2\big] = 0.2500

    which ranks incorrectly (a tie) yet scores better than (0.9,0.8)(0.9, 0.8), which ranks correctly. The loss and the objective disagree in sign.

    What is done instead. Pairwise losses of the form ℓ(y^A−y^B)\ell(\hat{y}_A - \hat{y}_B), which are per-pair rather than per-example — a different form, with O(n2)O(n^2) terms and a gradient that couples examples.

    Case 2 — a constraint across examples (permutation invariance fails)

    The objective. Predicted probabilities should be calibrated: among examples predicted at 0.70.7, about 70%70\% should be positive.

    Why it cannot be written per example. Calibration is a statement about a set of predictions. For any single prediction there is no fact of the matter — p=0.7p = 0.7 on one example with label 11 is neither calibrated nor miscalibrated. The quantity requires binning, and binning requires seeing the other examples.

    Worked numbers. Ten examples, all predicted p=0.7p = 0.7, of which 77 are positive. Perfectly calibrated. Cross-entropy:

    L‾=7(−log⁡0.7)+3(−log⁡0.3)10=7(0.3567)+3(1.2040)10=2.4969+3.612010=0.6109\overline{L} = \frac{7(-\log 0.7) + 3(-\log 0.3)}{10} = \frac{7(0.3567) + 3(1.2040)}{10} = \frac{2.4969 + 3.6120}{10} = 0.6109

    Now a model predicting p=1.0p = 1.0 for the seven positives and p=0.0p = 0.0 for the three negatives — also perfectly calibrated, and with loss 00. And one predicting 0.70.7 for all ten when only 33 are positive — badly miscalibrated — gives

    3(0.3567)+7(1.2040)10=0.9498\frac{3(0.3567) + 7(1.2040)}{10} = 0.9498

    So the loss does respond to calibration here, but only through accuracy: it cannot distinguish “well calibrated and uncertain” from “poorly calibrated”, because it never sees a group.

    Case 3 — fairness across a subgroup (both fail)

    The objective “the error rate on group A must not exceed group B’s by more than ε\varepsilon” is a constraint on two aggregates. A per-example loss can approximate it with group weights, as I.4.B05 does — but weights control expected contribution, not a realised gap, and the constraint can be violated while every weight is respected. This is the same gap between a surrogate and a target that I.4.X06 exhibited for accuracy.

    The strongest true claim

    A per-example mean is a separable, permutation-invariant objective. Any quantity of interest that is genuinely a property of the set of predictions — an ordering, a rate within a group, a distributional match, a constraint between subgroups — is not in that class, and can only be approached by a surrogate whose disagreement with the target has to be measured rather than assumed.

    Why the form is used anyway. Separability is what makes the gradient computable in one pass and the loss decomposable over a minibatch. Give it up and the gradient of one example requires the others, minibatching becomes an approximation rather than an identity, and the whole training loop changes shape. That is a real cost, and it is why the answer is nearly always a surrogate plus a separately reported metric — which is exactly the discipline Chapter VIII.5 is about.