keras-team/keras · error · ValueError
Training and validation subsets have different number of cla
Error message
Training and validation subsets have different number of classes after the split. If your numpy arrays are sorted by the label, you might want to shuffle them.
What it means
After the validation split, the training and validation slices must contain the same set of classes (unless ignore_class_split=True). Sorted-by-label data puts all of one class in one slice, making one-hot/label encoding impossible for the missing class.
Source
Thrown at keras/src/legacy/preprocessing/image.py:594
f"Found: x.shape = {np.asarray(x).shape}, "
f"sample_weight.shape = {np.asarray(sample_weight).shape}"
)
if subset is not None:
if subset not in {"training", "validation"}:
raise ValueError(
f"Invalid subset name: {subset}"
'; expected "training" or "validation".'
)
split_idx = int(len(x) * image_data_generator._validation_split)
if (
y is not None
and not ignore_class_split
and not np.array_equal(
np.unique(y[:split_idx]), np.unique(y[split_idx:])
)
):
raise ValueError(
"Training and validation subsets "
"have different number of classes after "
"the split. If your numpy arrays are "
"sorted by the label, you might want "
"to shuffle them."
)
if subset == "validation":
x = x[:split_idx]
x_misc = [np.asarray(xx[:split_idx]) for xx in x_misc]
if y is not None:
y = y[:split_idx]
else:
x = x[split_idx:]
x_misc = [np.asarray(xx[split_idx:]) for xx in x_misc]
if y is not None:
y = y[split_idx:]
View on GitHub (pinned to 7a34a03db6)
Solutions
- Shuffle x and y jointly with the same permutation before flow()
- Or pass ignore_class_split=True if missing classes in the split are acceptable
- Use train_test_split(..., stratify=y) to keep class balance
Example fix
// before it_train = gen.flow(x, y, subset='training') # x sorted by label // after idx = np.random.permutation(len(x)) x, y = x[idx], y[idx] it_train = gen.flow(x, y, subset='training')
Defensive patterns
Strategy: validation
Validate before calling
import numpy as np perm = np.random.RandomState(42).permutation(len(x)) x, y = np.asarray(x)[perm], np.asarray(y)[perm] assert set(np.unique(y[:int(len(y)*split)])) == set(np.unique(y))
Try / catch
try: gen.flow(x, y, subset='training') except ValueError as e: if 'shuffle' in str(e): shuffle jointly and retry once
Prevention
- Always shuffle before validation_split
- Prefer stratified splits for rare classes
When it happens
Trigger: Using validation_split with NumpyArrayIterator on arrays sorted by class label, so np.unique(y[:split]) != np.unique(y[split:]).
Common situations: Dataset assembled class-by-class then split without shuffling; rare classes landing entirely in the validation slice.
Related errors
- Unknown activation function '{activation}' cannot be seriali
- Could not interpret activation function identifier: {identif
- ConvNeXt does not support the `channels_first` image data fo
- If using `weights="imagenet"` with `include_top=True`, `clas
- Architecture configuration does not match {weights_name} var
AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25).
Data as JSON: /api/errors/c34ba8dc8419748c.
Report an issue: GitHub.