7 routes42 sections324 units

Unit 1.2 · about 5 h

171 / 324

Stable softmax, cross-entropy and loss reductions

Classification and contrastive objectives call softmax and cross-entropy on raw logits. The naive form overflows on ordinary inputs, and the wrong reduction silently rescales every gradient.

  • derive
  • implement

You can now

  • Derive the per-example cross-entropy with logits as \(-f_y + \log \sum_j e^{f_j}\), and its gradient \(\operatorname{softmax}(z)\) minus one-hot(\(y\)).
  • Implement max-subtracted softmax and log-softmax that never overflow, and binary cross-entropy with logits that never takes log of a rounded sigmoid.
  • State sum, mean and masked-mean reductions exactly: divisor used, and which positions get zero gradient.

Covers

  • Stable softmax and log-softmax
  • Cross-entropy and binary cross-entropy with logits
  • Regression, reconstruction and masked loss reductions

Study, in this order

4 steps

  1. Losses from maximum likelihood
    Understanding Deep Learning - Chapters 3 to 7

    Chapter 5, Sections 5.1 to 5.2 (Eq 5.1 to 5.6, printed pp. 56 to 60) for likelihood to negative log-likelihood; Section 5.3 (Eq 5.7 to 5.15, pp. 61 to 64) for least squares; Section 5.4 (Eq 5.16 to 5.20, pp. 64 to 66) for sigmoid plus binary cross-entropy; Section 5.5 (Eq 5.21 to 5.24, pp. 67 to 69) and Section 5.7 (Eq 5.27 to 5.31, pp. 71 to 72) for softmax plus multiclass cross-entropy

  2. Naive softmax and the spelled-out cross-entropy
    D2L - tensors, autograd, MLP and backpropagation

    The Softmax: the three-step naive code plus the warning that it is not robust and not for serious use; The Cross-Entropy Loss: y_hat[[0, 1], y] indexing and the reduce_mean of negative logs

    Depth · Do not copy the naive softmax or the log-of-probability loss into your own code. Use them only to see what the stable versions below replace.

  3. The max-subtraction trick
    CS231n Linear Classification - Softmax classifier and numeric stability

    Softmax classifier: \(L_i = -f_{y_i} + \log \sum_j e^{f_j}\); Practical issues: Numeric stability: the f -= np.max(f) code turning [123, 456, 789] into [-666, -333, 0]

  4. Masked reductions in `cross_entropy`
    `torch.nn.functional.cross_entropy` - `reduction` and `ignore_index`

    ignore_index and reduction parameters: ignored targets contribute no gradient, and mean averages over the non-ignored targets only

Focus on

  • Max subtraction is exact, not approximate: shifting every logit by \(c\) multiplies numerator and denominator by \(e^c\), which cancels. The largest shifted logit is 0, so every \(\exp\) input is at most 0 and no term overflows.
  • The fused per-example loss is \(L_i = -f_{y_i} + \log \sum_j \exp(f_j)\), and its logit gradient is \(\operatorname{softmax}(z)\) minus one-hot(\(y\)). This matches centered differences to about 1e-9 in float64.
  • Binary cross-entropy with logits must use the log-sigmoid form, never sigmoid followed by log: a confident sigmoid rounds to exactly 0 or 1 and the log is then infinite. Its logit gradient is \(\operatorname{sigmoid}(z) - y\).
  • Mean divides every gradient by \(N\); a masked mean divides by the valid count and gives masked positions exactly zero gradient. D2L cross_entropy uses reduce_mean; UDL least squares (Eq 5.11) sums.

Reproduce closed-book

Closed-book, implement log_softmax with max subtraction and a cross-entropy returning per-example losses plus their mean. Derive \(dL/dz = \operatorname{softmax}(z)\) minus one-hot(\(y\)). Show softmax([1000, 1001, 1002]) = [0.0900, 0.2447, 0.6652], and explain why the naive form returns [nan, nan, nan].

Traps

  • Taking \(\log(\operatorname{softmax}(z))\) in two steps. Even with max subtraction, a very small probability can underflow to 0 and its log becomes -inf. log_softmax(z) = \((z - m) - \log \sum \exp(z - m)\), with \(m\) the max, never forms the probability.
  • Clipping probabilities after a naive softmax to fix overflow. exp(1000) already overflowed to inf and the division already produced nan; clipping cannot recover the true distribution.
  • Expecting the stable answer on [1000, 1001, 1002] to be [1, 0, 0]. Only logit gaps matter, so the result equals softmax([0, 1, 2]): about [0.09, 0.245, 0.665].

Practice

Deep-ML 1227: Numerically Stable Softmax

Implement softmax(t, dim) by subtracting the max along dim. The two platform tests use a small \((2 \times 3)\) tensor along rows and along columns, so they do not exercise overflow.

After it passes, add your own large-logit test: [1000, 1001, 1002] must give [0.0900, 0.2447, 0.6652], and your log-softmax plus mean cross-entropy must stay finite.

TensorTonic: Calculate Squared-Error Loss Gradients (autograd-l08-squared-error-loss-gradients)

Losses, Training, and Zeroing Gradients section: Calculate Squared-Error Loss Gradients

State whether your derivation sums or means over examples, and how that choice scales the gradient.

Self-test

  1. Why does subtracting the maximum logit prevent overflow without changing softmax?

  2. What is the gradient of the per-example cross-entropy with respect to the logits?

  3. A batch of 5 has 2 masked positions under a masked mean. What is the divisor, and what gradient do masked positions get?

  4. Why must binary cross-entropy with logits avoid sigmoid-then-log?

Completion criterion

Stop when

Your fused loss matches centered differences, survives logits of magnitude 1000, and you can state the divisor and the masked-position gradient for sum, mean and masked mean without notes.

Mark passed, then open 1.3 Only mark this when you can do it without notes.

Leads to

Comes after

Resources for this unit

Also in this section

  • TensorTonic - Build Micrograd from Scratch
    TensorTonicrequiredpractice
    Use the 25-problem Micrograd study plan in order for derivatives, gradient checks, value graphs, reverse mode, accumulation, operators, modules, losses and training. Preserve local tests as the evidence instead of a platform score.
  • Deep-ML candidate - autograd and loss problems
    Deep-MLoptionalpractice
    After the five-sample platform check passes, use at most one of 26 Basic Autograd Operations, 997 Manual Cross-Entropy Backprop or 1227 Stable Softmax as a changed-prompt drill.
  • CS231n Neural Networks 3 - Gradient checks
    Stanford CS231nreferencereference
    Read the Gradient Checks section only: centered formula with \(O(h^2)\) error, relative error with thresholds, double precision, step size \(h\) near 1e-5, kinks, few datapoints, burn-in, regularization and dropout discipline, and checking a few dimensions per parameter.
  • PyTorch Broadcasting semantics
    PyTorchreferencereference
    Read General semantics for the trailing-dimension rules, prepend-1 alignment and max-size result, with the (5, 1, 4, 1) plus (3, 1, 1) examples; read In-place semantics for why an in-place tensor may not change shape.
  • `torch.autograd.gradcheck` API and tolerances
    PyTorchreferencereference
    Read the gradcheck signature defaults (eps 1e-6, atol 1e-5, rtol 1e-3) and the note that inputs with overlapping memory, such as expand outputs, will likely fail the check.
  • PyTorch Tensor Views
    PyTorchreferencereference
    Read the view and storage sharing example (data_ptr, mutating the view changes the base), the transpose non-contiguous example, the full view-ops list, and the special notes: reshape may copy, contiguous copies only when needed, basic indexing returns views while advanced indexing copies.
  • `torch.Tensor.stride` - stride and storage offset
    PyTorchreferencereference
    Read the stride definition: strides are per-dimension element steps, and with storage_offset they locate every element. Combine with the Tensor Views page for transposed and expanded layouts.
  • PyTorch Autograd mechanics - in-place operations
    PyTorchreferencereference
    Read In-place operations with autograd (why in-place rewrites the graph and is discouraged) and In-place correctness checks (the version counter and the error on accessing a modified saved tensor).
  • `torch.nn.Module` - parameters, buffers and state
    PyTorchreferencereference
    Read the parameters and buffers documentation: modules collect parameters recursively for the optimizer, while register_buffer holds persistent non-parameter tensors saved alongside them.

Quick find

Search Michi

Type to search every route, section, unit, topic and resource.

Enter opens the first result Esc closes

Reference

Keyboard shortcuts

n
Continue to the first unit not passed
j / k
Next / previous unit
1 2 3
Toggle learned, practised, passed
/
Open search
?
Show this help
Esc
Close open panels