Skip to content
AI360Xpert
Core ML

Transformer Architecture

Stack blocks of self-attention plus a feed-forward network, each wrapped in a residual connection and normalization, and repeat that same block many times to build the whole model.

One transformer block is attention plus a feed-forward network, each wrapped in a residual connection and a normalization layer, and the whole block repeats N times
One transformer block is attention plus a feed-forward network, each wrapped in a residual connection and a normalization layer, and the whole block repeats N times

Why Does This Exist?

Every piece assembled so far in this band is a part, not a machine. Self-attention mixes information across positions. Positional encoding supplies the order self-attention can't see on its own. Feed-forward networks transform each position's content once it's gathered. None of these, alone, is a working model — self-attention without depth can't build hierarchical representations, and a single feed-forward layer without attention has no way to relate one token to another at all.

The 2017 contribution wasn't any one of these pieces in isolation — recurrent and convolutional sequence models already existed. It was the specific way of combining attention and a feed-forward network into one repeatable block, wrapping that block so it trains reliably at real depth, and showing that stacking many copies of it outperformed the recurrent architectures that had dominated sequence modeling until then, while training dramatically faster because attention parallelizes across the whole sequence.

Think of It Like This

An assembly line where every station does the same two jobs

Picture an assembly line where every single station performs the identical two-step process: first, consult with every other item currently on the line to gather relevant context (attention), then apply a private transformation to what was gathered (the feed-forward network). The line has many stations, all running the same two-step process, but each station's specific weights are learned independently — station 3 might learn to gather very different context than station 20, even though the procedure at every station is identical.

That repeatable two-step station, copied end to end down the line, is the entire transformer architecture. Complexity comes from depth and learned specialization, not from each station doing something structurally different from the last.

How It Actually Works

The block, assembled

The diagram above shows one complete transformer block. Two sub-layers, each wrapped identically:

x=x+SelfAttention(Norm(x)),x=x+FFN(Norm(x))x' = x + \text{SelfAttention}(\text{Norm}(x)), \qquad x'' = x' + \text{FFN}(\text{Norm}(x'))

(This is the pre-norm ordering — pre-norm vs post-norm covers the alternative and why it matters.) Each sub-layer's output is added back onto its own input via a residual connection — the same identity-plus-correction structure that made very deep CNNs trainable, applied here to make very deep transformer stacks trainable. Without it, a stack of dozens of blocks would face the same degradation problem residual connections were invented to fix in the first place.

What repeats, and what doesn't

The block's structure — attention, then feed-forward, each wrapped in a residual connection and normalization — is identical at every layer. The weights inside each block are entirely separate: layer 1's attention projections, layer 1's feed-forward matrices, layer 2's attention projections, and so on, are all independently learned parameters. Stacking NN copies of this one block is what gives a transformer its depth, and NN is a genuine architectural choice — more blocks generally mean more capacity, at a roughly linear cost in compute and parameters per additional block.

Where positional encoding fits

Positional encoding is added exactly once, before the first block, directly to the input embeddings. It is not re-added at every layer — once position is folded into the token representations, it propagates through the stack the same way any other information does, carried along by the residual connections.

Encoder-only, decoder-only, and encoder-decoder

The block described above is the general unit; how many stacks a model builds from it, and whether those stacks use causal masking, defines the three major variants. An encoder-only model (BERT's lineage) stacks blocks with no causal mask, since it's building a representation of a complete input rather than generating one token at a time. A decoder-only model (GPT's lineage) stacks blocks with causal masking throughout, since every position is trained to predict the next token without peeking ahead. An encoder-decoder model runs both stacks, with the decoder additionally using cross-attention to read the encoder's output — the architecture the original transformer paper introduced for translation. Decoder-only became the dominant choice for large language models, largely because a single unified training objective (next-token prediction, everywhere) scales cleanly to enormous unlabeled text corpora in a way that made it the practical winner.

Show Me the Code

One transformer block, composing the pieces from earlier pages, with the residual connections kept visible.

import numpy as np

def layer_norm(x: np.ndarray, eps: float = 1e-5) -> np.ndarray:    mean, var = x.mean(axis=-1, keepdims=True), x.var(axis=-1, keepdims=True)    return (x - mean) / np.sqrt(var + eps)

def transformer_block(x: np.ndarray, attn_fn, ffn_fn) -> np.ndarray:    x = x + attn_fn(layer_norm(x))     # residual + pre-norm around attention    x = x + ffn_fn(layer_norm(x))       # residual + pre-norm around the feed-forward net    return x

def stub_attention(x: np.ndarray) -> np.ndarray:    return x * 0.1                       # stand-in: a real block calls self-attention here

def stub_ffn(x: np.ndarray) -> np.ndarray:    return np.tanh(x) * 0.1              # stand-in: a real block calls the FFN here

x = np.random.default_rng(0).normal(size=(4, 8))for layer in range(3):                    # stack N=3 identical-structure blocks    x = transformer_block(x, stub_attention, stub_ffn)print(x.shape)  # -> (4, 8) — shape is preserved through every block, by construction

Every block preserves the input shape exactly — that's what lets NN identical-structure blocks stack without any reshaping logic between them, regardless of how many layers deep the model goes.

Watch Out For

Assuming more blocks always means a better model

Stacking more transformer blocks increases capacity, but it also increases training difficulty, compute cost, and inference latency roughly proportionally. Past a certain depth for a given amount of training data, additional blocks stop paying for themselves — the model has more capacity than the data can usefully fill, and the marginal block adds cost without adding much quality. Depth is a real design choice with real diminishing returns, not a dial to maximize by default.

Getting the residual-connection wiring wrong when implementing from scratch

A common bug when hand-assembling a block is applying normalization and the sub-layer, but forgetting to add the original input back in — writing x = ffn_fn(layer_norm(x)) instead of x = x + ffn_fn(layer_norm(x)). This still runs and still produces output of the right shape, so nothing crashes, but it silently removes the residual connection that makes deep stacks trainable in the first place, and the model trains measurably worse without any obvious error pointing at why.

The Quick Version

  • A transformer block is self-attention plus a feed-forward network, each wrapped in a residual connection and normalization.
  • The block's structure repeats identically across layers; the learned weights inside each layer are entirely separate.
  • Positional encoding is added once, before the first block, and propagates through the stack via the residual connections.
  • Encoder-only, decoder-only, and encoder-decoder variants differ in which stacks exist and whether causal masking is applied.
  • Decoder-only became the dominant choice for large language models because next-token prediction scales cleanly to large unlabeled corpora.

Related concepts