Splitting a tensorflow dataset into training, test, and validation sets from keras.preprocessing API
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.
Introduction
When people ask how to split a TensorFlow dataset into training, validation, and test sets using the Keras preprocessing API, the important answer is that Keras preprocessing can create training and validation splits directly, but test data usually needs its own separate handling. If you try to force all three partitions out of one convenience call, the API shape often becomes the real source of confusion.
The Core Split: Training and Validation
For image directories, the current Keras-friendly pattern is image_dataset_from_directory with validation_split, subset, and a fixed seed.
The shared seed and validation_split keep the two subsets aligned so they partition the same directory consistently.
That solves only two splits:
- training
- validation
There is no automatic third "test" subset in that call.
Where the Test Set Should Come From
The cleanest approach is to keep test data separate from the start. For example:
Then use preprocessing to split only train_val:
This mirrors good machine-learning practice. The test set should be untouched by training-time decisions, so keeping it physically separate is often the least error-prone design.
If You Only Have One Directory
Sometimes you start with one directory and still need three partitions. In that case, use preprocessing to get two splits first, then split one of those again with tf.data.
Example idea:
- create a train+validation and test split outside the preprocessing helper, or
- load everything and manually slice the resulting dataset
Here is a tf.data style example using cardinality:
This works, but it is less explicit than a directory-level split, and the split is based on batches rather than raw examples unless you take extra care.
That is why a separate test directory is usually cleaner.
Older keras.preprocessing.image.ImageDataGenerator
Older tutorials often use ImageDataGenerator with validation_split:
That API has the same limitation: it gives you training and validation, not a magical third test split. If you need a test set, keep another directory or perform a separate split yourself.
Reproducibility Matters
Whenever you rely on automatic splitting, keep the split reproducible:
- set a fixed
seed - use the same split parameters in both calls
- avoid reshuffling differently between train and validation creation
Without those, the train and validation subsets may not partition the source data the way you think they do.
A Practical Recommendation
For maintainable pipelines, use this rule:
- training and validation can come from the same source directory using a split helper
- test data should usually live in a separate directory or separate manifest
That keeps evaluation honest and makes the pipeline easier to explain to other people on the project.
If you later need cross-validation or more elaborate experimental design, convenience splitting inside preprocessing is often too narrow anyway.
Common Pitfalls
The biggest mistake is assuming Keras preprocessing has a built-in three-way training/validation/test subset switch. It does not.
Another issue is creating training and validation datasets with different seeds or different split parameters, which breaks the intended partitioning.
Developers also often split after batching without realizing they are splitting batches rather than exact example counts. That may be acceptable, but it should be intentional.
Finally, do not let test data participate in tuning decisions. If the test set comes from the same convenience split loop you repeatedly rerun while experimenting, it is no longer a trustworthy final evaluation set.
Summary
- Keras preprocessing helpers can directly create training and validation splits.
- Test data is usually best kept separate rather than generated from the same helper call.
- Use the same
seed,validation_split, and source directory when building matching training and validation datasets. - Manual
tf.datasplitting is possible, but it is less explicit and can be batch-based. - A physically separate test set is usually the cleanest and safest design.
Related reading
- SSD anchors in Tensorflow detection API
- SSIM / MS-SSIM for TensorFlow
- Stateful LSTM - Hidden State transfer between and within batches Keras
- Stop Tensorflow from printing to the console
- Spring Boot embedded HornetQ cluster not forwarding messages
- squad2.0 training error THCudaCheck FAIL file/pytorch/aten/src/THC/THCGeneral.cpp line50 error100 no CUDA-capable device is detected
- Splitting values into groups evenly
- SQL based data diff longest common subsequence
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.