Concepts / Organizing Data into Training Batches

Organizing Data into Training Batches

The dataset is split into training, validation, and test portions before the PyTorch data loaders and batches are built, mirroring the earlier spam classification workflow.

  • Programming

Starting From One Prepared Dataset

Once an instruction dataset has been downloaded and formatted, it is still one undivided list of examples. Before any batches can be built for instruction fine-tuning, that list has to be divided into separate pieces. This article is about that division and about the step that follows it, grouping the entries of each piece into batches. The source material treats the work as a familiar one: it mirrors the approach used with the spam classification dataset in the previous chapter, so the logic should feel familiar even though the data is now instruction-style text.

What do you think happens?

The prepared instruction dataset is ready. Before any batches are built, what should happen to it?

  • It is grouped into batches of a fixed size right away

  • It is divided into training, validation, and test portions first

  • It is shuffled and then fed directly to the model

Reveal answer
Answer:

It is divided into training, validation, and test portions first.

The source places the split right after the data is downloaded and formatted, and right before the PyTorch data loaders and batches are set up. The loaders are built from the prepared portions, so the portions have to exist before any batching happens.

Instruction Data and Training Batches

The phrase organizing instruction data in training batches has two parts, and it helps to separate them before thinking about any mechanism. The first part, instruction data, is the material being organized. It is the set of instruction records, each one an example the model will learn from. The second part, training batches, is the grouping that the organizing is done into. In other words, the records are the unit being moved, and the batch is the container they are moved into.

The relationship between the two is containment. A collection of instruction data is divided into groups, and each group is a training batch. Nothing is lost or duplicated in the process: every record ends up in exactly one batch. The batch is therefore the unit to keep in view when you reason about the data, because the whole collection is organized by being split into such groupings.

Where Partitioning Fits in the Workflow

The source organizes the whole fine-tuning workflow into three stages. Stage 1 prepares the dataset, Stage 2 fine-tunes the model, and Stage 3 evaluates it. Partitioning belongs to the preparation work in Stage 1. It comes after the dataset has been downloaded and formatted, and it comes before the data loaders are built.

The order matters because of dependency. The data loaders are built from the prepared portions, so the portions must exist first. Batching then groups entries from those portions into the units the model processes during training. Put simply, the dataset is divided into portions first, and only then is one portion divided into batches. These are two different divisions, and confusing them is one of the most common misreadings covered later in this article.

Computing the Slice Boundaries

The partitioning starts from one number: the total length N of the data list. The training and test sizes are computed as proportions of that length, and each product is wrapped in int(), which keeps only the whole-number part. The validation size is not a proportion at all. It is whatever remains after the training and test sizes are subtracted from the total.

Rule

Once the three sizes are known, each slice follows from them. The training slice starts at the beginning of the list and stops before train_portion. The test slice starts at train_portion and runs for test_portion entries, so it ends just before train_portion plus test_portion. The validation slice starts at that combined offset and continues to the end of the list. Read in this order, the three slices cover the list from its first entry to its last, with no overlap and no gaps. The test boundary is the start of the test slice, and the validation boundary is the start of the validation slice; each one is the end of the slice before it.

python
Output (expected)
935 110 55
Notes on the code
  • The first two sizes are proportions wrapped in int()
  • The validation size is computed by subtraction, not by a proportion
  • The test slice is cut before the validation slice, matching the order in the source listing
  • The validation slice has no end index, so it runs to the end of the list

The code above is a reconstruction of the logic the source describes: it computes three integer sizes from the total length, slices the list into three pieces, and prints the length of each piece. The source's own listing assumes that a list called data already exists and holds every instruction example. Read the code once for its overall shape, then trace it line by line, watching the moment each variable receives its value and the moment each slice is cut.

Trainingindices 0 to 934, 935entriesTestindices 935 to 1044, 110entriesValidationindices 1045 to 1099, 55entriesboundary at index 935boundary at index 1045
Given a dataset of length N, where does each slice start and end, and how do the three boundaries sit along the index line?

Read the diagram from left to right. Each portion begins exactly where the previous one stops, so the boundaries are the only places where one slice hands over to the next. The training portion is the largest, the test portion comes next, and the validation portion occupies the final positions in the list. This is a statement about position in the list. The name of a portion tells you what it is for, but its slice tells you exactly which entries it contains.

Tracing the Split of 1100 Entries

Worked example

Splitting the source dataset

A prepared instruction dataset contains 1100 entries. Compute the size and slice boundaries of the training, test, and validation portions.

  1. 1
    Compute the training size

    The training size is int(0.85 times 1100). Since 0.85 times 1100 equals 935, the training size is 935.

  2. 2
    Compute the test size

    The test size is int(0.10 times 1100), which equals 110.

  3. 3
    Compute the validation size

    The validation size is what remains: 1100 minus 935 minus 110, which equals 55. No proportion is used here.

  4. 4
    Place the training slice

    The training slice starts at index 0 and stops before index 935, so it covers indices 0 through 934.

  5. 5
    Place the test slice

    The test slice starts at index 935 and runs for 110 entries, so it covers indices 935 through 1044.

  6. 6
    Place the validation slice

    The validation slice starts at index 1045, the combined offset of 935 plus 110, and runs to the end of the list, covering indices 1045 through 1099.

Result

Training has 935 entries, test has 110, and validation has 55. Together they sum to 1100, so every entry lands in exactly one portion. The source reports 935 training, 55 validation, and 110 test samples, consistent with these computed sizes.

Predicting Sizes for a Smaller Dataset

The same rules apply to any length. Try the procedure yourself on a much smaller list before reading the answer. Suppose the data holds six instruction records, labeled A through F. Work out how many entries each portion receives, and which records fall where.

What do you think happens?

For a dataset of 6 records, what are the sizes of the training, test, and validation portions, and which records does each receive?

Reveal answer
Answer:

Training gets 5 records (A through E), test gets 0 records, and validation gets 1 record (F).

int(0.85 times 6) is int(5.1), which is 5. int(0.10 times 6) is int(0.6), which is 0. Validation is 6 minus 5 minus 0, which is 1. The training slice covers A through E, the test slice starts at index 5 and is empty, and the validation slice starts at index 5 and holds F.

Grouping Records into Batches

After a portion exists, its entries can be grouped into batches. The grouping is the same containment idea described earlier: the records are placed into groups, and each record belongs to exactly one group. The example below is a generated illustration of the grouping idea, not a procedure from the source. It uses a small set of six instruction records labeled A through F, organized into batches of two.

Worked example

Grouping six records into batches of two

Six instruction records, A through F, are organized into batches of two. Trace which records land in each batch and confirm that no record is changed or removed.

  1. 1
    Start with the full set

    The set holds six records: A, B, C, D, E, and F.

  2. 2
    Form the first batch

    Records A and B are placed together as the first batch.

  3. 3
    Form the second batch

    Records C and D are placed together as the second batch.

  4. 4
    Form the third batch

    Records E and F are placed together as the third batch.

  5. 5
    Check the result

    Three batches of two records each contain all six records, and each record appears in exactly one batch. No record was altered or dropped.

Result

The set of six records is organized into three batches: A and B, then C and D, then E and F. The records are the same as before; only their grouping has changed.

Six instructionrecordsthe collection beingorganizedBatch 1records A and BRecord ABatch 2records C and DRecord BBatch 3records E and FRecord CRecord DRecord ERecord Fcontainscontainscontainsholdsholdsholdsholdsholdsholds
How do individual records nest inside batches, and how do batches nest inside a dataset split?

The diagram shows only the containment relationship the source names. Records sit inside batches, and batches sit inside the collection. In the full workflow, the collection being batched is one of the portions from the earlier split, not the whole original dataset. The batch sizes shown here are an illustration; the source does not provide a batch size for the course's own dataset.

Common Mistakes in Partition Code

The partition arithmetic is short, but a small slip in it silently changes which entries land in which portion. The comparison below shows what happens when the test slice is given the wrong end. The correct version stops the test slice at index 1045, which leaves exactly the validation entries for the validation slice. The wrong version lets the test slice run to the end of the list.

test = data[935:1045]110 entriestest = data[935:]165 entriesvalidation =data[1045:]55 entriesvalidation =data[1100:]0 entriestest takes validation records
How does an incorrect end index change which records land in which partition, compared with the correct version?
  • Common mistake

    Cutting the validation slice from the wrong offset, or cutting the test slice before the training slice ends

    What it looks like

    Starting the test slice at index 900 instead of 935 causes the training and test portions to overlap on indices 900 through 934.

    Why it fails

    The test slice must begin exactly where the training slice ends. Any other start creates overlap or a gap, and the three portions no longer cover the list cleanly.

    Do this instead

    Start the test slice at train_portion and the validation slice at train_portion plus test_portion, then check that the sizes sum to the total length.

  • Common mistake

    Letting a slice run to the end of the list when it should stop earlier

    What it looks like

    Writing test = data[935:] on the 1100-entry list gives the test portion 165 entries, because it swallows the 55 validation entries, and validation becomes empty.

    Why it fails

    A slice with no end index takes everything that remains, so a missing or wrong end index silently moves entries from one portion into another.

    Do this instead

    Give the test slice an explicit end of train_portion plus test_portion, and print each portion's length to confirm the sizes.

  • Common mistake

    Reading the proportions in the summary as the slice order

    What it looks like

    The source describes the split as 85% training, 10% testing, and 5% validation, and a reader assumes the slices are cut in that same order with validation last only by convention.

    Why it fails

    The order in the code, not the order of the summary sentence, determines which entries sit at which positions. The test portion is cut before the validation portion in the listing.

    Do this instead

    When you need to know where a given entry lands, read the slice lines in the code and trace the indices, rather than relying on the summary sentence.

  • Common mistake

    Assuming the portion sizes do not need to add up

    What it looks like

    A reader computes the training and test sizes, then forgets to compute validation and assumes it is 5% without subtracting.

    Why it fails

    Each integer truncation can leave a small remainder. Validation is defined as what is left over, so if the sizes do not sum to the total, some entries are unassigned or counted twice.

    Do this instead

    Compute the validation size by subtraction and check that training, test, and validation sizes together equal the length of the data.

Misreading the Batching Idea

  • Common mistake

    Treating batching as the same thing as splitting into training, validation, and test portions. The split divides the whole dataset into portions; batching divides one portion into groups of records. They happen in that order and are different operations.

  • Common mistake

    Assuming batching shuffles the data. The source material on this step does not describe shuffling, so do not add it as an assumed part of the procedure without checking the full source.

  • Common mistake

    Thinking the batches contain new or altered records

    Why it fails

    Batching is a containment relationship. Each record is placed into exactly one batch, and no record is changed, removed, or duplicated.

    Do this instead

    When you check a batching result, count the records across all batches and confirm the total matches the size of the portion.

  • Common mistake

    Treating a batch as a portion of the dataset. A portion is a large slice cut from the full list for a specific purpose, while a batch is a smaller grouping of records within one portion.

Practicing the Partition Arithmetic

MEDIUM

A prepared instruction dataset contains 400 entries. Compute the size of the training, test, and validation portions, then write the start and end indices of each slice. Check that your three sizes add up to 400.

Hints
  • Compute the training size as int(0.85 times 400) first.
  • Compute the test size as int(0.10 times 400) next.
  • Compute the validation size by subtracting the training and test sizes from 400, not by taking 5%.
  • The test slice starts where the training slice ends, and the validation slice starts where the test slice ends.

Key Takeaways

  • Before batching begins, the prepared dataset is divided into training, validation, and test portions, which are contiguous runs of entries cut from one list in a fixed order.
  • The training and test sizes are int(length times a proportion), and the validation size is whatever remains after those two are subtracted, so the three portions cover the list with no overlap or gaps.
  • For 1100 entries the partition gives 935 training, 110 test, and 55 validation entries, and slice order in the code determines which entries land where.
  • Batching organizes instruction records, the material being organized, into training batches, the grouping they are placed into; every record belongs to exactly one batch and nothing is lost or duplicated.
  • Batching is not the same as splitting into portions or shuffling, and the source's brief treatment means batch sizes and ordering should be checked against the full source.

Related concepts

More concepts starting with O