Validation and Hyperparameter Search
Grid search
Grid search tries every combination of the settings you list, scores each with cross-validation, and keeps the best — thorough, honest, and quick to explode.
- 7 min read
- 3 reading levels
- Published
Read these first
On this page 5
One lesson, three depths. Pick the one that fits you today — you can switch any time.
Beginner — No maths. Plain English.
Grid search tries every combination of the settings you list and keeps the combination that scores best.
Picture a chaiwala perfecting his recipe. He decides to test four levels of milk and four levels of sugar. So he brews all sixteen combinations, tastes each one, and keeps the winner. Nothing is skipped, nothing is guessed. The sixteen cups form a grid: milk down one side, sugar across the top.
That is the entire method. List the values you want to try for each setting, brew every combination, keep the best.
Why this had to be invented
Models have settings you must choose before training starts — how deep, how strict, how flexible. These are called hyperparameters, to separate them from the values the model learns on its own during training. No gradient descends onto them; someone has to pick.
Before systematic search, people picked by feel. Nudge a setting, retrain, squint at the score, nudge again. Unrecorded, unrepeatable, and biased toward whatever was tried last. Grid search replaced vibes with a receipt: every combination tried, every score written down, best one kept — and anyone can rerun the whole thing.
How it works
Each combination is scored with k-fold cross-validation, not a single lucky split — so the winner won on merit, not on dice.
how flexible the boundary may be
0.001 0.01 0.1 1
how 0.1 0.51 0.84 0.87 0.51 each cell = one full
strict 1 0.84 0.86 0.90 0.87 cross-validated score
the 10 0.85 0.86 [0.92] 0.86 ← best cell wins
model 100 0.85 0.90 0.90 0.86The danger is arithmetic. Two settings with four values each: 16 cells. Four settings with five values each: 625 cells — and each cell costs five trainings. The grid explodes multiplicatively, which is why this lesson has a sequel.
A real example you have seen
Any systematic taste test. A bakery trialling oven temperatures against baking times. Picture a farmer testing seed varieties against fertiliser doses in a grid of plots. Agricultural field trials have run this way for a century. Statistics grew up analysing them.
Remember this
- Hyperparameters are settings chosen before training; grid search tries every listed combination.
- Each combination is judged by cross-validation, and the receipt is rerunnable.
- Cost multiplies with every setting added — grids explode fast.
What to learn next
- Random search — same budget, better coverage, and the argument that retired big grids.
- Successive halving and Hyperband — stop wasting full budgets on hopeless candidates.
- K-fold cross-validation — the scoring engine inside every search.
Developer — Code and libraries.
Setup
pip install scikit-learnOutputs verified with scikit-learn 1.7.2 on CPU. Runs in well under a minute.
A 4 × 4 grid over an SVM
Two settings, sixteen combinations, five folds each — eighty model fits from four lines of configuration.
from sklearn.datasets import make_classification
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
X, y = make_classification(n_samples=500, n_features=10, n_informative=5,
flip_y=0.05, random_state=4)
pipe = Pipeline([("scale", StandardScaler()), ("svm", SVC())])
grid = {"svm__C": [0.1, 1, 10, 100],
"svm__gamma": [0.001, 0.01, 0.1, 1]}
search = GridSearchCV(pipe, grid, cv=5)
search.fit(X, y)
print("models trained:", len(search.cv_results_["params"]) * 5)
print("best settings:", search.best_params_)
print("best CV accuracy:", round(search.best_score_, 3))models trained: 80
best settings: {'svm__C': 10, 'svm__gamma': 0.1}
best CV accuracy: 0.916The diagram in the beginner section is this run's actual score table — search.cv_results_["mean_test_score"] reshaped to 4 × 4. Worth printing once: you see not only the winner but the landscape, including the cliff at gamma=1 where scores crash to 0.51.
The walkthrough
The Pipeline is doing quiet, critical work. Scaling sits inside the search, so each CV round fits the scaler on that round's training folds only. Scale before searching instead, and every fold's test data has leaked its statistics into training — the classic leakage bug, hidden inside a tuner.
svm__C — the double underscore routes each setting to its pipeline step: step name, two underscores, parameter name.
search.best_estimator_ is the winning configuration refitted on all the data, ready to use. GridSearchCV does this refit automatically after the search.
n_jobs=-1 parallelises across cells and folds — grid search is embarrassingly parallel, and on real problems you always want this.
Common mistakes
Reporting best_score_ as the final performance. The winner of sixteen contestants won partly by luck, so its CV score is optimistic. Evaluate best_estimator_ once on a test set no search decision ever touched — that number goes in the report.
A grid too coarse, trusted too literally. "C=10 is best" means best among 0.1, 1, 10, 100. The true optimum may sit at 30. Standard practice: coarse grid first, then a finer grid zoomed around the winner.
Exploding the grid. Adding "a couple more settings" turns 80 fits into thousands: four settings × five values × 5 folds = 3,125 fits. Before submitting that job, meet random search.
Grid values on the wrong scale. C: [1, 2, 3, 4] explores almost nothing — settings like C and gamma live on multiplicative scales, so steps should multiply (0.01, 0.1, 1, 10), not add. The score cliff between gamma=0.1 and gamma=1 above shows how fast these settings turn.
Try it yourself
Print the full landscape: search.cv_results_["mean_test_score"].reshape(4, 4). Find the cliff. Then refine: build a second grid spanning C in [3, 10, 30] and gamma in [0.03, 0.1, 0.3] and see whether zooming in beats 0.916.
What to learn next
- Random search — same budget, better coverage, and the argument that retired big grids.
- Successive halving and Hyperband — stop wasting full budgets on hopeless candidates.
- K-fold cross-validation — the scoring engine inside every search.
Researcher — Mathematics and papers.
Cost model
For hyperparameters $j = 1 \dots p$ with grids $G_j$, grid search fits
$$ N = k \cdot \prod_{j=1}^{p} |G_j| $$
models, where $k$ is the CV fold count. The exponential growth in $p$ is the curse of dimensionality in its bluntest form. Search is embarrassingly parallel across the $N$ fits; memory and scheduling, not statistics, set the practical ceiling.
Why grids spend budget badly
The decisive critique is Bergstra and Bengio (2012), Random search for hyper-parameter optimization (JMLR). Real tuning objectives have low effective dimensionality: a few hyperparameters move the score, the rest barely matter — and which few varies by dataset. A $p$-dimensional grid with $m$ points per axis evaluates only $m$ distinct values of each hyperparameter, recycling them $m^{p-1}$ times against configurations of the others. If one axis dominates, a 16-point grid has explored four values of it. Sixteen random points explore sixteen. The full argument, and its consequences, are the next lesson.
Grid search retains genuine advantages: exhaustive coverage of declared candidates (audit-friendly in regulated settings), perfect reproducibility without seed bookkeeping, and interpretable landscapes — the reshaped score matrix reveals interaction structure and cliffs that scattered samples obscure.
Selection bias of the reported maximum
The search returns $\max_c \widehat{CV}(c)$ over $C$ configurations. Even with an unbiased $\widehat{CV}$ per configuration, the maximum of $C$ noisy estimates is biased upward — the winner's-curse mechanism quantified by Cawley and Talbot (2010, JMLR) and, for CV specifically, Varma and Simon (2006). Corrections: nested CV for an unbiased estimate of the procedure, or the pragmatic untouched-test-set protocol. The bias grows with $C$ and shrinks with fold count and dataset size — a 3,125-cell grid on 500 rows is a bias factory.
The one-standard-error rule
When several cells score within noise of the maximum, Breiman et al. (1984) propose choosing the most regularised configuration within one standard error of the best (formalised in Hastie, Tibshirani and Friedman, The Elements of Statistical Learning, §7.10). Rationale: among statistically indistinguishable candidates, prefer the one with the smallest overfitting surface. cv_results_ contains the per-fold scores needed to apply it.
Where grids still belong
- $p \leq 2$ with cheap fits — the landscape picture is worth more than sampling efficiency.
- Categorical hyperparameters with few levels (kernel type, solver) — no continuous scale to sample.
- Final zoom-in around an optimum located by random or Bayesian search.
- Regulatory contexts demanding an enumerable, pre-declared search space.
Everywhere else, the sequels win: random search at equal budget, successive halving when partial training is informative, and model-based search when each fit costs hours.
What to learn next
- Random search — same budget, better coverage, and the argument that retired big grids.
- Successive halving and Hyperband — stop wasting full budgets on hopeless candidates.
- K-fold cross-validation — the scoring engine inside every search.