AI / ML Theory
Chapter 6 · 18 min

6.8 — The feed-forward block (position-wise MLP)

Goal: Define the FFN sub-layer, FFN(x) = W₂ σ(W₁ x + b₁) + b₂, applied independently per position; understand the standard d_ff = 4d expansion; count its parameters (8 d²) and FLOPs; place it as the per-position counterpart of attention's cross-position mixing.

1. Why this session exists

The attention sub-layer of 6.4–6.7 does one thing: it lets each token gather a content-addressed mixture of values from across the sequence. That is cross-position mixing — a linear operation in the value space, weighted by attention.

That is not enough. A purely-linear cross-position operation cannot, by itself, build complex per-position representations: an attention output is a convex combination of values, which lives in the convex hull of the value rows. To make the model represent compositional structure — "this is a noun phrase head with these modifiers" — we need a per-position non-linear feature transformer sitting next to attention.

That role is played by the feed-forward network (FFN) sub-layer: a two-layer MLP applied independently at each position. It is the second of the two sub-layers in every Transformer block. The pair "attention + FFN" is the fundamental computational unit of the architecture, and FFN holds more parameters than attention in every standard Transformer — typically 2/3 of the parameters of a block.

This session defines the FFN, motivates the standard "expand-to-4d4d, contract back" shape, counts the parameters and FLOPs, and connects to the per-position role that makes it complementary to attention.[1, 4]


2. The FFN formula

Let x∈Rdx \in \mathbb{R}^d be the hidden representation of a single token at one position. The standard Transformer FFN, as in AIAYN, is a two-layer MLP with a non-linearity in the middle:

 FFN(x)=W2 σ(W1x+b1)+b2, \boxed{\ \text{FFN}(x) = W_2\, \sigma(W_1 x + b_1) + b_2, \ }

with weight matrices

W1∈Rdff×d,W2∈Rd×dff,W_1 \in \mathbb{R}^{d_\text{ff} \times d}, \qquad W_2 \in \mathbb{R}^{d \times d_\text{ff}},

and biases b1∈Rdff,b2∈Rdb_1 \in \mathbb{R}^{d_\text{ff}}, b_2 \in \mathbb{R}^{d}. The non-linearity σ\sigma in AIAYN was ReLU; modern LLMs use GELU (GPT-3, BERT) or SwiGLU/GeGLU (LLaMA, Mistral) — these gated variants are deferred to [8.4] and slightly change the formula, but the shape of the block remains: expand to dffd_\text{ff}, apply non-linearity, contract back to dd.

2.1 "Per-position": what it means

Although we wrote FFN(x)\text{FFN}(x) for a single position, in practice we apply it to all TT positions of a sequence by batching. For an input tensor X∈RT×dX \in \mathbb{R}^{T \times d} representing TT tokens, the FFN sub-layer computes

FFN(X)t=W2 σ(W1Xt+b1)+b2,t=1,…,T.\text{FFN}(X)_t = W_2\, \sigma(W_1 X_t + b_1) + b_2, \qquad t = 1, \dots, T.

Crucially, the same W1,W2,b1,b2W_1, W_2, b_1, b_2 are used at every position, and there is no mixing between positions. The FFN is a position-wise operation: it transforms each row of XX independently.

This is what makes the FFN structurally orthogonal to attention. Attention mixes across positions but cannot do per-token non-linear transformations; FFN does per-token non-linear transformations but cannot mix across positions. Together, in alternating sub-layers, they cover both axes of the computation.


3. Why dff=4dd_\text{ff} = 4d?

The standard choice in AIAYN, and in every Transformer since, is

 dff=4d. \boxed{\ d_\text{ff} = 4 d. \ }

The number 4 is empirical, not derived from a theorem. Three observations make it stable:

(a) Wider hidden layer = more capacity. The MLP's expressive power scales with dffd_\text{ff} (more units in the hidden layer = more learnable features). Increasing dffd_\text{ff} improves model quality monotonically, but at quadratic cost in parameters: #θFFN=2d⋅dff+dff+d\#\theta_\text{FFN} = 2 d \cdot d_\text{ff} + d_\text{ff} + d.

(b) Compute parity with attention. With dff=4dd_\text{ff} = 4d, the FFN block has ∼8d2\sim 8 d^2 parameters per layer. The attention sub-layer has ∼4d2\sim 4 d^2. So the FFN holds about twice the parameter count of attention per block — a 2:1 ratio that the field has settled on. (For models with SwiGLU and three FFN matrices, the ratio is closer to 3:1; see 8.4.)

(c) Hardware-friendly shape. 4d4d is a "nice" number for GEMM on GPU. Anything substantially larger costs proportionally more memory; anything smaller hurts quality. Some recent models (PaLM, GPT-NeoX) experimented with dff∈[2d,8d]d_\text{ff} \in [2d, 8d] but always returned to roughly 4d4d as the sweet spot.

When LLMs were scaled up, the field generally kept dff=4dd_\text{ff} = 4d and increased both dd and the number of layers LL together. The Chinchilla scaling laws (7.12) ratify this as the compute-optimal choice.


4. Parameter count

For the standard FFN with dff=4dd_\text{ff} = 4d:

 #θFFN=2⋅d⋅4d  +  4d+d  =  8d2+5d. \boxed{\ \#\theta_\text{FFN} = 2 \cdot d \cdot 4d \;+\; 4d + d \;=\; 8 d^2 + 5d. \ }

The bias terms are an additive ∼d\sim d correction; in modern LLMs (e.g. LLaMA) they are often omitted, leaving 8d28 d^2. Compare with the attention sub-layer's 4d24 d^2 (6.4 §3). One Transformer block therefore has

#θblock≈4d2+8d2=12d2\#\theta_\text{block} \approx 4 d^2 + 8 d^2 = 12 d^2

parameters (no biases, no norms). For LLaMA-7B (d=4096d = 4096): 12⋅40962≈2×10812 \cdot 4096^2 \approx 2 \times 10^8 params per block, times 32 layers ≈6.4×109\approx 6.4 \times 10^9. Add the embedding matrix V⋅dV \cdot d and the output projection (tied with embedding), and you reach ∼6.7×109\sim 6.7 \times 10^9 — the canonical "7B" headline number.


5. FLOPs and the per-position cost

For a sequence of length TT:

#FLOPsFFN=2⋅T⋅d⋅dff+2⋅T⋅dff⋅d=4Td dff=16Td2.\#\text{FLOPs}_\text{FFN} = 2 \cdot T \cdot d \cdot d_\text{ff} + 2 \cdot T \cdot d_\text{ff} \cdot d = 4 T d\, d_\text{ff} = 16 T d^2.

(Each matrix multiply contributes 2Tddff2 T d d_\text{ff} FLOPs counting multiply+add; the non-linearity is comparatively free.) Compare with attention's ∼4T2d\sim 4 T^2 d FLOPs per layer (6.4 §3.1).

The cross-over is at T=4dT = 4d. For T<4dT < 4d the FFN dominates; for T>4dT > 4d, attention does. For LLaMA-7B (d=4096d = 4096), this is T=16,384T = 16{,}384 — a longer context than the original training window of 2048. So at standard pretraining context lengths, FFN compute dominates. Long-context inference shifts the balance to attention; this is the structural reason "attention is expensive at long context" is the headline cost figure but "FFN is expensive at short context" is the unsung counterpart. We will revisit this when we count compute in 6.12 (Part 2).


6. The FFN as a "feature memory"

A useful way to read the FFN: each row of W1W_1 is a pattern detector on the input xx (the row is a vector in Rd\mathbb{R}^d; its inner product with xx scores a particular feature). The non-linearity σ\sigma then gates the response. Each column of W2W_2 is a feature contribution — when the corresponding hidden unit fires, the column is added (scaled) to the output.

Schematically:

FFN(x)=∑i=1dffW2[:,i]⋅σ(W1[i,:] x+b1[i])+b2.\text{FFN}(x) = \sum_{i = 1}^{d_\text{ff}} W_2[:, i] \cdot \sigma\big( W_1[i, :]\, x + b_1[i] \big) + b_2.

The dffd_\text{ff} hidden units each define a "(detector, contribution)" pair: detect a feature in xx, contribute a vector to the output. This view has been formalised by Geva, Schuster, Berant & Levy (2021)[2], who showed that FFN weights in trained Transformers behave like an associative memory: W1W_1 rows act as keys, W2W_2 columns as values, and the FFN as a key-value lookup mediated by the non-linearity.

This is the same structural pattern as attention — a key-value lookup — except the keys and values are fixed weights (learned at training time) rather than computed from the input. Attention is a runtime lookup against the sequence; FFN is a parametric lookup against memorised features.

The two together — runtime cross-position retrieval (attention) and per-position parametric memory (FFN) — are why a Transformer can both "look at what's in the input" and "look at what it knows." Modern interpretability papers (Cap 11) often map model behaviour to these two complementary mechanisms.


7. Why per-position, not cross-position?

A natural question: why doesn't the FFN mix across positions too? It could, in principle — a "global" FFN would take X∈RT×dX \in \mathbb{R}^{T \times d} as a flattened vector of dimension TdT d and apply a dense MLP to it.

It doesn't, for three reasons:

(a) Parameter explosion. A dense MLP from TdT d to TdT d has T2d2T^2 d^2 parameters — quadratic in sequence length. For T=2048,d=4096T = 2048, d = 4096: ∼7×1013\sim 7 \times 10^{13}, infeasible.

(b) Position-coupling is attention's job. Cross-position mixing is what attention is for. Re-doing it in the FFN would be redundant and would re-introduce the parameter-count and translation-symmetry pathologies that attention was designed to avoid.

(c) Per-position structure is the right inductive bias. Once attention has mixed the relevant cross-position information into each position's representation, the FFN's job is to transform that representation, position-by-position. The two operations sit naturally on orthogonal axes of the computation.

The discipline is general: in a Transformer block, every operation is either per-position (FFN, layer norm, activation) or cross-position (attention). Mixing the two would over-couple the design.


8. What we keep going forward

The FFN sub-layer is one line of math:

FFN(x)=W2 σ(W1x+b1)+b2,dff=4d.\text{FFN}(x) = W_2\, \sigma(W_1 x + b_1) + b_2, \qquad d_\text{ff} = 4 d.

Applied position-wise. ∼8d2\sim 8 d^2 parameters. Dominates compute at short context; underweighted at long context. Functions as a parametric key-value memory complementary to attention's runtime retrieval.

We now have every piece of one Transformer block. Part 2 stacks them: residual connections (6.9), pre-norm vs post-norm (6.10), the complete block + the Attention Is All You Need read (6.11), compute counting (6.12), long-context variants (6.13), KV cache (6.14), hand-written numpy attention (6.15), and the nanoGPT walkthrough (6.16).

Self-test

(a) Confirm the parameter count #θFFN=8d2+5d\#\theta_\text{FFN} = 8 d^2 + 5d by counting the entries of W1,W2,b1,b2W_1, W_2, b_1, b_2 for dff=4dd_\text{ff} = 4d.

(b) Compute the FFN FLOPs for one forward pass of LLaMA-7B (d=4096,T=2048d = 4096, T = 2048): 16Td216 T d^2. Compare with the attention FLOPs ∼4T2d\sim 4 T^2 d. Which dominates at this TT? At what TT would attention dominate?

(c) Write the FFN forward pass for a small example: d=2,dff=4,W1=(100111−11),W2=(10100101)d = 2, d_\text{ff} = 4, W_1 = \begin{pmatrix} 1 & 0 \\ 0 & 1 \\ 1 & 1 \\ -1 & 1 \end{pmatrix}, W_2 = \begin{pmatrix} 1 & 0 & 1 & 0 \\ 0 & 1 & 0 & 1 \end{pmatrix}, biases zero, σ=\sigma = ReLU. Compute FFN((1,0))\text{FFN}((1, 0)) and FFN((0,1))\text{FFN}((0, 1)).

(d) Argue why a "global" FFN that mixes across positions would be redundant with attention. What would happen to the Transformer's translation-equivariance/position-handling story?

(e) A SwiGLU FFN replaces the single W1W_1 matrix with two parallel matrices W1,W3W_1, W_3 used as SwiGLU(x)=(W3x)⊙Swish(W1x)\text{SwiGLU}(x) = (W_3 x) \odot \text{Swish}(W_1 x). Argue that this triples the "expand" parameter count relative to standard FFN. To keep the total parameter count constant in modern LLMs, what is typically done to dffd_\text{ff}?


References

  1. [1]

    Vaswani, A., Shazeer, N., Parmar, N., et al. (2017). "Attention is all you need". NeurIPS. arXiv:1706.03762 — The Transformer paper. Scaled dot-product attention (6.2), multi-head attention (6.4), encoder–decoder cross-attention (6.3), sinusoidal positional encoding (Appendix 6.A), the FFN sub-layer (6.8), post-LN block diagram (6.10), full architecture read (6.11).

    ↩
  2. [2]

    Geva, M., Schuster, R., Berant, J., & Levy, O. (2021). "Transformer feed-forward layers are key-value memories". EMNLP. arXiv:2012.14913 — FFN as parametric associative memory (6.8 §6).

    ↩
  3. [3]

    Shazeer, N. (2020). "GLU variants improve Transformer". arXiv:2002.05202 — SwiGLU / GeGLU; modern FFN variant (6.8 Aside; full treatment in Cap 8.4).

    ↩
  4. [4]

    Alammar, J. (2018). "The illustrated Transformer". jalammar.github.io — Canonical visual walkthrough (6.4, 6.8).

    ↩