Chapter 4: Model Evaluation
Master the critical skill of measuring model performance honestly. Learn why train/test splits are essential, how to interpret classification metrics beyond accuracy, use cross-validation for robust estimates, and systematically tune hyperparameters.
- Topics
- 6
- Demo
- 1
- Videos
- 3
- Min read
- 77
Chapter Overview
Proper model evaluation is perhaps the most important skill in applied machine learning. A beautiful model that achieves 99% accuracy is worthless if that accuracy was measured on training data or if the metric doesn't capture what actually matters.
The fundamental principle is simple but often violated: never evaluate a model on data it has seen during training. This requires disciplined data management—splitting into train, validation, and test sets, and being rigorous about when each is used.
Beyond data splits, choosing the right metrics is crucial. Accuracy can be catastrophically misleading with imbalanced classes. A spam detector predicting "not spam" for everything achieves 99% accuracy if only 1% of emails are spam—yet it's completely useless. Precision, recall, F1, and AUC each tell different parts of the story.
Cross-validation provides more reliable performance estimates by averaging over multiple train/test splits. This is especially important with limited data, where a single unlucky split could give misleading results.
Finally, hyperparameter tuning requires systematic methods. Random search often outperforms grid search while being more efficient, and modern techniques like Bayesian optimization learn from past evaluations.
This chapter covers:
- Train/Test Split: The golden rule of evaluation, data leakage, and proper data handling
- Classification Metrics: Precision, recall, F1, ROC curves, PR curves, and when each matters
- Regression Metrics: MSE, MAE, R², and choosing the right metric for your problem
- Cross-Validation: K-fold, stratified, and time series methods for robust performance estimation
- Learning Curves: Diagnosing bias, variance, and deciding next steps
- Hyperparameter Tuning: Grid search, random search, Bayesian optimization, and best practices
Chapter Roadmap
Click any topic to jump in
Train/Test Split
The golden rule of evaluation — never test on training data. Data splits, stratification, leakage, and temporal considerations.
Classification and regression metrics quantify performance on held-out data
Classification Metrics
Beyond accuracy — precision, recall, F1, ROC/AUC, and choosing the right metric for imbalanced classes.
Regression Metrics
MSE, RMSE, MAE, R², and MAPE — measuring continuous prediction quality and selecting the right loss.
Cross-Validation
K-fold, stratified, and nested CV — robust performance estimates that don't depend on a single lucky split.
Learning curves reveal problems, tuning fixes them
Learning Curves
Diagnosing bias and variance visually — when to get more data vs. increase model complexity.
Hyperparameter Tuning
Grid search, random search, and Bayesian optimization — systematic approaches to finding the best model configuration.
Topics
6 topics in this chapter
A model that scores 99 percent on the data it was trained on can still fail on the first real customer. The previous chapter, Classification, built logistic regression, Naive Bayes, and other classifiers, but it never asked the harder question: how do we know any of them will work on data they have never seen? Training performance cannot answer it, because a flexible model can memorize its training set.
This chapter, Model Evaluation, is about measuring generalization honestly, and this first topic covers the foundation: holding data out. We start with why training error is optimistically biased. We then cover the basic train-test split and the three-way train, validation, and test split that keeps tuning away from the final score. Next comes stratified splitting, which preserves class ratios. We then study data leakage, the most common way evaluations lie, and finish with two structured splits: temporal splits for data that evolves over time, and group splits for data where several rows come from the same patient, user, or device.
Definition
A train-test split partitions a labeled dataset into a training set used to fit the model and a held-out test set used only to estimate performance on unseen data. A validation set may be split off as well for tuning. The split must mirror deployment, so that no information from held-out examples reaches training.
In this topic
- 1Why Split Data?
- 2Train/Test Split
- 3Train/Validation/Test
- 4Stratified Split
- 5Data Leakage
- 6Temporal Splits
- 7Group Splits
Why Split Data?
Training error measures how well a model fits examples it has already seen, which is not the question we care about. The fitting process tunes parameters specifically to those examples, so training error is biased downward, and the more flexible the model, the larger the bias. A lookup table that memorizes every training row scores perfectly yet predicts nothing useful. To estimate generalization error, the expected error on new examples drawn from the same distribution, we must score the model on data it never trained on. Everything else in this chapter refines that idea: how to hold data out, how much, and how to avoid contaminating it.
A model with parameters can perfectly memorize any dataset of points (Stone-Weierstrass theorem for universal approximators). Training error is therefore a biased estimator: . The gap is the optimism, and it grows with model complexity. Test error on unseen data is an unbiased estimator of generalization error because the model had no opportunity to fit noise in the test set.
Model achieves 99% on training data, 60% on new data. What happened?
Train/Test Split
Typical ratio: 80% train, 20% test
The simplest honest evaluation holds out a random fraction of the data, commonly 20 to 30 percent, as a test set. The model is fitted only on the training portion and scored once on the test portion, giving an unbiased estimate of generalization error. Fix the random seed, the random_state in scikit-learn, so the split is reproducible. The tradeoff is data efficiency: a larger test set gives a more precise estimate but leaves less for training. With small datasets a single split is also noisy, since a lucky or unlucky draw can move the score by several points, which motivates cross-validation later in this chapter.
With total samples and test fraction , you get training samples and test samples. The test error variance is , so a larger test set gives a tighter confidence interval. But fewer training samples means a less accurate model. The 80/20 split is a practical compromise — enough data to train, enough to get a reliable error estimate with standard error proportional to .
1000 samples, 80/20 split. How many in each set?
Train/Validation/Test
Typical: 60% train, 20% val, 20% test
Once we compare several models or hyperparameter settings, the test set can no longer be used to choose among them. Every time we pick the configuration with the best test score, we fit a little to the test set's noise, and the winning score becomes optimistic. The fix is a third split. The training set fits parameters, the validation set chooses among configurations, and the test set is touched once at the very end to report the final number. A common ratio is 60/20/20. If the test score is ever used to make a decision, it has become another validation set and is no longer unbiased.
Three-way splits allocate data to three roles with different bias profiles. Validation error guides hyperparameter selection — this introduces selection bias proportional to when choosing from configurations. The test set remains untouched, giving an unbiased final estimate. Without the validation set, optimizing on test data conflates model selection with evaluation, underestimating true error by the selection bias term.
Try 10 different model configs, pick best on validation. Then report test score. Why not pick best on test?
Stratified Split
Random splitting can distort class proportions, especially when one class is rare or the dataset is small. If the test set happens to contain few minority examples, metrics such as recall become unreliable, and if the training set is short of them, the model sees too few to learn from. Stratified splitting fixes this by splitting each class separately in the same ratio, so every subset keeps the original class proportions. In scikit-learn, pass stratify=y to train_test_split. For regression, a similar effect comes from binning the target and stratifying on the bins. It costs nothing and should be the default for classification.
For a dataset with class proportion and split size , each class count follows with variance . With rare classes () and small , the actual proportion can deviate substantially: . Stratification forces exactly in every split, eliminating this variance and ensuring each split faithfully represents the population.
Data: 90% class A, 10% class B. Random split could give test set with 2% class B. Problem?
Data Leakage
Data leakage happens when information unavailable at prediction time enters training or feature construction, producing evaluation scores that collapse in production. Target leakage uses features that are consequences of the label, such as a cancellation date when predicting churn. Train-test contamination lets test data shape training, for example fitting a scaler, imputer, or feature selector on the full dataset before splitting. Temporal leakage uses future information to predict the past. The warning sign is a score that looks too good. The fixes: fit every preprocessing step inside the training fold, with a scikit-learn Pipeline, and ask of each feature whether it would exist at prediction time.
Leakage means the model's estimate is conditioned on information that would not be available at inference time: . The training objective optimizes to exploit , producing optimistically biased error: . Common forms include fitting scalers on all data (leaking test statistics into training) and using future-dependent features (reverse causality).
Feature 'account_closed_date' predicts churn with 99% accuracy. Suspicious?
Temporal Splits
When data has a time order, a random split lets the model train on the future and predict the past, which deployment never allows. Prices, user behavior, and fraud patterns drift, so a random split also mixes neighboring periods that share conditions, inflating scores. A temporal split trains on everything before a cutoff date and tests on everything after, reproducing how the model will actually be used. Leave a gap between the two periods if labels take time to arrive. Expect temporal test scores to be lower than random-split scores; that difference is the optimism the random split was hiding.
Time series violate the i.i.d. assumption: samples have temporal correlation . A random split that puts in training and in test lets the model exploit future information, inflating accuracy. Temporal splits enforce , simulating the real deployment condition where you only have past data. The effective sample size is reduced by autocorrelation: .
Stock data 2020-2023. Random split trains on 2023 data, tests on 2021. Problem?
Group Splits
Many datasets contain several rows from the same source: multiple scans per patient, many sessions per user, or frames from one video. Rows from one group share traits, so if a group lands in both training and test sets, the model can recognize the group instead of learning the general pattern, and the test score is inflated. Group splitting assigns whole groups to one side. In scikit-learn, GroupShuffleSplit and GroupKFold take a groups array, such as patient IDs. Ask what the model will face in deployment: new patients means the test set must contain patients it has never seen.
When samples share a group identifier (e.g., patient), observations within a group have correlation . Random splits that place group members in both train and test let the model exploit within-group similarity rather than learning generalizable features. GroupKFold ensures (exclusive or), so the model must generalize across groups. The effective test set size becomes the number of unique groups, not individual samples.
10 photos per patient. Random split puts 5 photos of Patient A in train, 5 in test. Issue?
Theory Exercise
Problem:
You standardize your entire dataset (compute mean/std on all data), then split into train/test. Your model achieves 95% accuracy. What's wrong?
Hints:
- What information did the scaler learn?
- Did test data influence training?
- This is a form of data leakage
Coding Exercise
Problem:
Build an imbalanced 2-class dataset (~90/10) with make_classification, then compare the positive-class proportion in the test set from a plain train_test_split versus a stratified split (stratify=y). Show stratification preserves the class ratio.
Hints:
- Use make_classification with weights=[0.9, 0.1] and random_state=42 to create imbalance.
- Call train_test_split twice with the same random_state: once without stratify, once with stratify=y.
- Compare y_test.mean() (positive fraction) against the full dataset's y.mean().
Related Problems on PixelBank
A cancer screening model that predicts healthy for everyone is 99 percent accurate when 1 percent of patients are sick, and completely useless. The previous topic, Train/Test Split, showed how to hold out data honestly, but a held-out score is only as meaningful as the metric we compute on it. Accuracy collapses the two kinds of mistakes, false alarms and misses, into one number, and those mistakes rarely cost the same.
This topic, Classification Metrics, builds the vocabulary for measuring classifiers properly. We start with the confusion matrix, which counts every outcome. From it we derive accuracy and see where it fails, then precision, recall, and specificity, which each answer a different question. We combine precision and recall into the F1 score. We then move from single thresholds to threshold-free summaries: the ROC curve and its area, and the precision-recall curve, which behaves better on imbalanced data. We finish with log loss, which scores the quality of predicted probabilities rather than the labels alone.
Definition
Classification metrics are summary statistics that compare predicted labels or probabilities with true labels. Most derive from the confusion matrix counts of true positives, false positives, true negatives, and false negatives. Threshold-free metrics, such as ROC-AUC and precision-recall AUC, measure ranking quality, and log loss measures probability quality.
In this topic
- 1Confusion Matrix
- 2Accuracy
- 3Precision
- 4Recall (Sensitivity/TPR)
- 5Specificity (TNR)
- 6F1 Score
- 7ROC Curve & AUC
- 8Precision-Recall Curve
- 9Log Loss
Confusion Matrix
Every binary prediction falls into one of four cells. A true positive (TP) is a positive correctly flagged, and a true negative (TN) is a negative correctly passed. A false positive (FP) is a negative wrongly flagged, a false alarm. A false negative (FN) is a positive wrongly passed, a miss. Laying the counts out as a 2 by 2 grid of actual versus predicted gives the confusion matrix, and nearly every classification metric is a ratio of its cells. Always look at it before trusting a summary number, because it shows which mistakes the model makes, not just how many.
The confusion matrix is a contingency table (for binary: ) where entry counts samples with true class predicted as class . All classification metrics are functions of these four counts: . The matrix fully characterizes a classifier's behavior at a fixed threshold — every scalar metric is a lossy summary that collapses this 4-dimensional information into a single number.
Spam filter: 80 spam caught, 10 spam missed, 5 legit marked spam, 905 legit passed. TP, FP, FN, TN?
Accuracy
Accuracy is the fraction of all predictions that are correct, true positives plus true negatives over the total. It is intuitive and fine when classes are balanced and both mistakes cost about the same. It fails under imbalance: if 99 percent of examples are negative, predicting negative for everything scores 99 percent while finding nothing. Accuracy also hides which errors occur, since 10 misses and 10 false alarms look identical. Always compare it with the majority-class baseline, the accuracy of always predicting the most common class. A model is only interesting by how far it beats that number.
Accuracy = measures the fraction of correct predictions. With class imbalance ratio , a trivial classifier predicting the majority class achieves accuracy . When , a useless model scores 99%. Accuracy is only informative when classes are roughly balanced: its expected value under random prediction is , which approaches 1 as class imbalance grows.
TP=80, TN=905, FP=5, FN=10. Calculate accuracy.
Precision
Precision asks: of everything the model flagged as positive, what fraction really is? It is TP divided by TP + FP, so it falls with every false alarm. High precision matters when acting on a false positive is costly, such as sending a legitimate email to the spam folder, or blocking a valid credit card. Precision ignores misses entirely: a model that flags only its single most confident case can score 100 percent while missing nearly everything. That is why it is always reported together with recall, and why raising the decision threshold usually raises precision at recall's expense.
Precision = is the fraction of positive predictions that are correct. It answers "when I say positive, how often am I right?" Precision is critical when false positives are expensive — spam that deletes real email, fraud alerts that freeze valid cards. Mathematically, precision is the posterior , which depends on both the classifier and the class prior by Bayes' theorem.
TP=80, FP=5. Calculate precision. What does it mean?
Recall (Sensitivity/TPR)
Recall asks: of all the actual positives, what fraction did the model catch? It is TP divided by TP + FN, so it falls with every miss. Medicine calls it sensitivity, and ROC analysis calls it the true positive rate. High recall matters when misses are costly, as in cancer screening, fraud detection, or safety inspections. Recall ignores false alarms entirely: flagging every example gives 100 percent recall. Lowering the decision threshold usually raises recall and lowers precision, so the two are tuned together, with the balance set by the relative cost of misses and false alarms.
Recall = is the fraction of actual positives that are detected. It answers "of all the real positives, how many did I find?" Recall is critical when false negatives are dangerous — missing cancer diagnoses, failing to detect fraud. Recall is independent of class balance (it conditions on only), so it remains meaningful even with extreme imbalance, unlike accuracy.
TP=80, FN=10. Calculate recall. What does it mean?
Specificity (TNR)
Specificity is recall for the negative class: of all actual negatives, the fraction correctly identified, TN divided by TN + FP. It is also the true negative rate, and one minus specificity is the false positive rate on the x-axis of an ROC curve. Medical testing reports sensitivity and specificity as a pair, because together they describe the test independently of how common the disease is. The trap is that high specificity can still mean many false alarms when negatives vastly outnumber positives, which is exactly why precision, which depends on prevalence, is often more informative in rare-event problems.
Specificity = measures the true negative rate. It is the complement of the false positive rate on the ROC curve's x-axis. A test with 95% sensitivity and 90% specificity means: of 100 sick patients, 95 are detected; of 100 healthy patients, 90 are correctly cleared. The two rates are independent because they condition on different subpopulations ( vs ).
TN=905, FP=5. Calculate specificity.
F1 Score
When precision and recall both matter, the F1 score combines them as their harmonic mean, . The harmonic mean is dominated by the smaller value, so a model cannot hide poor recall behind excellent precision: 100 percent precision with 10 percent recall gives an F1 of only about 18 percent, while the arithmetic mean would say 55. The generalization weights recall times as heavily as precision, so F2 suits screening and F0.5 suits spam filtering. F1 ignores true negatives entirely, so it suits problems where the positive class is the focus.
F1 = is the harmonic mean of precision and recall. The harmonic mean penalizes imbalance: if either precision or recall is near 0, F1 is near 0 regardless of the other. Algebraically, , so it counts only errors involving the positive class — it ignores true negatives entirely. This makes F1 well-suited for imbalanced problems where TN dominates.
Precision=94.1%, Recall=88.9%. Calculate F1.
ROC Curve & AUC
A single threshold gives a single precision and recall, but a model's scores support every threshold. The ROC curve plots the true positive rate against the false positive rate as the threshold sweeps from high to low, tracing the full tradeoff. The area under it, AUC, summarizes ranking quality in one number: it equals the probability that a randomly chosen positive gets a higher score than a randomly chosen negative. An AUC of 1.0 is a perfect ranking and 0.5 is random guessing. ROC-AUC ignores calibration and class balance, which makes it a fair comparison across datasets but overly flattering on rare-event problems.
The ROC curve plots TPR vs FPR as the classification threshold sweeps from 0 to 1, tracing all possible operating points. AUC = — the probability that a randomly chosen positive sample is scored higher than a randomly chosen negative. AUC = 0.5 means random ordering; AUC = 1.0 means perfect separation. AUC is threshold-independent and prevalence-independent, making it useful for comparing classifiers across different deployment settings.
Model A: AUC=0.85. Model B: AUC=0.72. Random classifier AUC?
Precision-Recall Curve
The precision-recall curve plots precision against recall across all thresholds, and its area, PR-AUC or average precision, summarizes it. Unlike ROC, it never uses true negatives. On imbalanced data the negatives are so numerous that even a tiny false positive rate means many false alarms. ROC's x-axis barely registers them, but precision drops sharply. A random classifier's PR-AUC equals the positive rate, not 0.5, so a PR-AUC of 0.3 can be excellent when positives are 1 percent of the data. Davis and Goadrich showed that one model dominates in ROC space exactly when it dominates in PR space, but the areas can rank models differently.
The PR curve plots precision vs recall as the threshold varies. Unlike ROC, the PR curve is sensitive to class imbalance: a random classifier has (the positive class prevalence) rather than 0.5. This means PR-AUC reveals performance differences that ROC-AUC hides when positives are rare. When the positive class is 1% of data, ROC-AUC might be 0.95 while PR-AUC is only 0.20 — the PR curve exposes the classifier's struggle with false positives.
1% positive rate. ROC-AUC=0.95 for both models. PR-AUC: A=0.6, B=0.3. Which is better?
Log Loss
Accuracy and F1 only check which side of the threshold a prediction falls on, but many applications use the probabilities themselves, for ranking, pricing risk, or combining models. Log loss, the binary cross-entropy from the previous chapter, scores probability quality: each example costs minus the log of the probability assigned to its true class. Confident correct predictions cost almost nothing, hesitant ones cost more, and confident wrong ones cost a great deal. It rewards calibrated probabilities, where predictions of 0.8 come true about 80 percent of the time. A model that always predicts 0.5 scores ln 2, about 0.693, the baseline for balanced classes.
Log loss = penalizes confident wrong predictions exponentially. If the true label is 1 and the model predicts , the penalty is nats — far worse than for a less confident wrong prediction. Log loss is the negative log-likelihood of a Bernoulli model, so minimizing it is equivalent to maximum likelihood estimation. It is proper scoring rule: the minimum is achieved exactly when .
True: y=1. Model A: p=0.9, Model B: p=0.6. Compare log losses.
Theory Exercise
Problem:
A spam filter has 99% precision but only 50% recall. What does this mean in practice? When would high precision be more important than high recall?
Hints:
- Think about what FP and FN mean for spam
- What's the cost of marking a legitimate email as spam?
- What's the cost of letting spam through?
Coding Exercise
Problem:
On the breast cancer dataset, train a logistic regression and compute the confusion matrix. Derive precision, recall, and F1 by hand from the TP/FP/FN/TN counts, then verify they match sklearn's precision_score/recall_score/f1_score.
Hints:
- confusion_matrix returns [[TN, FP], [FN, TP]] for labels [0, 1]; unpack with .ravel().
- Precision = TP/(TP+FP), recall = TP/(TP+FN), F1 = 2*P*R/(P+R).
- Compare your hand-computed values to precision_score, recall_score, f1_score on the same y_test/y_pred.
Related Problems on PixelBank
A house-price model is off by 10,000 on most homes and by 300,000 on one mansion. Is it a good model? The answer depends on whether large misses matter more than small ones, whether errors should be judged in absolute or relative terms, and what the predictions will be used for. The previous topic, Classification Metrics, counted right and wrong labels, but regression predictions are never exactly right, so the question becomes how far off they are and how to summarize those distances.
This topic, Regression Metrics, covers the standard answers. We start with mean squared error and its square root, RMSE, which weight large errors heavily, then mean absolute error, which treats every unit of error equally. We compare MSE and MAE directly to see when each is appropriate. We then cover R squared, which measures error relative to a predict-the-mean baseline, and adjusted R squared, which penalizes extra features. We finish with mean absolute percentage error and a practical guide to choosing a metric that matches the business question.
Definition
Regression metrics summarize the differences between continuous predictions and true values. Scale-dependent metrics, such as MSE, RMSE, and MAE, measure error in the target's units. Relative metrics, such as R squared, compare the model with a constant baseline, and percentage metrics, such as MAPE, express each error as a fraction of the true value.
In this topic
- 1Mean Squared Error (MSE)
- 2Root Mean Squared Error (RMSE)
- 3Mean Absolute Error (MAE)
- 4MSE vs MAE
- 5R² (Coefficient of Determination)
- 6Adjusted R²
- 7Mean Absolute Percentage Error (MAPE)
- 8Choosing Metrics
Mean Squared Error (MSE)
Mean squared error averages the squared differences between true values and predictions over examples. Squaring makes every error positive and penalizes large errors disproportionately: one error of 10 costs as much as one hundred errors of 1. MSE is smooth and differentiable, which is why it is the default training loss for regression, and minimizing it yields predictions of the conditional mean. Its drawbacks are interpretability and robustness. Its units are the target's units squared, so the number itself is hard to read, and a few outliers can dominate it completely.
MSE = averages the squared residuals. Squaring amplifies large errors: a prediction off by 10 contributes 100 to MSE, while two predictions off by 5 contribute only 50 total. The gradient is linear in the residual, making optimization straightforward. MSE is the variance of residuals plus the square of their mean bias: .
Predictions: [100, 200, 150]. Actuals: [110, 190, 160]. Calculate MSE.
Root Mean Squared Error (RMSE)
RMSE is the square root of MSE, which returns the metric to the target's original units while keeping MSE's emphasis on large errors. It can be read loosely as a typical error size, although it is always at least as large as MAE, and the gap between them grows as errors become more uneven. Because it is a monotonic function of MSE, minimizing one minimizes the other, so the choice between them is about reporting, not training. RMSE is appropriate when errors are roughly normally distributed and large misses are genuinely worse. It remains sensitive to outliers.
RMSE = returns the error to the original units of . If is in dollars, RMSE is in dollars — directly interpretable. RMSE MAE always holds (by Jensen's inequality), with equality only when all errors are identical. The gap between RMSE and MAE indicates error variance: a large gap means a few predictions have outsized errors.
MSE = 100 for house price prediction (prices in thousands). What's RMSE?
Mean Absolute Error (MAE)
Mean absolute error averages the absolute differences between predictions and true values. Every unit of error counts the same, so MAE is in the target's units and reads directly as the average miss. It is more robust to outliers than MSE, because a large error contributes in proportion to its size rather than its square. Minimizing MAE yields predictions of the conditional median rather than the mean. Its main technical drawback is that the absolute value has no derivative at zero, which makes gradient-based training slightly awkward. Huber loss, which is quadratic for small errors and linear for large ones, combines both behaviors.
MAE = uses the norm of residuals. Unlike MSE, each error contributes linearly, so outliers have proportional (not quadratic) influence. The MAE-optimal prediction is the conditional median rather than the conditional mean that MSE targets. The gradient is — constant magnitude regardless of error size, which makes optimization less smooth near zero.
Errors: [-10, 10, -10, 100]. Calculate MAE and compare to RMSE.
MSE vs MAE
Choosing between MSE and MAE is choosing what kind of error matters. MSE grows with the square of the miss, so it suits problems where a large error is disproportionately bad, such as structural loads, and it targets the mean. MAE grows linearly, so it suits problems with occasional unavoidable outliers or where stakeholders think in average misses, and it targets the median. The choice changes the model you train, not just the number you report. With skewed targets, the mean and median differ, so the two losses produce different predictions. Huber loss offers a tunable compromise.
MSE and MAE target different location parameters of the conditional distribution . MSE optimizes toward the mean, MAE toward the median. For symmetric distributions they agree, but for skewed or heavy-tailed distributions they diverge. The breakdown point of MAE is 50% (up to half the data can be corrupt without destroying the estimate), while MSE has a 0% breakdown point — a single infinite outlier makes MSE infinite. Choose MAE when outlier robustness matters, MSE when you want to penalize large errors heavily.
Predicting delivery times. Occasional 2-hour delay due to traffic. Use MSE or MAE?
R² (Coefficient of Determination)
R squared compares a model's errors with a trivial baseline that always predicts the mean. is the sum of squared residuals of the model, and is the sum of squared deviations from the mean, the baseline's error. R squared is one minus their ratio. A value of 1 means perfect predictions, 0 means no better than the mean, and negative values mean worse than the mean, which can happen on test data. It is unitless, so it compares across targets. It says nothing about whether errors are small enough in absolute terms, and on training data it never decreases as features are added.
R² = compares model residuals to the baseline of predicting the mean. is the total variance; is the unexplained variance. R² = 1 means the model explains all variance; R² = 0 means it does no better than predicting . R² can be negative if the model is worse than the mean baseline — this signals a seriously broken model, not just a weak one.
SS_res=200, SS_tot=1000. Calculate R².
Adjusted R²
Training R squared never decreases when a feature is added, even pure noise, because the model can always use the new column to fit a little more of the training data. Adjusted R squared corrects for this by scaling the unexplained fraction by , where is the number of examples and the number of features. The adjustment grows as approaches , so a new feature raises adjusted R squared only if it improves the fit more than chance would. It is useful for comparing linear models of different sizes on the same data, though cross-validated error is the more general tool.
Adjusted R² = penalizes model complexity by inflating the residual term when (number of features) is large relative to (sample size). Each added feature reduces by at least a small amount (even random features), so unadjusted R² never decreases. The adjustment factor grows as , counteracting this artificial improvement. When , adjusted R² can be zero or negative even with perfect R².
Model A: R²=0.80, 5 features. Model B: R²=0.81, 50 features. n=100. Which is better?
Mean Absolute Percentage Error (MAPE)
MAPE expresses each error as a percentage of the true value and averages them, so it is unitless and easy to explain: off by 8 percent on average. That makes it popular in forecasting and business reporting across products of different scales. It has serious flaws. It is undefined when a true value is zero and explodes when true values are near zero. It is also asymmetric: for non-negative forecasts an under-forecast can cost at most 100 percent, while an over-forecast is unbounded, so minimizing MAPE biases predictions low. Symmetric MAPE or scaled errors, such as MASE, address some of these issues.
MAPE divides each error by the true value, making it scale-free: an error of 10 on an item worth 20 is 50 percent, while the same error on an item worth 1,000 is 1 percent. MAPE is undefined when and unstable near it. For non-negative forecasts the per-sample error is bounded at 100 percent when under-forecasting (predicting 0) but unbounded when over-forecasting, so a model that minimizes MAPE is pushed toward predictions below the true value.
Actual: [100, 50, 10]. Predicted: [90, 55, 8]. Calculate MAPE.
Choosing Metrics
The right metric is the one that matches how errors cost money or harm in the application, and it should be agreed before modeling starts. Use MAE when stakeholders ask how far off predictions typically are and outliers are noise. Use RMSE or MSE when large errors are disproportionately harmful. Use MAPE or a scaled error to compare across series of very different sizes, provided values stay well away from zero. Use R squared to describe how much of the variation a model explains, but pair it with an absolute metric. It is also common to train on one loss and report several metrics for different audiences.
The optimal metric depends on the loss function of the real-world problem. If errors cost proportional to their magnitude, use MAE. If large errors are disproportionately costly (e.g., energy grid imbalance), use MSE/RMSE. If relative errors matter (e.g., forecasting revenue across products of different scales), use MAPE. R² is useful for model comparison but not for optimization. In practice, evaluate multiple metrics and choose the one whose minimizer best aligns with the decision-maker's utility function.
Predict order quantities. Stakeholder asks 'how far off are we typically?' Which metric?
Theory Exercise
Problem:
Your regression model has MSE=100, MAE=8, R²=0.85 on predicting house prices (in thousands). Interpret these metrics.
Hints:
- RMSE gives you units of target
- R² tells you variance explained
- MAE is median-like error
Coding Exercise
Problem:
On the diabetes dataset, fit a linear regression and compute MSE, RMSE, MAE, and R² on the test set. Then inject a single large outlier into the predictions and recompute MSE and MAE to show MSE is far more sensitive to the outlier than MAE.
Hints:
- Use mean_squared_error, mean_absolute_error, r2_score; RMSE is np.sqrt(MSE).
- Copy y_pred and corrupt one entry by adding a large offset (e.g. +500).
- Compare the percentage increase in MSE versus MAE after the corruption.
Related Problems on PixelBank
Split 500 examples into training and test sets twice with different random seeds, and the test accuracy can move by several points. The previous topics, Train/Test Split and the two metrics topics, gave us honest held-out scores, but a single split wastes data and gives a single noisy number with no sense of its uncertainty. With small datasets that noise can be larger than the difference between the models we are trying to compare.
This topic, Cross-Validation, fixes both problems by rotating which data is held out. We start with K-fold cross-validation, where every example is tested exactly once, and discuss how to choose K. We then cover variants for specific situations: stratified K-fold for imbalanced classes, repeated K-fold for more stable estimates, and leave-one-out for tiny datasets. Next come structured variants that respect the data's dependencies: time series splits that only predict forward, and group K-fold that keeps related rows together. We finish with nested cross-validation, which gives an honest score for a model whose hyperparameters were also tuned by cross-validation.
Definition
Cross-validation is a resampling procedure that estimates generalization performance by partitioning the data into K folds, training on K minus 1 folds and evaluating on the remaining fold, and repeating until every fold has served as the test set once. The K scores are averaged, and their spread indicates the estimate's variability.
In this topic
- 1K-Fold Cross-Validation
- 2Choosing K
- 3Stratified K-Fold
- 4Repeated K-Fold
- 5Leave-One-Out (LOO)
- 6Time Series CV
- 7Group K-Fold
- 8Nested Cross-Validation
K-Fold Cross-Validation
K-fold cross-validation divides the data into K equal folds. It trains K models, each on K minus 1 folds, and scores each on the fold it left out. Every example is used for testing exactly once and for training K minus 1 times, so no data is wasted. The K scores are averaged for the estimate, and their standard deviation shows how much performance depends on the particular split. The final model is then retrained on all the data. Because the training sets overlap heavily, the K scores are correlated, so the standard deviation understates the true uncertainty of the mean.
K-fold splits data into equal folds, trains on folds, tests on the remaining fold, and rotates times. The CV estimate is . Each sample appears in exactly one test fold, so all samples contribute to the estimate. Compared to a single train/test split, K-fold reduces estimator variance by a factor of roughly (though the folds are not independent, so the reduction is not exact).
5-fold CV scores: [0.82, 0.78, 0.85, 0.80, 0.75]. Report performance.
Choosing K
The choice of K trades bias, variance, and compute. Each model trains on a fraction of the data, so a small K, such as 2 or 3, trains on noticeably less data and underestimates final performance. A larger K reduces that bias but costs K training runs, and the training sets overlap more, so the fold scores become more correlated. Kohavi's 1995 study recommended stratified 10-fold as a reliable default, and 5-fold is a common cheaper choice. For large datasets, even K = 3 or a single held-out split is enough, because each fold is already big.
The bias-variance tradeoff in K-fold: large trains on samples (low bias, closer to training on all data) but the folds share most of their training data (high correlation, high variance). Small has more bias (trains on less data) but lower correlation between folds. or is the standard — simulations show they balance bias and variance well. The computational cost scales linearly with : each fold requires a full model training.
1000 samples. K=5 vs K=10. Training set sizes?
Stratified K-Fold
Plain K-fold assigns examples to folds at random, which can leave a fold with few or no minority examples when classes are imbalanced. That fold's recall becomes undefined or wildly noisy, and the fold scores vary for reasons unrelated to the model. Stratified K-fold splits each class separately, so every fold keeps the overall class proportions. It reduces the variance of the estimate at no extra cost, which is why scikit-learn's cross_val_score uses it by default for classifiers. For regression, binning the target and stratifying on the bins gives a similar benefit.
Stratified K-Fold ensures each fold has approximately the same class proportion for every class . For rare classes with proportion , standard K-fold creates folds where the class count follows , which can be zero for small and small . Stratification eliminates this risk by distributing each class round-robin across folds. This is critical: a fold missing a class entirely produces undefined metrics for that fold.
100 samples: 90 neg, 10 pos. Regular 5-fold could give a fold with 0 positives. Problem?
Repeated K-Fold
A single K-fold run still depends on how the data was shuffled into folds; reshuffle and the mean score shifts. Repeated K-fold runs the whole procedure R times with different shuffles and averages all R times K scores, which smooths out the effect of any one partition. It is most useful on small datasets, where the partition noise is large, and when comparing models whose scores differ by only a point or two. The cost is R times the compute. The scores remain correlated, because every repetition reuses the same data, so the spread of the R times K scores still understates the true uncertainty.
Repeated K-fold runs the K-fold procedure times with different random shuffles, yielding error estimates. The variance of the mean estimate decreases as . The covariance terms are positive (folds share training data), so the variance reduction is less than . Typical choice: gives 100 estimates for a stable mean, at 10x the computational cost of single K-fold.
5-fold CV gives 80%±5%. Repeat 3 times. Now?
Leave-One-Out (LOO)
Leave-one-out cross-validation is K-fold with K equal to the number of examples : each model trains on all but one example and is tested on that one. It uses the maximum possible training data, so its estimate has very little pessimistic bias, and it involves no randomness. The costs: trainings, prohibitive for large data or slow models, and an estimate whose variance can be high, because the training sets are nearly identical and their errors are highly correlated. It suits very small datasets, and for linear regression there is a closed-form shortcut that needs only one fit.
LOO is K-fold with : each fold has one test sample. The model trains on samples, so bias is minimal (nearly the full dataset). But variance is high because the training sets differ by only one sample, making their error estimates highly correlated: . The computational cost is model trainings — prohibitive for large datasets but exact for small ones. LOO is nearly unbiased but can have higher variance than 10-fold CV.
50 samples. LOO means how many model trainings?
Time Series CV
Ordinary K-fold shuffles time-ordered data, so models train on the future and test on the past, which inflates scores. Time series cross-validation keeps the order: each split trains on an initial stretch of time and tests on the period immediately after, then moves forward. In an expanding window, the training set grows to include everything before the test period. A sliding window keeps a fixed-length recent history, which helps when old data is no longer representative. Scikit-learn's TimeSeriesSplit implements the expanding version, and its gap parameter leaves a buffer so that test labels cannot leak in.
Time series CV uses expanding or sliding windows: fold trains on and tests on , ensuring the temporal ordering in every fold. Unlike standard K-fold, folds cannot be exchanged — fold 3's test data can never be fold 1's training data. This respects the causal structure of time data. The training set size grows with each fold, so earlier folds have higher bias from smaller training sets.
Monthly data Jan-Dec. 3-fold time series split?
Group K-Fold
When rows come in groups that share hidden traits, such as several samples per patient, user, or recording session, plain K-fold scatters each group across folds. The model then partly recognizes groups it has already seen, and the score overstates performance on new groups. Group K-fold assigns whole groups to folds, so each group appears in exactly one test fold and never in its own training data. Folds may differ in size if groups do. StratifiedGroupKFold additionally balances class ratios. The rule of thumb: split by whatever unit will be new at deployment.
Group K-fold assigns entire groups (e.g., patients, stores) to folds, never splitting a group across train and test. If group has samples, all go to the same fold. The effective sample size for generalization estimation is the number of groups , not the number of samples . The folds may be unequal in size since groups vary. This prevents the model from learning group-specific patterns that inflate test scores — it must generalize across groups.
50 patients, 10 samples each (500 total). 5-fold GroupKFold. How many patients per fold?
Nested Cross-Validation
If hyperparameters are tuned by cross-validation and the best cross-validated score is reported, that score is optimistically biased, because the configuration was selected for scoring well on those same folds. Varma and Simon showed this bias can be large on small datasets. Nested cross-validation separates the two jobs. An inner loop tunes hyperparameters using only the outer training folds, and an outer loop scores the resulting tuned model on its untouched outer test fold. The outer scores estimate the performance of the whole procedure, tuning included. The cost is multiplicative, so it is used mostly for small datasets and for publishing results.
Nested CV has an outer loop for performance estimation and an inner loop for model selection. The outer loop splits into folds; within each outer training set, the inner loop runs -fold CV to select hyperparameters. This prevents information leakage from the selection process. The resulting estimate is nearly unbiased for the true generalization error of the entire pipeline (model + hyperparameter selection), not just the model. Total cost: model trainings.
Outer 5-fold, inner 3-fold. Total model trainings?
Theory Exercise
Problem:
You have medical images from 100 patients, 10 images each. You use 5-fold CV and get 95% accuracy. Why might this be overoptimistic?
Hints:
- What if images from same patient are in train and test?
- The model might recognize patient-specific features
- This is a data leakage problem
Coding Exercise
Problem:
On the iris dataset, contrast the variability of a single train/test split accuracy (across several random seeds) with 5-fold cross_val_score. Report the spread of single-split scores versus the CV mean ± std to show CV gives a more stable estimate.
Hints:
- Loop over a few random_state values, doing train_test_split + fit + score each time, and collect the accuracies.
- Use cross_val_score(model, X, y, cv=5) for the cross-validated estimate.
- Compare the min-to-max range of single-split scores against the CV mean and its std.
Related Problems on PixelBank
Your model's validation error is 15 percent and the target is 10. Should you spend a month collecting more data, or try a bigger model? Guessing wrong wastes the month. The previous topic, Cross-Validation, gave us reliable single scores, but one number cannot say why a model falls short. For that we need to watch how training and validation performance change as something varies, and the shape of those curves tells us which fix will work.
This topic, Learning Curves, turns the bias-variance tradeoff from the introduction chapter into a practical diagnostic. We start with learning curves over training set size and how to read whether more data will help. We then study the three characteristic patterns: high bias, where both errors are high and close; high variance, where a wide gap separates them; and a good fit. Next come training curves over epochs, which expose optimization problems, and validation curves over a hyperparameter. We finish by turning each diagnosis into concrete next steps.
Definition
A learning curve plots a model's training and validation performance against a quantity that varies, most often training set size, number of training epochs, or a hyperparameter value. The gap between the two curves and their final level diagnose underfitting, overfitting, or optimization problems and indicate whether more data, more capacity, or more regularization will help.
In this topic
- 1Learning Curve: Data Size
- 2High Bias Pattern
- 3High Variance Pattern
- 4Good Fit Pattern
- 5Training Curve
- 6Validation Curve
- 7Diagnosing from Curves
Learning Curve: Data Size
A data-size learning curve trains the model on increasing subsets of the training data, say 10, 20, up to 100 percent, and plots training and validation error for each. With little data, training error is low, because the model fits a few points easily, and validation error is high. As data grows, training error rises and validation error falls, and the curves approach each other. If they are still converging at the right edge, more data will help. If both have flattened at a level above the target, more data will not help, and the model itself must change. Scikit-learn's learning_curve automates this with cross-validation.
A learning curve plots model performance vs. training set size . Training error typically increases with (harder to fit more data perfectly), while validation error decreases with (more data enables better generalization). The gap between them is the generalization gap. Statistical learning theory bounds this gap: for models with VC dimension , it shrinks as . The curves converge as to the irreducible error (Bayes error).
At 1K samples: train=5%, val=15%. At 10K: train=8%, val=10%. Should you get more data?
High Bias Pattern
High bias, or underfitting, shows as training and validation errors that are both high and close together. The model cannot fit even the data it trains on, so its errors come from wrong assumptions rather than noise in the sample. On a data-size curve both lines flatten early at a poor level, so collecting more data will not help. The fixes increase the model's capacity: more or better features, polynomial or interaction terms, a more flexible model family, or less regularization. A useful check is to compare training error with a human or best-known baseline for the task.
High bias (underfitting) shows both train and validation errors converging to a high value. The model lacks capacity to capture the underlying pattern, so even with infinite data, error stays high. Mathematically, the bias term dominates because the hypothesis class cannot represent the true function . Adding more data will not help — you need a more expressive model (more parameters, non-linear features).
Train error: 25%. Validation error: 27%. Gap is small but both are high. Diagnosis?
High Variance Pattern
High variance, or overfitting, shows as a large gap: low training error and much higher validation error. The model has fit noise specific to its training sample, so it would change substantially if trained on a different sample. On a data-size curve the gap narrows as data grows, which is why more data is the most reliable fix. Other fixes reduce effective capacity: stronger regularization, fewer or simpler features, a smaller model, early stopping, dropout in neural networks, or averaging many models, as random forests do. Fixing variance usually raises training error slightly, which is expected.
High variance (overfitting) shows low training error but a large gap to validation error. The model has enough capacity to memorize training data but fails on new data. The variance term dominates — small changes in the training set produce very different models. More data helps because it constrains the model: with samples, the effective dimensionality of the learned function is where is model capacity.
Train error: 2%. Validation error: 20%. Large gap. Diagnosis?
Good Fit Pattern
A good fit shows as training and validation errors that are both low and close together, with the validation curve flattened out. The model has enough capacity to capture the real pattern but not so much that it memorizes noise. A small gap is normal and expected, because training data is always slightly easier than unseen data. Good fit is relative to the task: compare with the irreducible error, often estimated by human performance or label noise, and with the business target. Once there, the remaining gains come from better data or features rather than model tweaks, and the test set can be used.
A well-tuned model shows training and validation errors converging to a low value with a small gap. The bias-variance decomposition is balanced: . The gap between the curves approaches zero as , and both converge to near the Bayes error. This is the target state — the model is complex enough to capture the pattern but regularized enough to generalize.
Train error: 8%. Validation error: 10%. Small gap, both reasonably low. Assessment?
Training Curve
A training curve plots loss against training iterations or epochs, and its shape diagnoses optimization rather than generalization. A healthy curve falls quickly, then flattens smoothly. Spikes or a loss that climbs suggest the learning rate is too high, so steps overshoot the minimum. A curve that falls painfully slowly suggests the rate is too low. A long plateau may mean poor initialization, saturated units, or a need for learning-rate decay. Plotting validation loss on the same axes adds generalization: where validation loss turns upward while training loss keeps falling, overfitting has begun, and early stopping should stop training there.
The training curve plots training loss vs. training iterations (epochs). It always decreases for expressive models with sufficient learning rate. The rate of decrease follows roughly (power law) for neural networks. A plateau indicates a saddle point or a learning rate that is too small. A spike followed by recovery indicates the optimizer escaping a local minimum. The final training loss indicates how well the model class fits the training data.
Loss: [1.0, 0.5, 0.3, 2.1, 0.4, 3.5, ...]. Spiky! What's wrong?
Validation Curve
A validation curve plots training and validation scores against one hyperparameter, such as tree depth or regularization strength, with everything else fixed. At the low-complexity end both scores are poor, meaning high bias. At the high-complexity end the training score keeps improving while the validation score falls, meaning high variance. The best setting sits at the validation peak, where the two effects balance. Using cross-validated scores at each point makes the curve less noisy. Choosing the peak is itself a form of tuning, so the chosen value must still be confirmed on a separate test set.
A validation curve plots performance vs. a hyperparameter (e.g., regularization strength , tree depth ). As the hyperparameter increases model complexity, training error monotonically decreases while validation error is U-shaped: it decreases (reducing bias) then increases (adding variance). The optimal value is at the minimum of the validation curve — the point where the bias-variance tradeoff is best balanced.
Tree depth vs accuracy. Depth 2: 70%. Depth 5: 85%. Depth 20: 75%. Best depth?
Diagnosing from Curves
Curves are useful only when they lead to the right action. If training error is high, the problem is bias: add features, use a more flexible model, or reduce regularization, and do not bother collecting more data yet. If training error is fine but validation error is much higher, the problem is variance: add data, regularize, simplify, or ensemble. If both look fine on validation but the test or production score is worse, suspect leakage, distribution shift, or overfitting to the validation set. Change one thing at a time and redraw the curves, because a large change can overshoot from one problem into the other.
The gap between train and validation curves at a given decomposes as: gap . If both curves are high: high bias — increase model complexity. If the gap is large: high variance — get more data, add regularization, or simplify the model. If curves have not converged: more data could still help. If curves have converged with a small gap: you are near the best achievable performance for this model class — try a fundamentally different approach.
Train: 15%, Val: 16% (high bias). You add polynomial features. Now Train: 3%, Val: 25%. What happened?
Theory Exercise
Problem:
Your learning curve shows: train error steadily at 5%, validation error at 25% regardless of training set size. What's the diagnosis and what would you try?
Hints:
- Large gap between train and validation
- More data isn't helping
- Think about model complexity
Coding Exercise
Problem:
Use sklearn.model_selection.learning_curve on the breast cancer dataset to compute train and validation accuracy at increasing training-set sizes. From the numbers (not a plot), report the final train/validation gap and interpret whether the model looks high-bias, high-variance, or a good fit.
Hints:
- learning_curve returns train_sizes, train_scores, val_scores; average the score arrays over axis=1.
- Use cv=5 and train_sizes=np.linspace(0.1, 1.0, 5).
- A small train-val gap with both scores high suggests good fit; a large gap suggests high variance; both scores low suggests high bias.
A gradient-boosted model with default settings scores 82 percent; the same model with a better learning rate, depth, and number of trees scores 88. Those settings are not learned during training, so somebody has to choose them, and trying every combination by hand quickly becomes impossible. The previous topic, Learning Curves, showed how to diagnose underfitting and overfitting; tuning is how we search systematically for the settings that balance them.
This topic, Hyperparameter Tuning, closes the chapter. We start by separating hyperparameters, which we choose, from parameters, which training learns. We then compare search strategies: exhaustive grid search, random search, and why random search usually wins when only a few hyperparameters matter. Next comes Bayesian optimization, which models the score surface to choose promising settings, and successive halving, which spends little compute on poor candidates. We then cover early stopping, which tunes training length automatically, and finish by combining tuning with cross-validation, including the cost of doing it properly.
Definition
Hyperparameter tuning is the search for the hyperparameter values, settings fixed before training such as learning rate, regularization strength, or tree depth, that optimize a model's validation performance. Common strategies include grid search, random search, Bayesian optimization, and successive halving, with each candidate scored on validation data or by cross-validation, never on the test set.
In this topic
- 1Hyperparameters vs Parameters
- 2Grid Search
- 3Random Search
- 4Why Random Often Beats Grid
- 5Bayesian Optimization
- 6Successive Halving / Hyperband
- 7Early Stopping
- 8Cross-Validation in Tuning
Hyperparameters vs Parameters
A model has two kinds of numbers. Parameters, such as weights and biases, are learned from the training data by the optimizer. Hyperparameters, such as the learning rate, regularization strength, tree depth, or number of layers, are fixed before training starts and control how learning happens or how big the model is. Since training cannot set hyperparameters, we choose them by comparing validation performance across settings, effectively an outer optimization loop wrapped around training. A useful test: if changing the value requires retraining to judge it, it is a hyperparameter. Some, such as the number of epochs, can be tuned during training through early stopping.
Parameters are learned by the training algorithm (e.g., gradient descent minimizes ). Hyperparameters control the learning process itself — learning rate, regularization strength, tree depth. They live in a meta-optimization: . The number of hyperparameters is typically small (5-20) but the search space is continuous and often non-convex, making exhaustive search impractical.
Neural network: weights, biases, learning rate, batch size, num layers. Which are hyperparameters?
Grid Search
Grid search lists a few candidate values for each hyperparameter and trains a model for every combination, keeping the best by validation or cross-validated score. It is simple, exhaustive within the grid, and easy to parallelize. Its cost multiplies: hyperparameters with values each need trainings, so 5 hyperparameters at 5 values is 3,125 fits. It also only tests the values you listed, so a good setting between grid points is missed, and grid spacing for scale parameters such as learning rate should be logarithmic. It suits two or three hyperparameters with known sensible ranges.
Grid search evaluates all points on a regular grid: with values per hyperparameter and hyperparameters, it evaluates configurations. The cost grows exponentially with dimensionality — the curse of dimensionality. For 5 hyperparameters with 10 values each, that is evaluations. Grid search guarantees finding the best point on the grid, but the grid may miss good regions between grid points, especially when the optimum is between evaluated values.
C=[0.1, 1, 10], gamma=[0.01, 0.1, 1]. Grid search combinations?
Random Search
Random search samples each hyperparameter from a distribution, such as a log-uniform range for the learning rate, and trains a fixed budget of random combinations. Its cost is set by the budget, not by the number of hyperparameters, so adding a dimension does not multiply the work. Every trial tests new values of every hyperparameter, covering continuous ranges far more finely than a grid. A useful property: with 60 random trials, the chance that at least one lands in the best 5 percent of the space is about 95 percent, whatever the dimension. It is easy to parallelize and to stop early.
Random search samples hyperparameters from specified distributions (e.g., uniform, log-uniform) independently. With evaluations, each hyperparameter is tested at unique values, compared to per parameter for grid search. For and : random tests 60 values per parameter, grid tests only . This dramatic advantage grows with dimensionality and is the key theoretical result from Bergstra & Bengio (2012).
Learning rate from [0.0001, 0.1]. Grid: [0.001, 0.01, 0.1]. Random: 60 samples from log-uniform. Which explores better?
Why Random Often Beats Grid
Bergstra and Bengio observed that in most models only a few hyperparameters matter much, and which ones varies by dataset. A grid wastes most of its budget: with a 3 by 3 grid, the 9 trials test only 3 distinct values of each hyperparameter, so if one hyperparameter barely matters, 6 trials just repeat the same 3 values of the important one. Random search tests 9 distinct values of every hyperparameter, so the important dimension is explored three times as finely. The advantage grows with dimension. Grid search still wins when there are only one or two hyperparameters and their good ranges are known.
In practice, some hyperparameters matter much more than others — the effective dimensionality . Grid search wastes evaluations on unimportant dimensions: if only 2 of 5 hyperparameters matter, the grid explores the same 2 important values times while varying unimportant ones. Random search explores unique important values because each sample varies all dimensions independently. This is a direct consequence of the projection property of random sampling.
2 hyperparams: A matters a lot, B barely matters. 9-point grid vs 9 random points. Which explores A better?
Bayesian Optimization
When each training run is expensive, choosing the next trial at random wastes budget. Bayesian optimization fits a cheap surrogate model, such as a Gaussian process or a tree-structured Parzen estimator, to the scores seen so far, giving a predicted score and an uncertainty for every untried setting. An acquisition function, such as expected improvement, then picks the next trial, balancing exploitation, near the current best, against exploration, where uncertainty is high. Tools such as Optuna and Hyperopt implement it. It usually reaches good settings in fewer trials than random search, but it is more sequential and harder to parallelize.
Bayesian optimization models the objective with a surrogate (typically a Gaussian Process: ). The GP provides a posterior mean and uncertainty for untested points. An acquisition function (e.g., Expected Improvement: ) balances exploitation (low ) and exploration (high ). Each iteration evaluates the most promising point, updating the GP posterior.
Tried LR=0.01 (85%), LR=0.001 (70%), LR=0.1 (60%). Where does Bayesian opt try next?
Successive Halving / Hyperband
Most hyperparameter settings are clearly bad early in training, so training all of them to completion wastes compute. Successive halving starts many configurations on a small budget, such as one epoch or a small data subset. It then keeps the best half, doubles their budget, and repeats until one configuration remains. Total compute is a small multiple of one full run, yet many configurations are explored. The risk is that slow starters are eliminated before they would have caught up. Hyperband addresses this by running several brackets with different starting budgets. Scikit-learn provides HalvingGridSearchCV and HalvingRandomSearchCV.
Successive halving allocates a budget across configurations. In round , each surviving configuration gets resources (where is the reduction factor). The bottom fraction is eliminated each round. Total cost is , much less than . Hyperband runs successive halving with multiple brackets (varying the exploration/exploitation ratio), providing robustness against the choice of initial budget allocation.
64 configs, each needs 100 epochs. Successive halving: start all at 1 epoch, halve each round. Total epochs?
Early Stopping
Training longer lowers training loss indefinitely, but validation loss eventually turns upward as the model starts to overfit. Early stopping watches validation loss each epoch and stops when it has not improved for a set number of epochs, the patience. It then restores the weights from the best epoch. This tunes the number of epochs automatically within a single run and acts as a regularizer, limiting how far weights move from their initialization. Patience trades off noise and wasted compute: too small, and a random bump stops training early; too large, and compute is wasted. Prechelt analyzed several stopping criteria.
Early stopping monitors validation loss during training and stops when it has not improved for epochs (patience). It implicitly regularizes: the number of training iterations acts as an inverse regularization parameter — more iterations = more capacity = more overfitting risk. The effective model complexity grows with training time: . Early stopping selects the time where is minimized, equivalent to choosing the optimal regularization strength.
Val loss: [0.5, 0.4, 0.35, 0.36, 0.37, 0.38]. Patience=2. When to stop?
Cross-Validation in Tuning
Scoring each candidate on a single validation split is noisy, so with many candidates the winner is often the luckiest rather than the best. Using the K-fold cross-validated score for each candidate reduces that noise and also gives a spread, so near-ties can be recognized. Scikit-learn's GridSearchCV and RandomizedSearchCV do this and then refit the best configuration on all the training data. The cost is K times as many trainings. The winning cross-validated score is still optimistic, because it was selected, so report final performance on a held-out test set, or use nested cross-validation.
Combining CV with tuning: for each hyperparameter configuration , run -fold CV to estimate , then select . The total cost is model trainings where is the number of configurations tried. The CV error estimate for the selected is optimistically biased by due to selection — nested CV provides an unbiased outer estimate.
100 hyperparameter combos, 5-fold CV. Total model trainings?
Theory Exercise
Problem:
You have 5 hyperparameters, each with 10 possible values. How many evaluations does grid search require? If each evaluation takes 1 minute, how long would this take? Suggest a better approach.
Hints:
- Grid search tries all combinations
- Calculate 10^5
- Think about random search
Coding Exercise
Problem:
On a make_classification dataset, tune a RandomForestClassifier with both GridSearchCV and RandomizedSearchCV over the same parameter space (n_estimators, max_depth, min_samples_split). Report each best score and the number of fits, showing random search reaches a comparable score with far fewer fits.
Hints:
- Define one param dict; pass it as param_grid to GridSearchCV and as param_distributions to RandomizedSearchCV.
- Use cv=5 and a small n_iter (e.g. 6) for RandomizedSearchCV with random_state set.
- Number of grid fits = (product of grid sizes) * cv; random fits = n_iter * cv.