Tokenizing Text for a GPT Model
DummyGPTModel is a simplified GPT-style nn.Module. It builds token and positional embeddings, dropout, a stack of transformer blocks, a final layer normalization, and a linear output head.
Try it: Text Vectorization: Tokens to Vectors
The text-to-tensor pipeline: standardize, split into tokens, build a frequency-ranked vocabulary with padding and [UNK], map tokens to integer ids, pad or truncate, then one-hot or multi-hot encode and look the ids up in an embedding table.
How it works
- Standardize: lowercase and delete punctuation.
- Split on whitespace into tokens.
- Build the vocabulary: 0 = padding, 1 = [UNK], then words by frequency (ties: first appearance), capped at max tokens.
- Map each token to its id (1 if it did not make the vocabulary), then pad with 0 or truncate to the sequence length.
- Encode: one-hot rows per position or one multi-hot row per text; embed: id k selects row k of the embedding table.
Default run (18 steps): Raw text (59 characters): "The movie was great. The plot was great, the acting wasn't!". A model cannot read strings, so it is turned into numbers step by step. … Embedding lookup: id k selects row k of a fixed 8 x 3 table, giving a (8, 3) dense matrix instead of (8, 8) sparse one-hots. Row 0 (padding) is looked up too; a trained Embedding layer would learn these rows.
Simplified: Bounded ASCII text (up to 200 characters, 40 tokens), whitespace splitting only, and a small FIXED embedding table (a real Embedding layer learns its rows). The multi-hot vector keeps the padding slot (always 0) so its positions line up with the ids.
Loading the simulation…
Running the Model Before Explaining It
This article starts from running code rather than from a definition. The model you will meet is a class called DummyGPTModel. It is a stripped-down, GPT-style network built with PyTorch. Some of its internal parts are deliberately fake, so the code runs from start to finish even though those parts do no real work yet. The plan for this lesson is to run the accompanying listing, observe what comes out, and then use a step-by-step trace to explain every value you saw.
The source material describes the model's behavior in prose rather than reproducing its full listing, so this article explains the structure and data flow that the class is built around. When you run the listing yourself, use the trace in the sections below to account for each stage. If an output looks wrong, the same trace tells you where to look.
Tracing the Forward Pass in Order
The model receives a tensor of integer token indices, called in_idx. Those indices are not meaningful to the network as plain integers, so the model first converts them into vectors. After that conversion, the data passes through a fixed sequence of stages: the embeddings, a dropout layer, a stack of transformer blocks, a final normalization, and the output head. The forward method is the single place where this order is written down, so reading it from top to bottom gives you the data flow.
Read the diagram as a chain of hand-offs. Each box is a named component of the class, and each arrow is the value passed from one stage to the next. The stage that matters most for debugging is the first one, because every later stage depends on the vectors it produces. If the embeddings are wrong, nothing downstream can fix them.
Building the Input Vectors from Two Tables
The model turns each integer index into a vector in two separate ways and then adds the results together. A token embedding maps each token index to a vector, which tells the model what the token is. A positional embedding maps each position in the sequence to a vector, which tells the model where that token sits. Because the two tables are indexed differently, one answers the question what and the other answers the question where.
The forward method adds the two tensors element by element. The result has the same shape as either input, so the next stage receives one combined vector per token position. This is why the sum can be passed directly onward without any reshaping. The source also states that the sum is taken before any dropout is applied, so dropout operates on the combined vector and not on either embedding alone.
Why the Placeholders Change Nothing
After the embeddings are summed, the data moves through four more stages. Two of them are placeholders. The class DummyTransformerBlock and the class DummyLayerNorm each accept whatever they are given and return it without modification. Their constructors accept a configuration or a normalized shape, so they match the interface of the real components. They keep no logic, so the value that goes in is the value that comes out.
The transformer blocks are gathered into an nn.Sequential container. The container is built from a list comprehension that creates n_layers copies of the placeholder, and each copy receives the output of the previous one. Because every copy is an identity operation, the whole stack is also an identity operation. Adding more layers does not change the data, because passing a value through an identity any number of times still returns that value. The final normalization is a single placeholder, so it adds nothing either.
The only stage that transforms the data at the end is the linear output head. It maps each position's embedding vector to a score for every token in the vocabulary, and those scores are called logits. In this placeholder version, the logits therefore come directly from the summed embeddings and the output head. The placeholders in between have no effect, which is what makes the trace below manageable.
Notice also what this implies about where to look. If the logits look surprising, the placeholders cannot be the cause in this version, because they pass values through untouched. The suspects are the stages that actually compute something: the embedding lookups, the sum, and the output head.
Nested Components Inside One Module
DummyGPTModel is a single nn.Module, but it contains several sub-components. Its construction builds the token and positional embeddings, a dropout layer, a stack of transformer blocks, a final layer normalization, and a linear output head. The forward method then calls these parts in order. Seeing this as a containment structure helps you know which part owns which values when you inspect the model.
Finding Where an Unexpected Output Starts
When the output is not what you expected, the source's advice is to compare intermediate tensors stage by stage in forward-pass order. You are looking for the first stage where the result diverges from what you expect. Earlier stages are checked first, because a divergence in an early stage carries forward into every later one. This turns a vague problem, the output looks wrong, into a short sequence of concrete checks.
Tracing a surprising logits tensor
You run the model and the logits do not match what you expected from the lesson's description. Use the forward-pass order to find the first stage where the result diverges. The example below is generated for practice and does not reflect the actual listing output.
- 1Check the input indices
Confirm that
in_idxholds the integer token indices you intended to pass. If the input is wrong, every later stage will be wrong for a reason that has nothing to do with the model. - 2Check the token and positional embeddings
Inspect the two embedding outputs separately. Each should have one vector per token position. Verify that the positional vectors correspond to the positions you expect.
- 3Check the summed embeddings
Confirm that the sum has the same shape as either embedding and that it equals the element-by-element addition of the two. This is the last point before dropout, so a difference here is an error in the embedding stage or the addition.
- 4Check after dropout
Dropout is a stage that changes values during training. Compare its output to its input to confirm that it is behaving as the configuration intends. If the model is in evaluation mode, the behavior should be different from training mode, so check the mode before concluding anything.
- 5Check after the transformer blocks and final norm
Because the placeholders return their input unchanged, the tensor here should equal the tensor from the previous check. A difference at this point would mean the stage is not behaving as the placeholder description says, so the code itself should be inspected.
- 6Check the output head
The output head is the only remaining stage that transforms the data. If the earlier checks match, the logits should be determined by the output head's mapping. A divergence first appearing here points to the head rather than to the embeddings.
The first stage whose output differs from its expected value is the stage to investigate. Because the earlier stages were verified in order, the search stops at the earliest divergence rather than at the final logits.
Mistakes That Slow Down the Trace
Common mistake Expecting the placeholder blocks to change the vectors
Why it failsDummyTransformerBlock and DummyLayerNorm return their input unchanged, and the stack of blocks is an identity operation.
Do this insteadTreat these stages as pass-through checkpoints. If their output differs from their input, investigate the code rather than assuming it is expected.
Common mistake Treating the token embedding and positional embedding as one lookup
Why it failsThe two tables are indexed differently. One maps token indices to vectors and the other maps positions to vectors, and their results are added together.
Do this insteadInspect each embedding output separately before checking the sum.
Common mistake Checking the final logits before the intermediate stages
Why it failsAn error that appears early in the forward pass propagates to every later stage, so the final output alone cannot show where the problem started.
Do this insteadCompare intermediate tensors in forward-pass order and stop at the first stage that diverges.
Common mistake Assuming the sum is taken after dropout
Why it failsThe source states that the sum is taken before any dropout is applied, so dropout acts on the combined vector.
Do this insteadPlace the embedding sum before dropout in your mental model and in any trace you write.
Common mistake Forgetting that the output head is the only stage that transforms the data in this version
Practice Tracing Your Own Run
Run the DummyGPTModel listing and choose one value from the output. Using only the forward-pass order from this article, name the stage that produced that value's last transformation and the stage whose output you would check first if the value looked wrong. Explain why placeholder stages cannot be the source of a surprising value in this version.
Hints
- Start from the output head, because it is the stage that produces the logits.
- Walk backward through the pipeline until you reach a stage that does real computation.
- The placeholders return their input, so a change in the value must come from an earlier stage.
Without running the code, describe in one sentence what happens to a summed embedding vector as it moves from the dropout stage to the output head. Name each stage it passes through and state whether that stage changes it.
Hints
- Consider which stages are placeholders.
- Remember that dropout is applied after the sum.
Summary of the Forward Pass
- 1DummyGPTModel is a stripped-down, GPT-style nn.Module. It contains token and positional embeddings, dropout, a stack of transformer blocks, a final layer normalization, and a linear output head.
- 2Token embeddings and positional embeddings are looked up separately and added element by element before dropout and before the transformer blocks.
- 3DummyTransformerBlock and DummyLayerNorm return their input unchanged, so only the embeddings, dropout, and output head affect the logits in this version.
- 4When an output looks wrong, compare intermediate tensors in forward-pass order and stop at the first stage where the result diverges.
At a glance
- DummyGPTModel is a simplified GPT-style nn.Module that builds token and positional embeddings, dropout, a stack of transformer blocks, a final layer normalization, and a linear output head.
- The token and positional embeddings are looked up from separate tables and summed element by element before any other stage runs.
- The placeholder transformer blocks and placeholder layer normalization return their input unchanged, so in this version the logits depend on the embeddings, dropout, and output head.
- To locate an unexpected output, compare intermediate tensors stage by stage in forward-pass order and identify the first stage where the result diverges.