对完整管道进行交叉验证与网格搜索
您将把 Pipeline 传入 cross_val_score 和 GridSearchCV,并使用双下划线表示法指定各个步骤的超参数。
对完整管道进行交叉验证与网格搜索 是 CoddyKit 上的免费 Machine Learning Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Machine Learning Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Machine Learning Academy 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
Why Grid-Search a Full Pipeline?
Hyperparameter tuning should always be combined with cross-validation to prevent overfitting the validation set. When your preprocessing steps have their own parameters (e.g., PCA's n_components, OneHotEncoder's drop), those must be tuned simultaneously with the model's parameters. Wrapping everything in a Pipeline and passing it to GridSearchCV ensures all of this is done correctly without leakage.
Passing a Pipeline to cross_val_score
The simplest way to evaluate a Pipeline fairly is cross_val_score(pipeline, X, y, cv=5). Each fold re-fits the entire pipeline — including scaler and classifier — on the training portion, then evaluates on the held-out fold. The mean and standard deviation of the returned array give you a reliable generalisation estimate.
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_wine
import numpy as np
X, y = load_wine(return_X_y=True)
pipe = Pipeline([
('sc', StandardScaler()),
('lr', LogisticRegression(C=1.0, max_iter=300))
])
scores = cross_val_score(pipe, X, y, cv=5, scoring='accuracy')
print(f'CV accuracy: {np.mean(scores):.4f} +/- {np.std(scores):.4f}')Double-Underscore Notation for Pipeline Params
To reference a parameter of a named step inside the pipeline, use stepname__paramname. For nested structures like ColumnTransformer inside a Pipeline, chain the names: preprocessor__num__scaler__with_std. This convention is used both in set_params calls and in the param_grid dictionary passed to GridSearchCV.
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
pipe = Pipeline([('sc', StandardScaler()), ('svm', SVC())])
# Print all tunable parameters
params = pipe.get_params()
for k, v in params.items():
print(f' {k}: {v}')Defining a param_grid for GridSearchCV
Create a dictionary where keys are pipeline parameter names (using double-underscore notation) and values are lists of candidates to try. GridSearchCV trains and evaluates the pipeline for every combination in the Cartesian product of all lists. The total number of fits equals len(combinations) * cv_folds.
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import load_wine
X, y = load_wine(return_X_y=True)
pipe = Pipeline([('sc', StandardScaler()), ('svm', SVC())])
param_grid = {
'svm__C': [0.1, 1.0, 10.0, 100.0],
'svm__kernel': ['rbf', 'linear'],
'svm__gamma': ['scale', 'auto']
}
grid = GridSearchCV(pipe, param_grid, cv=5, n_jobs=-1, scoring='accuracy')
grid.fit(X, y)
print('Best params:', grid.best_params_)
print('Best CV score:', grid.best_score_.round(4))Tuning Preprocessor Parameters Too
You can include preprocessor parameters in the same grid. For example, tune n_components of a PCA step alongside the classifier's regularisation. This finds the optimal compression level and model complexity simultaneously, which is more rigorous than tuning them in separate steps.
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import load_digits
X, y = load_digits(return_X_y=True)
pipe = Pipeline([
('sc', StandardScaler()),
('pca', PCA()),
('lr', LogisticRegression(max_iter=500))
])
param_grid = {
'pca__n_components': [10, 20, 30, 40],
'lr__C': [0.1, 1.0, 10.0]
}
grid = GridSearchCV(pipe, param_grid, cv=5, n_jobs=-1)
grid.fit(X, y)
print('Best:', grid.best_params_)
print('Score:', grid.best_score_.round(4))Inspecting GridSearchCV Results
The cv_results_ attribute is a dictionary (convertible to a DataFrame) containing mean test scores, standard deviations, and fit times for every hyperparameter combination. Inspecting this DataFrame helps you understand the performance landscape and identify whether the best result is significantly better than the second-best, or if many parameter combinations perform similarly.
import pandas as pd
results = pd.DataFrame(grid.cv_results_)
results_sorted = results.sort_values('rank_test_score')
print(results_sorted[['param_pca__n_components', 'param_lr__C',
'mean_test_score', 'std_test_score']].head(6).to_string())RandomizedSearchCV for Large Parameter Spaces
When the parameter space is large, GridSearchCV becomes computationally prohibitive. RandomizedSearchCV samples a fixed number of combinations at random (controlled by n_iter), often finding near-optimal results in a fraction of the time. Use scipy.stats distributions for continuous parameters to sample from a range rather than discrete values.
from sklearn.model_selection import RandomizedSearchCV
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.datasets import load_wine
from scipy.stats import loguniform, uniform
X, y = load_wine(return_X_y=True)
pipe = Pipeline([('sc', StandardScaler()), ('svm', SVC())])
param_dist = {
'svm__C': loguniform(0.01, 100),
'svm__gamma': loguniform(1e-4, 1),
'svm__kernel': ['rbf', 'linear']
}
rs = RandomizedSearchCV(pipe, param_dist, n_iter=30, cv=5, random_state=42, n_jobs=-1)
rs.fit(X, y)
print('Best params:', rs.best_params_)
print('Best score:', rs.best_score_.round(4))Nested CV: Evaluation and Selection Together
Standard grid search with cross-validation slightly overfits the validation set — after choosing the best hyperparameters, you have implicitly used the validation data. Nested cross-validation solves this: the outer loop evaluates the tuned model's generalisation, the inner loop selects hyperparameters. The outer loop score is an unbiased estimate of the final model's true test performance.
from sklearn.model_selection import GridSearchCV, cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.datasets import load_iris
import numpy as np
X, y = load_iris(return_X_y=True)
pipe = Pipeline([('sc', StandardScaler()), ('svm', SVC())])
param_grid = {'svm__C': [0.1, 1.0, 10.0], 'svm__gamma': ['scale', 'auto']}
inner_cv = GridSearchCV(pipe, param_grid, cv=5, n_jobs=-1)
# Outer CV evaluates the tuning procedure itself
outer_scores = cross_val_score(inner_cv, X, y, cv=5)
print(f'Nested CV score: {np.mean(outer_scores):.4f} +/- {np.std(outer_scores):.4f}')Using the Best Estimator
After GridSearchCV.fit, the best_estimator_ attribute is the pipeline re-fitted on the entire training dataset using the best hyperparameters. This is the model you should use for final predictions. You can call predict, predict_proba, or score on it directly.
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.datasets import load_wine
X, y = load_wine(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
pipe = Pipeline([('sc', StandardScaler()), ('svm', SVC())])
param_grid = {'svm__C': [0.1, 1.0, 10.0], 'svm__kernel': ['rbf', 'linear']}
grid = GridSearchCV(pipe, param_grid, cv=5, n_jobs=-1)
grid.fit(X_train, y_train)
best = grid.best_estimator_
print('Test accuracy:', best.score(X_test, y_test).round(4))Scoring Options in GridSearchCV
By default GridSearchCV uses the estimator's default score (accuracy for classifiers). You can specify any metric with the scoring parameter: 'roc_auc', 'f1', 'neg_mean_squared_error', or a custom scorer made with make_scorer. For imbalanced datasets, 'f1_macro' or 'roc_auc' are better choices than raw accuracy.
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
X, y = load_breast_cancer(return_X_y=True)
pipe = Pipeline([('sc', StandardScaler()), ('lr', LogisticRegression(max_iter=300))])
param_grid = {'lr__C': [0.01, 0.1, 1.0, 10.0]}
grid = GridSearchCV(pipe, param_grid, cv=5, scoring='roc_auc', n_jobs=-1)
grid.fit(X, y)
print('Best C:', grid.best_params_)
print('Best ROC-AUC:', grid.best_score_.round(4))Saving the Best Pipeline
After grid search, save the best pipeline to disk. This single file contains the scaler (with its fitted means and variances), the PCA (with its components), and the classifier (with its weights) — everything needed to reproduce predictions on new data. Load it in production and call predict directly.
import joblib
# Save the best estimator
joblib.dump(grid.best_estimator_, '/tmp/best_pipeline.pkl')
# Load and verify
loaded = joblib.load('/tmp/best_pipeline.pkl')
print('Loaded pipeline test score:', loaded.score(X_test, y_test).round(4))Quick Check
Test your understanding of cross-validating and grid-searching a full pipeline from this lesson.
Lesson Recap
In this lesson you learned: cross_val_score on a Pipeline re-fits all steps per fold and gives honest generalisation estimates, double-underscore notation references nested hyperparameters in param_grid, and RandomizedSearchCV efficiently explores large parameter spaces by sampling a fixed number of random combinations. Next up we save and load a full pipeline with joblib for production deployment.
用 AI 导师学习 Python — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 30
- 课程
- 120
常见问题解答
「对完整管道进行交叉验证与网格搜索」课时是免费的吗?
是的 — 「对完整管道进行交叉验证与网格搜索」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Machine Learning Academy 课程的其余内容,请升级到 CoddyKit PRO。 Machine Learning Academy 课程共包含 4 节课。
「对完整管道进行交叉验证与网格搜索」这节课中我会学到什么?
您将把 Pipeline 传入 cross_val_score 和 GridSearchCV,并使用双下划线表示法指定各个步骤的超参数。 你通过在浏览器中直接运行的动手代码来练习 Machine Learning Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Machine Learning Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Machine Learning Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「对完整管道进行交叉验证与网格搜索」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Machine Learning Academy 课中编写并运行代码吗?
能。每节 Machine Learning Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 构建您的第一个管道:标准化器加分类器
- 管道中的 ColumnTransformer
- 对完整管道进行交叉验证与网格搜索
- 使用 joblib 保存和加载管道