Transformers, ELI5 · Part 4 / 10

Inside the feed-forward network

Widen, drop the negatives, shrink back. A bank of pattern-detectors that stores most of the model's knowledge.

The is the “think alone” half of a block. Three steps, one token at a time: go wide, filter, come back.

Wide

Multiply the token (width 4) by W_up to make it wider (8 here; ~16,000 in a real model). Each new slot is a detector asking “is this feature here?”

Filter — ReLU

: negative → 0, positive → keep. Only the detectors that fired stay lit.

This bend is the model’s key , and it matters more than it looks: without it, stacking a hundred layers would be no smarter than one — they’d fold into a single multiply. (Real models soften the bend — older ones used a smooth cousin, ; today’s gate it instead, see the panel below.)

Back

Multiply by W_down to fold back to width 4. Each lit detector writes its stored knowledge in.

Step through. Click any cell to see the dot product behind it.

Try it: on × W_up, click a cell to see the multiply-and-add. On ReLU, watch the blue negatives clip to 0. On × W_down, the zeroed detectors add nothing.

see this in PyTorch

After attention mixes tokens together, this little two-layer network thinks about each token on its own: expand it 4x, run it through GELU, then shrink it back.

import torch
import torch.nn as nn
import torch.nn.functional as F

class FeedForward(nn.Module):
    def __init__(self, d_model):
        super().__init__()
        # blow the vector up to 4x its size, so the block has room to "think"
        self.up = nn.Linear(d_model, 4 * d_model)    # d_model -> 4*d_model
        # squeeze it back down to the original size so it fits the next layer
        self.down = nn.Linear(4 * d_model, d_model)  # 4*d_model -> d_model

    def forward(self, x):
        # x: (batch, seq, d_model) -- runs on EVERY token independently, no token sees another here
        x = self.up(x)        # (batch, seq, 4*d_model): expand
        x = F.gelu(x)         # (batch, seq, 4*d_model): smooth on/off switch, keeps the useful signal
        x = self.down(x)      # (batch, seq, d_model): shrink back to normal size
        return x

Attention moves information between words. The FFN is where a lot of it is stored — most of the model’s live here.

Go deeper: what does one detector actually store?

Each wide-layer slot is a little “if you see X, add Y” rule — most of a model’s facts live here. But there are more ideas than slots, so detectors .

Switch the token; click a lit detector to see what it stores.
Go deeper: the modern gated FFN (SwiGLU)

Real models tweak this: instead of a hard ReLU, a adds a second lane — a learned volume knob that multiplies the signal.

Slide the input — the gated lane fades smoothly where ReLU snaps to 0.

Next: stack the block.

Sources · 7