hyunwoongko/transformer: The Transformer Repo That Reads Like the Paper

A from-scratch PyTorch build that turns multi-head attention, masking, and positional encoding into a file tree you can actually follow.

8 to 10 min read View on GitHub More from hyunwoongko

A wide workshop table where a paper blueprint has been turned into a physical machine. Modules for embedding, attention, masking, and decoder sit on the table and connect back to a manuscript labeled Attention Is All You Need. It explains that this repository makes the model legible by mirroring the architecture in code.
This repo works because it behaves like a guided tour of the Transformer, not a black box wrapper around one.

I implemented the Transformer model of Google Brain using Pytorch. It was specially written together in very detailed and easy explanatory comments. If you're a beginner who wants to implement Transformer, look at my code and try it!

hyunwoongko, Project Creator · r/MachineLearning post
Key Takeaways

Why this repo still works as a Transformer tutorial

Most Transformer repos teach by abstraction. This one teaches by exposure. It does not wrap the model in a polished API and call it a day. It walks you through the architecture in the same order the paper does, which makes the code feel less like a framework and more like a diagram you can run.

That matters because the Transformer is easy to name and hard to internalize. The real lesson is not that attention replaced recurrence. It is how the pieces fit together: embeddings, positional signals, masked decoder attention, feed-forward blocks, and the final projection back to tokens.

A codebase that mirrors the paper

The folder structure mirrors the paper’s mental model, which lowers the cost of learning each component in isolation.

The repository is organized the way a careful teacher would outline the model. `models/embedding` handles token and positional encoding. `models/layers` contains the atomic math, including multi-head attention and layer normalization. `models/blocks` assembles encoder and decoder layers, and `models/model` ties the whole thing together.

That hierarchy matters more than it sounds like it should. When the file tree matches the conceptual stack, you stop hunting for the implementation and start reading the architecture as a sequence of decisions.

LayerWhat it doesWhy it helps learners
embeddingToken and positional inputKeeps the first step visible
layersAttention, normalization, math primitivesShows the core equations directly
blocksEncoder and decoder layer assemblyExplains how parts compose
modelFull Transformer orchestrationMakes end-to-end flow obvious

The most important trick is hidden in the tensors

A close-up mechanical diagram of tensor blocks splitting into parallel lanes, each lane representing an attention head. A triangular gate blocks future positions on the decoder path, then the lanes rejoin into a single output stream. It explains how reshaping and masking make multi-head attention work without leaking future tokens.
The heart of the implementation is not a fancy class hierarchy. It is the tensor choreography inside attention.

The key move is not conceptual. It is tensor reshaping. The code projects inputs into Q, K, and V, then splits those matrices across heads with `view` and `transpose`, so every head can run in parallel on the GPU. After attention is computed, the heads are concatenated back into one stream and projected again.

That is the part many readers miss when they first learn attention. The innovation is mathematically elegant, but the implementation story is brutally practical: reshape, split, mask, merge.

# Conceptual shape flow in multi-head attention
Q = linear_q(x)   # [batch, seq, d_model]
K = linear_k(x)
V = linear_v(x)

Q = split_heads(Q)  # [batch, heads, seq, d_k]
K = split_heads(K)
V = split_heads(V)

scores = (Q @ K.transpose(-2, -1)) / math.sqrt(d_k)
scores = scores.masked_fill(triangular_mask == 0, float('-inf'))
weights = softmax(scores, dim=-1)

context = weights @ V
context = concat_heads(context)  # [batch, seq, d_model]
out = linear_out(context)

The target mask is the quiet hero here. `torch.tril` builds the lower triangular pattern that prevents the decoder from seeing future tokens during training. Without that gate, the model would cheat. With it, the training signal matches the real task: predict the next token from the ones already available.

Pedagogical purity comes with rough edges

A hedcut-style portrait of Hyunwoong Ko based on his GitHub avatar. It adds a human face to the repository’s warning that the code is a learning artifact, not a perfect reference implementation.

That README warning is not a disclaimer you skip past. It is the point. The repo is a learning artifact from the period when Transformer implementation was still being actively decoded by individual developers, and you can feel that in the code.

Some choices are intentionally didactic. The custom layer norm makes the normalization math visible. The fixed sinusoidal positional encoding sticks close to the paper. The training stack leans on legacy `torchtext`, which is less convenient today but historically explains how many people first got these examples running.

ChoiceWhat it buysWhat it costs
Custom LayerNormShows the math directlyLess optimized than native PyTorch
Fixed sinusoidal positionsMatches the paper closelyLess flexible than learned embeddings
Legacy torchtextFits the era of the projectHarder to run on modern setups
Simple training scriptEasy to followLess production-ready

What modern Transformer code usually abstracts away

Dimensionhyunwoongko/transformerModern higher-level implementation
Level of abstractionLow enough to inspect every stepHigher, with many internals hidden
Readability for learnersVery strongOften better for users than learners
Fidelity to the original paperClose and explicitUsually adapted to newer conventions
Ease of running todayMay need refactoringUsually smoother
Masking and head reshapingExposed directlyOften tucked inside helpers
Maintenance burdenHigherLower

This is where the repo earns its status as a reference point rather than a production template. It exposes exactly the things modern libraries tend to hide: the masks, the head reshaping, the positional signal, the layer assembly. That makes it slower to use, but faster to understand.

So the comparison is not about winners. It is about intent. Modern implementations optimize for ergonomics and deployment. This one optimizes for learning, and it succeeds because those goals are not the same.

Why this repository became a reference point

The repo became memorable because it did something rare: it made a breakthrough architecture feel approachable without pretending the details did not matter. It is both a tutorial and a timestamp. A tutorial, because it teaches the moving parts cleanly. A timestamp, because it captures a moment when the Transformer was still new enough that people were learning it by rebuilding it from scratch.

That is why the code still matters. Not because it is the fastest or cleanest implementation you can find, but because it shows how a generation of developers learned to think in attention.