Concepts / Batching Instruction Examples with a Custom Collate Function

Batching Instruction Examples with a Custom Collate Function

Masking changes which tokens count, not which examples exist. The dataset and the batching logic stay the same, and only the label positions for instruction and input tokens change.

  • Programming

Why Masking Becomes an Experiment

By the time you reach the end of the instruction fine-tuning chapter, you already have most of the pieces in place. You have built an InstructionDataset class that holds instruction examples, you have written a custom_collate_fn function that batches those examples, and you have fine-tuned a model. The final exercise, Exercise 7.2, asks for one more move: change which tokens count during training, and then judge whether that change actually helps.

Think of this as a small experiment layered on top of a pipeline you already understand. Nothing new is being built from scratch. A single variable, the masking of instruction and input tokens, is being altered, and the result is compared against an earlier run. That framing matters, because it turns a vague question (is this change good?) into a concrete one (did the score move, and was the movement caused by masking?).

Tracing One Example Through Masking

Start with a single tokenized instruction example and follow it through the masking step. Every position in the example has a label, and masking decides which labels keep their real token IDs and which are replaced. The diagram below shows one example with six token positions. The first three positions hold the instruction and input, and the last three hold the response the model should learn to produce.

Position 0-100 (masked)Position 1-100 (masked)Position 2-100 (masked)Position 3real token IDPosition 4real token IDPosition 5real token ID
Within one tokenized example, which token positions keep their real IDs in the labels, and which become -100 so they are ignored?
Worked example

Masking one six-position example

An example has six token positions. Positions 0 to 2 hold the instruction and input. Positions 3 to 5 hold the response. Which label positions are replaced with -100?

  1. 1
    Identify the instruction and input span

    Positions 0, 1, and 2 belong to the instruction and input, which are the tokens that masking targets.

  2. 2
    Replace those labels with the mask

    Each of positions 0, 1, and 2 has its label replaced with -100.

  3. 3
    Leave the response labels alone

    Positions 3, 4, and 5 keep their real token IDs, so the training signal still comes from the response.

Result

Labels at positions 0 to 2 become -100. Labels at positions 3 to 5 keep their real token IDs.

What the -100 Mask Replaces

Definition

Instruction masking is the step that replaces the instruction and input tokens in an example with the -100 mask. The response tokens are not replaced in this description, so they keep their real labels.

The value -100 works as a marker rather than a token. Positions carrying -100 are positions the training setup treats as not counting. That is why masking is a choice about which tokens count during training: the same example is kept intact, but the marked positions are excluded from what the model is asked to reproduce. Exercise 7.2 then asks whether this selective treatment has a positive effect on model performance.

Key point

Masking changes which tokens count, not which examples exist. The dataset and the batching logic stay the same, and only the label positions for instruction and input tokens change.

From Dataset Object to Training Batch

Masking only matters if the masked examples actually reach the model in batches, so the next question is how data travels from storage to training. The source describes three roles. The InstructionDataset object holds the instruction examples. The custom_collate_fn function describes how individual examples are combined into a batch. The PyTorch data loader connects the two and handles shuffling and batching, so the training code can simply request the next batch.

In practical terms, the InstructionDataset object is plugged into a PyTorch data loader together with the custom_collate_fn function. The loader asks the dataset for examples, shuffles them, groups them into batches, and passes each group through the collate function. The training loop then receives a ready batch and never has to handle individual examples itself.

Example Ashorter sequenceBatch row 1padded to common lengthExample Blonger sequenceBatch row 2common lengthcollatecollate
How do examples of different lengths get padded to a common length and stacked into one batch, and where does the -100 padding go in the labels?

The collate function is where unequal examples become one rectangular batch. The diagram shows the generic idea: examples of different lengths are brought to a shared length and stacked. Padding positions in the labels are conventionally given the -100 value, so they are excluded in the same way that masked instruction tokens are. The source does not spell out this padding convention in detail, so treat the padding placement as the general pattern to verify against your own collate function.

Where Data Loaders Sit in the Workflow

The source presents instruction fine-tuning as three stages: preparing the dataset, fine-tuning the LLM, and evaluating the LLM. Each stage contains numbered steps. Creating the data loaders is the closing move of the first stage. It is the point where prepared data stops being a collection of examples and becomes a stream of batches that the fine-tuning stage can consume.

Stage 1: Preparedatasetdata loaders created lastStage 2: Fine-tuneLLMconsumes batchesStage 3: Evaluate LLMafter fine-tuningbatchestrained model
At which stage does the data loader get created, and what comes immediately before and after it?

Data loaders are created for the training, validation, and test sets. Each split gets its own loader, so the same batching logic serves both fine-tuning and evaluation. Because of this handoff, everything in stage 2 depends on the loaders built at the end of stage 1. The masking experiment depends on the same handoff, since the data that flows through those loaders is what the masked training run actually sees.

Mistakes When Batching and Masking

  • Common mistake

    Treating masking as a change to the dataset

    What it looks like

    Deleting the instruction text from the examples before batching.

    Why it fails

    Masking replaces instruction and input tokens with the -100 mask. It does not remove the examples or their text from the dataset.

    Do this instead

    Keep the examples intact and change only which label positions are masked.

  • Common mistake

    Changing several settings at once in the comparison

    What it looks like

    Altering masking, learning settings, and the number of epochs in the same rerun.

    Why it fails

    A fair test changes masking as its only variable. Otherwise you cannot tell whether a score change came from masking.

    Do this instead

    Hold everything else constant and compare against the earlier fine-tuned run.

  • Common mistake

    Assuming the data loader is a separate piece of data

    What it looks like

    Building a new dataset for each split instead of creating loaders from the prepared data.

    Why it fails

    The data loader connects the InstructionDataset and the collate function and handles shuffling and batching.

    Do this instead

    Create loaders for the training, validation, and test sets from the same prepared dataset.

  • Common mistake

    Skipping the validation and test loaders because only training is being changed

Designing a Fair Masking Test

  1. 1
    Start from the fine-tuned run you already have as the baseline.
  2. 2
    Keep the InstructionDataset, the custom_collate_fn function, and the data loaders the same across both runs.
  3. 3
    Change only the masking of instruction and input tokens in the new run.
  4. 4
    Fine-tune the model with the changed masking, using the same training setup as the baseline.
  5. 5
    Compare the result of the masked run against the earlier fine-tuned run.
  6. 6
    Judge whether the change has a positive effect on model performance, based on that comparison.
MEDIUM

Suppose a colleague reports that masking instruction tokens improved their model, but they also changed the batch size and the number of training steps in the same rerun. Explain why their result cannot yet be attributed to masking, and describe the change to the experiment that would fix this.

Hints
  • Ask which variable the fair test is supposed to change.
  • Think about what the earlier fine-tuned run is for.

Key Takeaways

  • Instruction masking replaces the instruction and input tokens with the -100 mask, while the response tokens keep their real labels.
  • Exercise 7.2 is a fair experiment: change masking as the only variable and compare against the earlier fine-tuned run.
  • The InstructionDataset holds the examples, custom_collate_fn describes how they are combined into batches, and the PyTorch data loader shuffles and batches them for training.
  • Data loaders are created for the training, validation, and test sets as the last step of stage 1, the dataset preparation stage, before fine-tuning begins.

Related concepts

More concepts starting with B