Concepts / Preparing Text Data for Training

Preparing Text Data for Training

Input-target pairs are the training examples used for LLM training, generated from tokenized data.

  • Programming

From Tokens to Training Examples

Before a language model can learn from text, the text has to be converted into a form the training process can use. Earlier steps in this chapter covered how raw text is broken into tokens. This article picks up at that point. You already have a sequence of tokens, and the question is how to turn that sequence into the examples a model actually trains on.

The chain to keep in mind is this: tokenized data goes in, a sliding window slides across it, and input-target pairs come out. The pairs are what the model is trained on. Each pair ties a piece of input text to the target the model should learn to associate with it.

What do you think happens?

If a text is split into tokens, and a window of fixed length slides across those tokens one position at a time, what do you think the learner's training examples look like?

  • Each example is a single token with no context

  • Each example is a window of tokens paired with the tokens that follow it

  • Each example is the entire text at once

Reveal answer
Answer:

Each example is a window of tokens paired with the tokens that follow it

The sliding window produces input-target pairs. The input is a run of tokens, and the target is the matching run of tokens the model should learn to predict from that input.

Why Pairs Matter for Training

Definition

An input-target pair is a training example for an LLM. The input is a piece of tokenized text, and the target is the text the model should learn to associate with that input. The source defines these pairs by their purpose: they supply training examples.

Tokenized data is the input to this process, and input-target pairs are its output. The source applies the idea to tokens specifically. The window does not slide over raw characters. It slides over tokens, because tokens are the units the model already treats as discrete pieces. That is why tokenization comes first.

The sliding window approach moves a window across the token sequence to produce these pairs. A single token sequence can yield several pairs, because consecutive window positions overlap. The next section traces exactly how that happens.

Tracing the Sliding Window

Consider a small illustrative token sequence of eight tokens: the, story, was, short, and, clear, to, read. Use a window that holds four tokens and moves forward by one position at each step. The input for each pair is the four tokens inside the window. The target is the four tokens one position later, so that each target position is the token that follows the matching input position.

Step 0input: the story was shortStep 1input: story was short andStep 2input: was short and clearslide by 1 tokenslide by 1 token
As the window advances one step, the input and target change together. Which tokens are in the window before and after, and how does each next pair differ from the previous one?

Step 0 pairs the input the, story, was, short with the target story, was, short, and. Step 1 moves the window one token forward. The input becomes story, was, short, and, and the target becomes was, short, and, clear. Notice that three of the four input tokens in step 1 were also in step 0. That overlap is why one token sequence can produce several pairs.

Worked example

Producing a pair at one window position

The token sequence is the, story, was, short, and, clear, to, read. The window holds four tokens and starts at position 0. What is the input-target pair at that position?

  1. 1
    Identify the input

    The window covers positions 0 to 3, which are the, story, was, short.

  2. 2
    Identify the target

    The target is shifted one position forward, covering positions 1 to 4, which are story, was, short, and.

  3. 3
    Check the alignment

    Each target token lines up with the input token one position before it. Story in the target follows the in the input, and so on across the window.

Result

Input: the, story, was, short. Target: story, was, short, and.

theinput position 0storytarget position 0storyinput position 1wastarget position 1wasinput position 2shorttarget position 2shortinput position 3andtarget position 3next tokennext tokennext tokennext token
Which token in the input lines up with which token in the target? Each target position holds the token that comes next after the matching input position.

Choosing a Small Public Text

The text used throughout this part is The Verdict, a short story by Edith Wharton. It was already used in chapter 2. Choosing it solves two problems at once. Because the story is in the public domain, there is no question about usage rights. Because it is small, the code runs on a standard laptop in a matter of minutes, even without a high-end GPU.

Size is the trade-off. A dataset this small cannot train a model that produces useful text on its own. The purpose here is education, so the code runs in minutes instead of weeks. Later in the workflow, pretrained weights from OpenAI are loaded into the model, which is how the small text is made useful in practice.

For scale, the source points to the 7 billion parameter Llama 2 model, a relatively popular openly available LLM. Training it required 184,320 GPU hours on A100 GPUs and processed 2 trillion tokens. A larger corpus is the route toward more extensive training, at a much higher computational cost.

Loading Text and Counting Characters and Tokens

The first code step reads the whole story into a single string. The file is opened in read mode with UTF-8 encoding, and file.read() returns its full contents. Once the text is in memory, it is measured in two different units. The number of characters comes from len(text_data). The number of tokens comes from passing the same text through the tokenizer and measuring the result.

python
Notes on the code
  • The file is opened in read mode with UTF-8 encoding.
  • file.read() returns the full contents as one string.
  • len(text_data) counts characters.
  • Passing the same text through the tokenizer gives the token count.

The two numbers answer different questions. The character count describes the raw text. The token count describes how the model will actually read it. These are different counts, and the token count is the one that describes what the model reads. In the source's run, the text yields 5,145 tokens. That may look too small to train an LLM, and it is accepted here because the aim is quick educational runs.

Characterslen(text_data)Raw textmeasures the stringTokenstokenizer outputModel inputwhat the model readsdescribesdescribes
The same loaded text looks different when measured as characters versus as tokens. The character count describes raw text, and the token count describes what the model reads.

Splitting Text with a Train Ratio

Next the text is divided into a training part and a validation part. The validation part is used for model evaluation during training, so it must be kept separate from the training part. The split is set by a train_ratio of 0.90, which means 90 percent of the text goes to training and the remaining 10 percent goes to validation. The source describes this split as a split index computed from train_ratio, and the two parts are never mixed.

Formula, step by step
  1. 1
    N is the total length of the text that is being divided.
  2. 2
    Multiply N by train_ratio to find the training share, for example $0.90 \times N$.
  3. 3
    Round down to a whole position, which becomes the cut point between the two subsets.
  4. 4
    Text before the cut point is the training subset, and text from the cut point onward is the validation subset.
Worked example

Computing a split index

A text has N = 1000 units. The train_ratio is $0.90$. Where is the cut point, and how many units go to each subset?

  1. 1
    Compute the product

    $0.90 \times 1000 = 900$.

  2. 2
    Set the cut point

    The split index is 900, so positions 0 through 899 form the training subset.

  3. 3
    Find the validation share

    Positions 900 through 999 form the validation subset, which is 100 units, or one tenth of the text.

Result

The training subset has 900 units and the validation subset has 100 units.

From Split Text to Batched Tensors

A split subset is still plain text, and the model needs fixed-size tensors. The source describes the preparation as a chain of operations. The subset is tokenized. The token sequence is divided into chunks of a user-specified length. The chunks are shuffled. The shuffled chunks are organized into batches, where the batch size sets how many chunks are processed together.

Split texttokenized subsetChunkslength 256 eachShuffled chunksrandom orderBatchesbatch size 2Tensor2 samples of 256 tokensdivideshufflegroupstack
How does one long token sequence become chunks, then shuffled order, then batches? The tensor shape at the end is two samples of 256 tokens.

The source uses a batch size of 2 because the dataset is small. It notes that training LLMs with batch sizes of 1,024 or larger is not uncommon in practice. Batch size is therefore a resource choice, and the small value here reflects the small dataset rather than a recommended setting for large-scale training.

Training Versus Validation Loader Settings

The loaders are built with the create_dataloader_v1 function from chapter 2. Both calls use the same batch size, max_length, and stride. The settings that differ are drop_last and shuffle, and those differences encode the training-versus-validation distinction. A random seed is also fixed so that the shuffling is repeatable.

SettingTraining loaderValidation loader
shuffleOn, so the order of examples variesOff, so evaluation uses a fixed order
drop_lastTrue, so every batch has the full sizeFalse, so no validation chunk is thrown away
batch sizeSame value in bothSame value in both
max_length and strideSame value in bothSame value in both

Loader settings that differ between training and validation, as described in the source

Setting drop_last to True on the training loader discards an incomplete final batch, so every training batch has the full size. The validation loader sets it to False, so no validation chunk is silently discarded. Shuffling is switched on for training, where the order of examples should vary, and switched off for validation, where a fixed order keeps evaluation consistent.

Checking Batch Shapes

The source suggests an optional check. Iterate through each loader and print the shape of every input and target tensor. Each loader yields a pair, an input x and a target y, so the loop unpacks two values per batch. The printed output confirms whether the loaders were built correctly.

In the source's printed output, the training loader yields nine batches, each with two samples of 256 tokens. The validation loader yields one batch of two input examples. This matches what the split and the batch settings predict, since only about a tenth of the text goes to validation.

MEDIUM

A text has 5,145 tokens, the context length is 256 tokens per sample, and the batch size is 2. Using the training split of 90 percent, estimate how many full training batches you expect the training loader to yield, and check your estimate against the source's printed output of nine batches. Think about how many tokens the training portion contains and how drop_last affects an incomplete final batch.

Hints
  • Start by estimating the training share: 90 percent of 5,145 tokens.
  • Divide that training share by the number of tokens in one sample, then by the batch size.
  • Remember that drop_last discards an incomplete final batch.

Mistakes Beginners Make When Preparing Data

  • Common mistake

    Treating the character count as the number the model reads

    What it looks like

    Reporting len(text_data) as the size of the training input.

    Why it fails

    The character count describes the raw text. The token count describes how the model actually reads it.

    Do this instead

    Measure the tokens with the tokenizer when you need the size the model sees.

  • Common mistake

    Mixing training and validation text

    Why it fails

    The validation part is used for evaluation during training, so it must stay separate from the training part.

    Do this instead

    Cut the text once at the split index and build each loader from its own subset.

  • Common mistake

    Using the same shuffle and drop_last settings for both loaders

    Why it fails

    Shuffling for training varies the order of examples, while a fixed order keeps evaluation consistent. drop_last discards incomplete training batches, but it would also silently drop validation chunks.

    Do this instead

    Shuffle and drop the final incomplete batch only on the training loader.

  • Common mistake

    Assuming the windows do not overlap, when consecutive window positions share tokens and one sequence can yield several pairs

Practical Notes on Dataset Scale

Dataset choice is a matter of goal and constraints. A small public domain text answers the questions of licensing and speed, which matters when the aim is to learn the mechanics. A larger corpus is the route toward more extensive training, at a much higher computational cost.

Summary of the Preparation Chain

  1. 1
    Input-target pairs are the training examples for an LLM, and they are generated from tokenized data.
  2. 2
    A sliding window moves across the tokens, and consecutive positions overlap so one sequence yields several pairs.
  3. 3
    Characters and tokens are different counts, and the token count describes what the model reads.
  4. 4
    A split index computed from train_ratio divides the text into training and validation parts that are never mixed.
  5. 5
    Split text is tokenized, chunked, shuffled, and batched, and the printed shapes confirm the loaders are correct.

At a glance

  • Input-target pairs are the training examples for LLM training, generated from tokenized data by a sliding window.
  • Consecutive window positions overlap, so a single token sequence can yield several pairs.
  • The token count, not the character count, describes what the model reads, and a train_ratio of 0.90 sends 90 percent of the text to training.
  • Split text is tokenized, chunked, shuffled, and batched, and the training and validation loaders differ in shuffle and drop_last.

Related concepts

More concepts starting with P