Cross-Entropy Loss for Language Models
Padding positions in a batch are excluded from the training loss by assigning them the placeholder value -100 in the target lists.
Filler That Should Not Teach
When training sequences in a batch have different lengths, the shorter ones are filled out with extra padding tokens so that every row has the same size. The tensors have to be rectangular for the computation to work, but the filler carries no information about the language the model should learn. The problem this article addresses is how to keep that filler from influencing the training signal, specifically the loss that the optimizer uses to adjust the weights.
The approach is to assign a special placeholder value, -100, to every padding position in the target lists. The loss function is then configured to skip any position that carries that value. Padded rows keep their place in the tensor, so the shape never changes, but they contribute nothing to the average. Before explaining the mechanism, it helps to watch the placeholder in action and predict what it does.
What do you think happens?
You have a valid two-row loss. You add a third row of logits and set its target to -100 instead of a real token index. Does the overall loss change?
Reveal answer
No, the loss stays the same as the two-row loss.
The third row still exists in the logits, but cross-entropy ignores the entry whose target is -100. The position is removed from the calculation without changing the shape of any tensor.
Tracing the Loss Over Three Rows
Start with a small self-contained example. Each row of the logits tensor holds one score per vocabulary entry for a single predicted position, and the targets tensor holds the index of the correct entry for each row. The example uses two positions and a two-entry vocabulary, which keeps every number easy to check by hand.
Now add a genuine third position with a real target. A correct token ID at that position is supposed to influence the loss. Adding a valid third target changes the loss from 1.1269 to 0.7936. The loss is an average over the positions that count, so a position with a real target shifts the result. The key question is what happens when the third target is a placeholder instead of a real index.
- The logits tensor has one row per predicted position and one column per vocabulary entry.
- The targets tensor holds the correct column index for each row.
- The third target is -100, so PyTorch's cross-entropy skips that row.
- Both printed values should be identical, because the ignored row adds nothing to the average.
The loss over the three rows equals the loss over the two original rows. Run the code above and compare the two printed values. The third row is still present in the logits, so the tensor shape is unchanged. Only its contribution to the loss is removed. This is the mechanism that lets padded batches be used safely.
How a -100 Target Leaves the Average
PyTorch's cross-entropy loss ignores any target equal to -100. A padded row therefore contributes nothing to the average, even though the tensor shape is unchanged. Each position is checked in turn: if its target is a real index, its loss is computed and counted; if its target is -100, that position is skipped entirely and is not part of the averaged result.
The denominator of the average changes with the ignored positions. The loss is averaged only over the positions that are not ignored. A batch with many padded positions therefore does not dilute the loss with rows that were never meant to count.
Which End-of-Text Tokens Survive
Padding in target lists is usually the end-of-text token, ID 50256. Replacing every instance with -100 would look tidy, but it would remove information the model needs. The first end-of-text token in each target list is kept, so the model gets a training target at the stopping point and learns when to generate an end-of-text token in response to an instruction. The model treats that token as the signal that its generated response is complete. Only the later copies, which serve purely as padding, are replaced with -100.
Applying the end-of-text rule to one row
A target list of length 5 is 464, 2068, 50256, 50256, 50256. Which positions keep their IDs and which become -100?
- 1Find the first end-of-text token
The first 50256 is at position 2, counting from 0.
- 2Keep it and everything before it
Positions 0, 1 and 2 keep their IDs, so the model still gets a training target at the stopping point.
- 3Replace the later copies
Positions 3 and 4 are later end-of-text tokens that only serve as padding, so each becomes -100.
- 4Check the effect on the loss
Positions 3 and 4 are skipped, so only positions 0 to 2 are counted in the averaged loss.
The target list becomes 464, 2068, 50256, -100, -100.
Pipeline From Targets to Loss
The batching process prepares the target sequence by shifting token IDs one position to the right and appending an end-of-text token. The padding replacement is the last step before those targets reach the loss. The first two stages decide what the target list contains, and the replacement stage decides which positions the loss may see. Only the final stage performs the actual skipping.
This separation matters when you debug a training run. A problem in the padding step will show up later as a loss that looks wrong, even though the loss function itself is working as designed. When a loss looks suspicious, check the target lists before blaming the loss function.
Common mistake Replacing every end-of-text token with -100
Why it failsRemoving the first end-of-text token deletes the training signal that teaches the model when to stop.
Do this insteadKeep the first end-of-text token in each target list and replace only the later padding copies.
Common mistake Assuming -100 changes the tensor shape
Why it failsThe padded row is still in the logits and targets, so the shape is unchanged. Only its contribution to the loss is removed.
Do this insteadExpect the same shapes and a loss averaged over the counted positions only.
Common mistake Using allowed_max_length to exclude padding
Why it failsallowed_max_lengthlimits how long each sample may be. It does not decide which positions count toward the loss.Do this insteadUse the -100 placeholder in the target lists to exclude padding positions from the loss.
Common mistake Expecting a padded position to change the weights through the loss
Check Your Batch
A batch has two target lists of length 4. Row A is 818, 2068, 50256, 50256. Row B is 818, 50256, 50256, 50256. Write the target lists after the padding replacement, then state which positions are counted in the averaged loss.
Hints
- Find the first 50256 in each row and keep it.
- Every later 50256 becomes -100.
- Counted positions are the ones whose targets are not -100.
Key Takeaways
- 1Padding positions are excluded from the training loss by setting their target to -100.
- 2PyTorch's cross-entropy ignores targets equal to -100, so the padded row keeps its place in the tensor but adds nothing to the average.
- 3The first end-of-text token, ID 50256, in each target list is kept so the model learns when to stop; later copies become -100.
- 4
allowed_max_lengthlimits sample length and is a separate control from the -100 placeholder.
At a glance
- Padding positions are excluded from the training loss by setting their target to -100.
- PyTorch's cross-entropy ignores targets equal to -100, so a padded row adds nothing to the average even though the shape is unchanged.
- The first end-of-text token, ID 50256, in each target list is kept so the model learns when to stop; later copies become -100.
allowed_max_lengthcontrols sample length and is separate from the -100 placeholder that controls which positions count toward the loss.