ML Notes
Understanding the importance of splitting data into training, validation, and test sets with proper techniques, ratios, and common mistakes to avoid.
The way you split your data determines whether you can trust your model's performance estimates. Get this wrong, and you might deploy a model that works perfectly in development but fails catastrophically in production.
Why Split Data?
| │ If you test on training data | │ |
| │ Student studies EXACT exam questions | Gets 100% │ |
| │ But learned nothing | Fails real-world problems │ |
| │ If you test on unseen data | │ |
| │ Student studies concepts | Takes NEW exam │ |
The Three-Way Split
| Training Set | Validation | Test Set |
|---|---|---|
| (60-70%) | (15-20%) | (15-20%) |
| Used to train the | Used to tune | Used ONCE at the end |
| model parameters | hyperparams | for final evaluation |
Basic Train-Test Split
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
import numpy as np
# Load data
iris = load_iris()
X, y = iris.data, iris.target
# Simple 80/20 split
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
print(f"Total samples: {len(X)}")
print(f"Training samples: {len(X_train)} ({len(X_train)/len(X):.0%})")
print(f"Testing samples: {len(X_test)} ({len(X_test)/len(X):.0%})")
# Check class distribution is maintained (stratified)
print(f"\nClass distribution:")
print(f" Original: {np.bincount(y) / len(y)}")
print(f" Training: {np.bincount(y_train) / len(y_train)}")
print(f" Testing: {np.bincount(y_test) / len(y_test)}")Three-Way Split for Hyperparameter Tuning
# Method 1: Manual three-way split
X_temp, X_test, y_temp, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
X_train, X_val, y_train, y_val = train_test_split(
X_temp, y_temp, test_size=0.25, random_state=42, stratify=y_temp # 0.25 * 0.8 = 0.2
)
print(f"Training: {len(X_train)} samples ({len(X_train)/len(X):.0%})")
print(f"Validation: {len(X_val)} samples ({len(X_val)/len(X):.0%})")
print(f"Testing: {len(X_test)} samples ({len(X_test)/len(X):.0%})")Cross-Validation Instead of Fixed Validation Set
from sklearn.model_selection import cross_val_score, StratifiedKFold
from sklearn.ensemble import RandomForestClassifier
# Cross-validation uses all data more efficiently
model = RandomForestClassifier(random_state=42)
# 5-Fold Stratified CV
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X_train, y_train, cv=cv, scoring='accuracy')
print("Cross-Validation Results:")
for i, score in enumerate(scores, 1):
print(f" Fold {i}: {score:.4f}")
print(f" Mean: {scores.mean():.4f} (+/- {scores.std():.4f})")Special Cases
Time Series Data (NO random splitting!)
Recommended Split Ratios
| Dataset Size | Train | Validation | Test |
|---|---|---|---|
| < 1,000 | Use cross-validation | (built into CV) | 20% |
| 1,000 - 100,000 | 70% | 15% | 15% |
| 100,000 - 1M | 80% | 10% | 10% |
| > 1M | 90%+ | 5% | 5% |
Common Mistakes
# WRONG: Scaling before splitting (data leakage!)
from sklearn.preprocessing import StandardScaler
# BAD - test data influences scaling
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X) # Uses ALL data
X_train_bad, X_test_bad = train_test_split(X_scaled, test_size=0.2)
# CORRECT - scale using only training data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # Fit on train only
X_test_scaled = scaler.transform(X_test) # Transform test with train params
print("Correct: Scaler fitted only on training data")Interview Questions
- Why can't you use the test set for hyperparameter tuning?
The test set must simulate truly unseen data. If you tune hyperparameters on it, you're indirectly fitting to it, and your performance estimate becomes optimistic.
- What is stratified splitting and when is it important?
Stratified splitting maintains the class proportions from the original dataset in each split. It's critical for imbalanced datasets where random splitting might leave minority classes underrepresented.
- How do you split time series data?
Never randomly — always use temporal order. Train on past data, validate/test on future data. Use TimeSeriesSplit or walk-forward validation.
- What is data leakage through preprocessing?
If you fit a scaler (or any transform) on the entire dataset before splitting, test data statistics leak into training. Always fit transforms on training data only.
- When would you use Leave-One-Out cross-validation?
With very small datasets (< 50 samples) where you can't afford to hold out many samples. It's computationally expensive but gives almost unbiased estimates.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Training vs Testing Data.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Machine Learning topic.
Search Terms
machine-learning, machine learning, machine, learning, fundamentals, training, testing, data
Related Machine Learning Topics