Appendix A: Derivative Reference

Every derivative in this table is derived somewhere in the chapters. They are collected here so you have one page open on a second monitor while writing a backward pass, instead of hunting through thirty of them. The chapter column tells you where the derivation lives when the result alone is not enough.

Notation throughout is the one the book uses. A gradient arriving from above is written ๐‘”, the quantity a layer produced is ๐‘ฆ, and the quantity it received is ๐‘ฅ. Nothing here assumes a batch dimension, because none of the programs in this book carry one.

A.1 Activations

NameForwardDerivativeCh.
Sigmoid๐œŽ(๐‘ฅ)=11+๐‘’โˆ’๐‘ฅ๐œŽ(๐‘ฅ)(1โˆ’๐œŽ(๐‘ฅ))2
Tanhtanh(๐‘ฅ)1โˆ’tanh2(๐‘ฅ)6
ReLUmax(0,๐‘ฅ)1 if ๐‘ฅ>0, else 05
Leaky ReLUmax(๐›ผ๐‘ฅ,๐‘ฅ)1 if ๐‘ฅ>0, else ๐›ผ5
SiLU๐‘ฅ๐œŽ(๐‘ฅ)๐œŽ(๐‘ฅ)(1+๐‘ฅ(1โˆ’๐œŽ(๐‘ฅ)))24
GELU๐‘ฅฮฆ(๐‘ฅ)see A.224
Softmax๐‘’๐‘ง๐‘–โˆ‘๐‘˜๐‘’๐‘ง๐‘˜see A.34

The rectifier has no derivative at zero. Every implementation picks one, and the book picks zero, which matters less than being consistent about it.

A.2 GELU

The book uses the tanh approximation, which is what GPT-2 uses as well as some models after it. Write ๐‘ข=๐‘(๐‘ฅ+๐‘Ž๐‘ฅ3) with ๐‘=2/๐œ‹โ‰ˆ0.7978846 and ๐‘Ž=0.044715.

GELU(๐‘ฅ)=12๐‘ฅ(1+tanh๐‘ข)
GELUโ€ฒ(๐‘ฅ)=12(1+tanh๐‘ข)+12๐‘ฅ(1โˆ’tanh2๐‘ข)๐‘(1+3๐‘Ž๐‘ฅ2)

The second term is the one that gets dropped. Dropping it leaves a derivative that is correct at large positive ๐‘ฅ, wrong near the origin, and plausible enough that training still appears to work.

A.3 Softmax and Cross Entropy

Taken separately, the softmax Jacobian is a full matrix and the cross entropy derivative divides by a probability that can be very small. Taken together, almost everything cancels.

๐œ•๐‘๐‘–๐œ•๐‘ง๐‘—=๐‘๐‘–(๐›ฟ๐‘–๐‘—โˆ’๐‘๐‘—)
๐œ•๐ฟ๐œ•๐‘ง๐‘—=๐‘๐‘—โˆ’๐‘ฆ๐‘—

The second line is the one to remember and the one the code uses. The predicted distribution minus the one hot target, with no division and nothing to guard against. When the loss is a mean over positions rather than a sum, the gradient carries the same divisor, and forgetting that scales every gradient in the model by the sequence length at once.

The first line is still needed wherever softmax appears without cross entropy behind it, which in this book means inside attention. There it is applied as a vector operation rather than a matrix.

โˆ‡๐‘ง๐‘—=๐‘๐‘—(โˆ‡๐‘๐‘—โˆ’โˆ‘๐‘˜๐‘๐‘˜โˆ‡๐‘๐‘˜)

A.4 Normalization

Both normalizers divide by a statistic computed from every component of the input, which is why the backward pass has a correction term rather than being elementwise. Write ๐‘ฅฬ‚ for the normalized activation and ๐‘” for the learned gain.

NameForwardCh.
LayerNorm๐‘”โ‹…๐‘ฅโˆ’๐œ‡๐œŽ2+๐œ€23
RMSNorm๐‘”โ‹…๐‘ฅmean(๐‘ฅ2)+๐œ€23

RMSNorm drops the mean subtraction, which removes one pass over the data and, as it turns out, costs nothing in quality. Every model in the second half of this book uses it.

โˆ‡๐‘”๐‘–=โˆ‡๐‘ฆ๐‘–๐‘ฅฬ‚๐‘–
โˆ‡๐‘ฅ๐‘—=1๐œŽ(๐‘”๐‘—โˆ‡๐‘ฆ๐‘—โˆ’๐‘ฅฬ‚๐‘—โ‹…1๐‘›โˆ‘๐‘–๐‘”๐‘–โˆ‡๐‘ฆ๐‘–๐‘ฅฬ‚๐‘–)

The sum inside the second expression is what couples the components. Leave it out and the gradient points in roughly the right direction, which is the worst possible failure mode because the loss still falls.

A.5 Linear Layers and Attention

For ๐‘ฆ=๐‘Š๐‘ฅ with ๐‘Š of shape ๐‘šร—๐‘›, the three gradients are the ones every backward pass is assembled from.

โˆ‡๐‘Š๐‘–๐‘—=โˆ‡๐‘ฆ๐‘–๐‘ฅ๐‘—,โˆ‡๐‘ฅ๐‘—=โˆ‘๐‘–๐‘Š๐‘–๐‘—โˆ‡๐‘ฆ๐‘–

Attention is these three applied five times with a softmax in the middle. Scores are ๐‘ ๐‘–๐‘—=๐‘ž๐‘–โ‹…๐‘˜๐‘—/๐‘‘โ„Ž, weights are ๐‘๐‘–=softmax(๐‘ ๐‘–) over the unmasked positions, and the context is ๐‘๐‘–=โˆ‘๐‘—๐‘๐‘–๐‘—๐‘ฃ๐‘—.

QuantityGradient
โˆ‡๐‘ฃ๐‘—โˆ‘๐‘–๐‘๐‘–๐‘—โˆ‡๐‘๐‘–
โˆ‡๐‘๐‘–๐‘—โˆ‡๐‘๐‘–โ‹…๐‘ฃ๐‘—
โˆ‡๐‘ ๐‘–๐‘—softmax backward applied to โˆ‡๐‘๐‘–, then divided by ๐‘‘โ„Ž
โˆ‡๐‘ž๐‘–โˆ‘๐‘—โˆ‡๐‘ ๐‘–๐‘—๐‘˜๐‘—
โˆ‡๐‘˜๐‘—โˆ‘๐‘–โˆ‡๐‘ ๐‘–๐‘—๐‘ž๐‘–

A masked position must receive no gradient. The cleanest way to guarantee that is to loop only as far as the diagonal in the backward pass exactly as the forward pass did, rather than computing everything and zeroing afterwards.

A.6 Residuals and Embeddings

A residual connection passes its gradient through unchanged, so the sublayer gradient adds to what is already flowing rather than replacing it. That single property is why deep stacks train, and it is one line of code.

An embedding lookup is a matrix multiply by a one hot vector, so its gradient is a scatter add. The row for the token that appeared accumulates the incoming gradient, and every other row receives nothing. A token appearing several times in one window accumulates several contributions, which is correct and is easy to get wrong by assigning rather than adding.

When the output head is tied to the embedding table, that table receives gradient from two directions in the same step, once as a readout and once as an input. Both contributions must be present. With only one of them the two roles pull against each other and the model cannot train, which Chapter 37 measures directly.

A.7 Optimizers

NameUpdateCh.
SGD๐‘คโ†๐‘คโˆ’๐œ‚โˆ‡๐‘ค5
Momentum๐‘ฃโ†๐›ฝ๐‘ฃ+โˆ‡๐‘ค8
Adamsee below8

Adam keeps a running mean and a running uncentered variance of the gradient, corrects both for the bias introduced by starting them at zero, and divides one by the square root of the other.

๐‘šโ†๐›ฝ1๐‘š+(1โˆ’๐›ฝ1)โˆ‡๐‘ค,๐‘ฃโ†๐›ฝ2๐‘ฃ+(1โˆ’๐›ฝ2)(โˆ‡๐‘ค)2
๐‘คโ†๐‘คโˆ’๐œ‚๐‘š/(1โˆ’๐›ฝ1๐‘ก)๐‘ฃ/(1โˆ’๐›ฝ2๐‘ก)+๐œ€

Defaults of ๐›ฝ1=0.9, ๐›ฝ2=0.999 and ๐œ€=10โˆ’8 are what the paper proposed and what almost everyone still uses. The capstone uses them unchanged.

A.8 Verifying Any of This

None of the formulas above are worth trusting in your own code until you have checked them against the loss they claim to differentiate. Perturb a weight by a small amount in both directions, measure how the loss responds, and compare.

โˆ‡๐‘คโ‰ˆ๐ฟ(๐‘ค+๐œ€)โˆ’๐ฟ(๐‘คโˆ’๐œ€)2๐œ€

Two practical notes. Single precision arithmetic will limit the agreement to a few parts in a thousand, because the difference of two nearly equal float values throws away most of the significant digits. And a per element check is noisiest exactly where the gradients are smallest, which is usually the query and key projections. Perturbing a whole parameter block along one random direction and comparing against the analytic gradient projected onto that direction avoids both problems, and Chapter 37 shows the code.