A layer is a structural assumption about the data; each layer here fixes a specific failure of the one before, and most of those failures trace to one fact: the gradient reaching layer 1 of an L-layer stack is a product of L Jacobians, which vanishes (factors < 1) or explodes (factors > 1).
Pick a layer by input structure
Read a row as: this layer maps this shape, betting this is true; when it is false, this breaks.
| Layer | Shape in → out | Bet | Failure when false |
|---|---|---|---|
Dense (Wx+b) | (in) → (out) | each coordinate has fixed meaning | no prior; params = in·out + out explode |
| Convolution | (H,W,C_in) → (H',W',C_out) | patterns are local, position-invariant | blind past receptive field; only translation shared |
| Pooling | (H,W,C) → (H/2,W/2,C) | exact position in window irrelevant | loses where (detection, segmentation) |
| Recurrence | (n,d_in) → (n,d_h) | past compresses to fixed vector, order matters | no long-range gradient; sequential (no parallel) |
| Attention | (n,d) → (n,d) | relevance decided by content | O(n²) cost; no position unless injected |
| Embedding | (n) ints → (n,d) | tokens are discrete symbols | rare tokens stay near random init |
- Prior = assumption wired in instead of learned. A strong prior saves data. Tabular data (no structure) → dense, but gradient-boosted trees usually win.
Depth beats width
- ReLU net is piecewise-linear; count pieces (linear regions) to count expressive power.
- One hidden layer of width
w: at mostw+1pieces (width adds kinks linearly). - The fold
|2x−1|copies its input range onto the output twice, so composing doubles pieces:Lfolded layers →2^Lpieces. Width adds, depth composes. - Montúfar 2014 bound:
Ω((w/d_in)^(d_in·(L−1)) · w^d_in)regions —Lin the exponent,win the base. Exponential in depth, polynomial in width. - Expressivity ≠ learnability. A plain 50-layer net can represent more than a 10-layer one but trains worse (gradient dies through 50 Jacobians). Residuals + normalization make depth trainable.
Convolution and receptive field
- Kernel of
k×k,C_in→C_out: params= k²·C_in·C_out + C_out. (3×3, 3→64 = 1,792 vs 150M for the equivalent dense layer, ~84,000× fewer.) - Weight sharing → translation equivariance (shift input, output shifts identically). Invariance to shift comes from pooling on top, not conv.
- Receptive field recurrence — update
rwith the incomingj, then updatej:r_l = r_{l−1} + (k_l − 1)·j_{l−1}thenj_l = j_{l−1}·s_l- Ordering trap: advance
jbeforerand every laterris wrong.
- A 3×3 conv adds
(k−1)·j = 2jtor; a stride-2 pool adds onlyjdirectly but doublesj, so downsampling (not depth) buys global context cheaply. samepadding never changesrorj. Dilationdcoversd·(k−1)+1pixels withkweights at full resolution.
Recurrence → LSTM/GRU
- RNN:
h_t = tanh(W·h_{t−1} + U·x_t + b), weights shared across time. - Vanishing gradient is an exponential: per-step Jacobian
D_t·W, so‖dL_T/dh_k‖ ≤ (max|tanh'|·‖W‖)^(T−k) = s^(T−k). Withs ≈ 0.84:0.84^100 = 2.7e-8(dead). Nosstays put for allT. - Exploding side is the easy one: gradient clipping rescales a too-large norm (threshold ~1.0). Nothing recovers an underflowed gradient.
- LSTM replaces the matrix product with an additive cell state:
c_t = f_t ⊙ c_{t−1} + i_t ⊙ g_t, sodc_t/dc_{t−1} = diag(f_t)— numbers the net chooses per step/channel.f=0.99→0.99^100 = 0.37survives.- Gates: forget
f, inputi, outputo(allsigmoid, “fraction to keep”), candidateg(tanh, “value to write”). - Params
= 4·(d_in·d_h + d_h² + d_h). Initb_fto 1.0–2.0 so the untrained gate starts atsigmoid(1)=0.73, not0.50.
- Gates: forget
- GRU: 2 gates (update, reset), 1 state,
3·(…)params (25% fewer).ztrades forget vs write off against each other. - What killed recurrence: parallelism, not gradients (attention trains all positions in one matmul). Recurrence still wins fixed memory: state is
O(1)per token vs a KV cache’sO(n).
Attention
- Derived from a dict lookup by removing what blocks gradients: hard
argmax→ soft match (q·k) → softmax → convex combination of values. attention(Q,K,V) = softmax(Q·Kᵀ / √d_k)·V, withq_i=W_q x_i,k_i=W_k x_i,v_i=W_v x_i(same 3 matrices at every position).q=what I ask,k=what I advertise,v=what I hand over;W_q≠W_kso a token can ask ≠ offer.- Dot product
= ‖q‖‖k‖cos θ: relevance is an angle. √d_kis forced. With unit-variance components,Var(q·k)=d_k, sosd=√d_k(11.3 atd_k=128). Unscaled → near one-hot softmax →p(1−p)≈1e-5gradient (frozen forward and backward). Dividing by√d_krestores unit variance; dividing byd_kover-corrects → uniform weights.- Causal mask: set future scores to
−∞before softmax (soe^{−∞}=0and surviving weights still sum to 1). Zeroing after leaves rows summing to <1. - Multi-head:
hheads of widthd/h, total params4·d²regardless ofh(thehcancels) — heads partition a fixed projection, trading per-head resolution for reading several places at once. - Attention is permutation-equivariant: it cannot tell word order → inject position (sinusoidal/learned encodings, or RoPE).
Transformer block and parameter arithmetic
- Block = 2 sublayers, each wrapped in a norm + residual add: attention (moves info between positions) and FFN
d→4d→d(transforms within a position). Params: attention4d², FFN8d²→12·d²per block. - Residual
y = x + F(x): JacobianI + dF/dx, so∏(I+J_l)always has a bare-Iidentity path → gradient floor ≥ 1, can’t decay inL. Also lets a block learnF=0(adding depth can’t raise train loss); acts as an ensemble of2^Lpaths. - Pre-LN
x + Sublayer(LN(x))keeps the residual stream a true identity → deep stacks train without careful init (post-LN puts norm on the path and needs warmup). Warmup still mandatory. Residual stream variance grows as1+2L→ final norm before unembedding is required. - Normalization
(x−μ)/√(var+eps)·gain+bias; layers differ only in the reduction axis. LayerNorm/RMSNorm reduce overDper token → identical train/inference, work at batch 1. BatchNorm reduces overB,Tper channel → depends on batch-mates, breaks on variable length, batch-1 decoding, and gradient accumulation. RMSNorm drops mean + bias (x/√(mean(x²)+eps)·gain), one pass cheaper (norms are memory-bandwidth bound). - Dying ReLU: if
z<0on all data, gradient is 0 forever (absorbing state) — usually from too-high lr. Fix: lower lr/warmup, GELU/SiLU/LeakyReLU, He init, normalization. SwiGLU (current default) uses 3 matrices, sod_ff = (8/3)·d(rounded to a tile multiple, e.g. 11,008). - Wiring decides the job: encoder-only (BERT, bidirectional, ~15% positions supervised) → representations; decoder-only (GPT, causal, 100% supervised) → generation; encoder-decoder (T5) → seq-to-seq. Decoder-only won on supervision density (6.7×) + one stack + prefix caching + in-context learning.
params ≈ 12·L·d² + V·d. Compute: forward2NFLOPs/token, training6N. Attention dominates FFN only pastn = 6dtokens. KV cache= 2·L·d_kv·bytesper token (512 KiB/token atd=4096, fp16); GQA shares KV heads for a 4× cut, MQA for 32×.
flowchart TD
IN{"input structure?"}
IN -->|"none, tabular"| D["Dense (or GBT)"]
IN -->|"local patterns"| C["Convolution"]
IN -->|"sequence"| Q{"dependency length?"}
Q -->|"short, streaming, fixed memory"| R["RNN / LSTM / GRU"]
Q -->|"long, train in parallel"| A["Attention"]
style A fill:#2d6a4f,color:#fff