Simple Grid Search
A simple grid search is a set of nested for loops that trains and evaluates a classifier for every combination of candidate parameter values.
Why More Cores Does Not Settle the Question
A grid search is a method for finding good parameter values for a classifier. You list candidate values, try them, and keep the combination that scores best. Once you learn that a grid search can run in parallel, a natural belief follows: if one core makes the search slow, giving the search every core on the machine should make it as fast as possible. That belief is partly correct, but it is incomplete in a way that can cost time and memory. This article starts with a complete script, traces what it does, and then builds the reasoning needed to use parallelism well.
The article has three goals. First, you will follow a simple grid search step by step and count the models it trains. Second, you will see why grid search splits so neatly across cores, and where that splitting runs into limits. Third, you will examine why the reported best score can mislead you when the parameters are chosen using the test data.
Following the Nested Loops
A simple grid search is a set of nested for loops that trains and evaluates a classifier for every combination of candidate parameter values. The source introduces it using two parameters of a support vector classifier, SVC: gamma and C. The outer loop chooses a gamma value and holds it fixed. The inner loop then cycles through every C value. When the inner loop finishes, the outer loop advances to the next gamma, and the inner loop starts again from the first C value. Because of this structure, every pair of values is visited exactly once.
- The import lines and the
train_test_splitcall must run before the loops, or the script fails - The outer for loop chooses gamma and holds it fixed
- The inner for loop cycles through every C value for that gamma
- A new SVC is built with the current gamma and C on every pass
- The if statement is the only place where the stored answer can change
Inside the inner loop, four steps repeat for every combination. A new SVC is built with the current gamma and C. The model is fitted on the training data. The fitted model is scored on the test data. Finally, an if statement compares that score with best_score. If the new score is higher, both best_score and the best_parameters dictionary are overwritten. Every combination is trained and scored, but the stored result is replaced only when a new score beats the current best.
What do you think happens?
The script uses 6 gamma values and 6 C values. How many models does the nested loop train and evaluate in total?
Reveal answer
36 models
The nested loops multiply the list lengths. Each of the 6 gamma values is paired with each of the 6 C values, which gives $6 \times 6 = 36$ combinations, and each combination produces one trained and scored model.
Counting models when cross-validation is added
Suppose the same 36 parameter combinations are each evaluated with 5 cross-validation folds. How many models are trained in total? This extension is not part of the simple script, but it shows how the count multiplies.
- 1Count the parameter combinations
The grid has 6 gamma values and 6 C values, so there are $6 \times 6 = 36$ combinations.
- 2Count the folds per combination
Each combination is evaluated on 5 folds, so each combination trains 5 models.
- 3Multiply
The total is $36 \times 5 = 180$ models.
180 models, one per combination per fold
Tracking best_score and best_parameters
The stored answer starts empty. best_score begins at a value below any real score, and best_parameters is an empty dictionary. Only the if comparison can change either variable. The comparison replaces them only when a new score is higher than the current best_score. A lower score is evaluated and then ignored. The print statements run once, after every loop has finished, so they report the final stored state rather than any intermediate one.
Read the diagram as a trace. Only three evaluations change the stored answer. The scores 0.85 and 0.93 are computed and then discarded, because each is lower than the best seen so far. This is the core rule of the script: the search keeps every score in its head only long enough to compare it, and it keeps just the winning combination.
Why Grid Search Splits Across Cores
Grid search and cross-validation are embarrassingly parallel. The term means that the work divides into pieces that never need to talk to each other. Consider one combination of parameter settings evaluated on one cross-validation split. Building that model needs only the training portion of that split and the chosen parameter values. It does not need the result of any other combination or any other split. Each piece can therefore run on its own, in any order, on any core.
Locating Failures in the Script
When a grid search script fails or gives a strange result, the cause usually sits in one of a few places. Trace the script in order and check each place before blaming the model.
Common mistake Running the loops without the setup that defines the data
What it looks likeThe loops call train_test_split and refer to iris, but the import and load lines were never run, so the script stops with a NameError before any model is trained.
Why it failsThe snippet depends on earlier setup for
train_test_splitand iris. The loop body cannot run if the names it uses do not exist yet.Do this insteadRun the import and data-loading lines first, then the split, then the loops.
Common mistake Expecting the best score to come from an unexpected place
What it looks likeA reader assumes the reported best combination is the last one the loops visited.
Why it failsOnly the if comparison changes
best_scoreandbest_parameters, and it replaces them only when a new score is higher. The last combination may score lower than an earlier one.Do this insteadTrace the if statement for each evaluation, as in the best_score trace above.
Common mistake Assuming all 36 models share one training set
What it looks likeA reader assumes each SVC is trained on different data for each pair.
Why it failsIn the script, every model is fitted on the same training data and scored on the same test data. Only gamma and C change between models.
Do this insteadKeep the data fixed and vary only the parameters, so the comparison between combinations is fair.
Common mistake Nesting the loops in the wrong order changes the visit order but not the total count, so the number of models stays at 36 either way.
Overfitting the Parameters and the Validation Set
The source section on this implementation is titled to flag a danger. In the script, every combination is scored on the test set, and the combination with the highest test score is reported as best. The parameters were therefore picked to fit the test data. The reported best score is no longer an unbiased estimate of how the model will perform on new data. The selection process has leaked information from the test set into model choice.
Practice: Predicting and Tracing a Grid
Change the script so that gamma takes 3 values and C takes 4 values. Before running anything, predict the number of models trained. Then state which combination the outer loop visits first, and which combination it visits last.
Hints
- The total is the number of gamma values multiplied by the number of C values.
- The outer loop uses the first gamma value, and the inner loop runs through all 4 C values before the outer loop advances.
- The expected total is $3 \times 4 = 12$ models.
Key Takeaways
- A simple grid search is a set of nested for loops that trains and evaluates a classifier for every combination of candidate parameter values. Two lists of 6 values each produce 36 models.
- Only the if comparison changes
best_scoreandbest_parameters, and it replaces them only when a new score is higher. Lower scores are computed and then discarded. - Grid search and cross-validation are embarrassingly parallel because each fit is independent. Use
n_jobsto set the core count, with -1 requesting all cores, but keep parallelism at the search level and monitor memory. - Choosing parameters by test-set score makes the reported best score optimistic. Keep a separate validation set for selection and a test set for the final, one-time evaluation.