Stratified and Group Splits
Splits that respect class balance and entity structure
When classes are imbalanced or rows share a group, plain k-fold misrepresents the data. StratifiedKFold preserves class ratios; GroupKFold keeps every member of an entity on one side of the split.
What you will learn
- Choose stratified splitting when classes are imbalanced
- Explain why repeated entities need group splits
- Spot group leakage before it waters down your estimate
What is this?
Plain k-fold ignores two truths about real data: labels are imbalanced and rows are not independent. StratifiedKFold shuffles then partitions while preserving the target distribution in every fold, so rare classes are always represented in validation. GroupKFold partitions by a group variable instead, guaranteeing that all rows of a user, patient or session stay together in either train or test — eliminating group leakage where the model 'recognizes' entities it saw during training.
Why do you need it?
- Unstratified folds can drop a rare class entirely from validation, making fold metrics meaningless.
- Correlated rows inflate realistic difficulty: a split across the same user's sessions is deceptively easy.
- Fraud, recommendations, medical and multi-image tasks all have natural groups.
- Group-stratified CV yields the honest estimate of what will happen to new entities.
Mental model
Cooking for a family with allergies
Stratified + group splitting
You can't just split the meal any way — each served portion must include safe options for everyone (stratify on the dietary label) and never switch a guest's dish mid-meal (keep a person's courses together).
How it works
- StratifiedKFold partitions shuffled indices so each fold's label histogram mirrors the full dataset.
- For multilabel targets it stratifies on the multilabelization so each combination appears in every fold.
- GroupKFold gathers all indices sharing a group_id and assigns whole groups to folds — groups never split.
- The number of folds is bounded by the number of groups, not rows.
- Combining both (class ratio AND group integrity) is done by GroupShuffleSplit-style or custom splitters.
Rows vs groups as the unit of the split.
In production
- A fraud model splits by cardholder so the same person's transactions never cross the fold boundary.
- An image classifier splits by subject ID, not image, so a person's photos don't leak into both train and test.
- A churn model stratifies folds by churn label because churners are only 4% of accounts.
Best practices
- Prefer StratifiedKFold for single-label classification out of the box.
- Add group splits whenever you can name the entity that generates multiple rows.
- Log the split strategy in the experiment — 'KFold' vs 'GroupKFold' changes meaning.
- When groups and labels interact (rare amid common), use a stratify-within-group scheme.
Common mistakes
- Using KFold on highly imbalanced labels and trusting fold means.
- Grouping by row index instead of the true entity id, so groups are meaningless.
- Splitting by group but forgetting that stratification — both desirable — requires a combined splitter.
- Building folds from groups but training row-wise features that already encode group identity.
Common issues
Model says 0.99 on CV, fails on new customersRow-correlated instances straddled folds, letting the model memorize identities
Switch to GroupKFold keyed on the true entity id and drop entity-id features that leak membership.
GroupKFold errors when groups outnumber samplesEach group has one row; the splitter can't partition
Verify group uniqueness; if every group is unique, the data may have no group structure and KFold is fine.
Debugging tips
- Print per-fold class counts; any fold at 0 on a class is an emergency, not a surprise.
- Check for group id collision: same entity id with different feature shapes signals dirty keys.
- If CV estimates look too good, ask 'do these rows share an entity that a new user won't share?'
- Verify fold size variance — GroupKFold folds can differ a lot in row count if groups are skewed.
Interview checkpoint
Quick quiz
Your data has 10 transactions per user. To evaluate on new users, split with:
StratifiedKFold fixes group leakage.