GridSearchCV
LogisticRegression
scikit-learn
machine learning
hyperparameter tuning

GridSearchCV on LogisticRegression in scikit-learn

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

GridSearchCV is a reliable way to tune LogisticRegression when you need a transparent, reproducible baseline model. It systematically evaluates parameter combinations using cross validation and returns the best estimator for a chosen metric. The most important part is building a valid search space that matches solver and penalty compatibility rules.

Build a Leak-Free Pipeline First

Before tuning parameters, place preprocessing and model steps in one pipeline so each fold applies transformations independently.

python
1from sklearn.datasets import load_breast_cancer
2from sklearn.linear_model import LogisticRegression
3from sklearn.model_selection import train_test_split
4from sklearn.pipeline import Pipeline
5from sklearn.preprocessing import StandardScaler
6
7X, y = load_breast_cancer(return_X_y=True)
8X_train, X_test, y_train, y_test = train_test_split(
9    X, y, test_size=0.2, stratify=y, random_state=42
10)
11
12pipe = Pipeline([
13    ("scale", StandardScaler()),
14    ("model", LogisticRegression(max_iter=3000))
15])

Keeping scaling outside the pipeline would leak validation information into training folds.

Create Solver-Compatible Parameter Grids

Not every logistic regression solver supports every penalty. Split grid definitions to avoid invalid combinations.

python
1from sklearn.model_selection import GridSearchCV
2
3param_grid = [
4    {
5        "model__solver": ["liblinear"],
6        "model__penalty": ["l1", "l2"],
7        "model__C": [0.01, 0.1, 1.0, 10.0],
8    },
9    {
10        "model__solver": ["saga"],
11        "model__penalty": ["l1", "l2", "elasticnet"],
12        "model__l1_ratio": [0.2, 0.5, 0.8],
13        "model__C": [0.01, 0.1, 1.0],
14    },
15]
16
17search = GridSearchCV(
18    estimator=pipe,
19    param_grid=param_grid,
20    scoring="f1",
21    cv=5,
22    n_jobs=-1,
23    refit=True,
24)
25
26search.fit(X_train, y_train)
27print(search.best_params_)
28print(search.best_score_)

This keeps search stable and avoids solver-penalty runtime errors.

Choose Metrics That Match Business Risk

Accuracy can be misleading on imbalanced classes. Select metrics based on operational goals.

Examples:

  • 'f1 for balancing precision and recall'
  • 'roc_auc for ranking quality'
  • custom scorer for domain-specific cost asymmetry

Pick the metric before running search so model comparison remains consistent.

Evaluate Best Estimator on Holdout Data

Do not treat cross-validation score as final production metric. Evaluate best model on untouched test data.

python
1from sklearn.metrics import classification_report, confusion_matrix
2
3best_model = search.best_estimator_
4y_pred = best_model.predict(X_test)
5
6print(confusion_matrix(y_test, y_pred))
7print(classification_report(y_test, y_pred))

This reveals real-world behavior after parameter selection.

Analyze cv_results_ for Stability

best_score_ alone hides variance across folds. Inspect cv_results_ to check whether winning parameters are consistently strong.

python
1import pandas as pd
2
3results = pd.DataFrame(search.cv_results_)
4cols = ["mean_test_score", "std_test_score", "params"]
5print(results[cols].sort_values("mean_test_score", ascending=False).head(10).to_string(index=False))

High variance can indicate unstable models, especially on smaller datasets.

Practical Runtime Optimization

Grid search can be expensive. Useful controls:

  • narrow parameter ranges based on prior experiments
  • reduce folds temporarily for quick iteration
  • move to randomized search when grid size grows large

Start with a focused grid and expand only if metrics plateau.

Save Model and Metadata Together

After choosing final estimator, persist both model and experiment metadata.

python
import joblib

joblib.dump(best_model, "logreg_grid_best.joblib")

Store alongside:

  • training data snapshot reference
  • selected metric and value
  • search parameter grid
  • package versions

This ensures reproducible retraining and easier audits.

Parallelism and Reproducibility Notes

n_jobs=-1 speeds up search on multi-core machines, but exact runtime can vary between environments. Keep fixed random seeds for splits and model initialization so score comparisons remain meaningful when rerunning experiments on different hosts.

Common Pitfalls

  • Applying preprocessing outside the pipeline and causing data leakage.
  • Mixing incompatible solver and penalty combinations.
  • Optimizing only for accuracy on imbalanced labels.
  • Declaring victory from cross-validation score without holdout evaluation.
  • Running huge grids without hypothesis and wasting compute budget.

Summary

  • Use pipeline plus GridSearchCV for reproducible logistic regression tuning.
  • Keep parameter grids solver-compatible.
  • Optimize against metrics aligned with real business costs.
  • Validate final model on untouched test data.
  • Persist estimator and experiment context for reliable deployment.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.