网格搜索与随机搜索
在训练部分交叉验证候选超参数;网格枚举组合,随机搜索按分布抽样。
学习前需要掌握
背景与问题
模型参数由训练估计,超参数则规定训练过程或模型容量,例如正则化强度和树深。反复凭测试分数调整超参数,会让测试集变成开发数据,产生乐观评价。
搜索要把候选空间、划分器、主指标和预算写清楚,确保每个方案都经过同样边界内的训练与验证。
概念定义
参数由 fit 学习,超参数由搜索流程选择。GridSearchCV 穷举有限网格,RandomizedSearchCV 更适合大空间。
直观理解
不是在测试集上反复试钥匙,而是在训练区域内进行多轮模拟考试。
核心原理
GridSearchCV 枚举给定参数组合,RandomizedSearchCV 在分布中抽样。参数尺度应依据含义选择,例如正则化强度常用跨数量级候选;更大空间意味着更多训练,也增加偶然选中高分方案的机会。
预处理与模型应封装在 Pipeline 中,搜索每一折时从训练折重新拟合。参数名称通过步骤名连接到估计器,例如 model__C;搜索对象不能引用在全数据上提前学好的缩放或特征选择结果。
scoring 决定候选排名,refit 决定选择后是否在传给 fit 的完整开发集上重新训练。best_score_ 是用于选择的验证均值,不是独立最终测试表现;refit 也不会自动使用从未传入的测试数据。
多指标搜索需要预先指定用于选择的主规则。若想评价“整套调参过程”的泛化,可以使用嵌套交叉验证;最终固定流程后,再使用保留测试集做约定的最终检查。
数学表达
核心表达
先基于参数含义设置对数尺度范围,固定主 scoring 和 refit;锁定最佳方案后只测试一次。
变量含义
变量定义与本页概念定义一致,代码中的同名变量保持相同语义。
计算步骤
- 1保留测试集
- 2定义 Pipeline
- 3选择 CV 和 scoring
- 4设置合理空间
代码对应位置
示例 1完整 Pipeline 的小型网格搜索:在固定内置数据上演示搜索、候选统计与 refit;没有保留独立测试集,不声称最终性能。
案例:只比较两个正则化强度
在内置 Iris 数据上,先标准化再训练逻辑回归,候选 C 为 0.1 与 1.0,使用 3 折分层验证。每个候选需要 3 次拟合,选择后 refit 再拟合 1 次,共 7 次训练。
下方输出的最佳均值来自这个教学数据与固定划分,只用于展示搜索结果读取,不能作为独立测试分数。若看完结果再扩展候选,也仍属于开发过程;应另留独立数据验证最终选择。
计算与实现步骤
- 保留测试集
- 定义 Pipeline
- 选择 CV 和 scoring
- 设置合理空间
- 执行搜索
- 检查 cv_results_
- 最终测试
代码实现
示例 1
完整 Pipeline 的小型网格搜索
example_01.py用途:在固定内置数据上演示搜索、候选统计与 refit;没有保留独立测试集,不声称最终性能。
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV, StratifiedKFold
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
X, y = load_iris(return_X_y=True)
pipeline = Pipeline([("scale", StandardScaler()), ("model", LogisticRegression(max_iter=1000))])
cv = StratifiedKFold(3, shuffle=True, random_state=42)
search = GridSearchCV(pipeline, {"model__C": [0.1, 1.0]}, cv=cv, scoring="f1_macro", refit=True)
search.fit(X, y)
assert search.best_estimator_.n_features_in_ == 4
print("candidates:", len(search.cv_results_["params"]))
print("folds:", search.n_splits_)
print("best_C:", search.best_params_["model__C"])
print(f"selection_mean_f1={search.best_score_:.3f}")代码解析
解析始终位于完整代码下方,并按实际代码段逐项对应。
输入数据与任务
在固定内置数据上演示搜索、候选统计与 refit;没有保留独立测试集,不声称最终性能。
X- 完整特征矩阵,每行一个样本、每列一个特征。
y- 目标标签或连续目标值。
model- 组合预处理和估计器的模型对象。
Step 1 · 1–5 行
导入当前步骤需要的数值计算、预处理、模型或评价工具。依赖集中写在代码开头,便于复现。
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV, StratifiedKFold
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScalerStep 2 · 7–16 行
调用 fit 学习训练数据中的参数;若在 Pipeline 中,预处理器与模型会按顺序拟合。
X, y = load_iris(return_X_y=True)
pipeline = Pipeline([("scale", StandardScaler()), ("model", LogisticRegression(max_iter=1000))])
cv = StratifiedKFold(3, shuffle=True, random_state=42)
search = GridSearchCV(pipeline, {"model__C": [0.1, 1.0]}, cv=cv, scoring="f1_macro", refit=True)
search.fit(X, y)
assert search.best_estimator_.n_features_in_ == 4
print("candidates:", len(search.cv_results_["params"]))
print("folds:", search.n_splits_)
print("best_C:", search.best_params_["model__C"])
print(f"selection_mean_f1={search.best_score_:.3f}")代码与数学原理
减去训练均值并除以训练标准差,对应代码中的 mean/std 或 StandardScaler。
预期输出或运行结果
本地 scikit-learn 1.8.0 的核对输出: candidates: 2 folds: 3 best_C: 1.0 selection_mean_f1=0.953
常见错误 · 4 条
- 不要在测试集上调用 fit 或 fit_transform;测试集只能复用训练参数。
- 搜索前在全部样本上拟合预处理,导致每个候选的验证折都泄漏信息。
- 读取 best_score_ 后称其为最终泛化分数,或以测试集决定候选范围。
- 多指标搜索没有明确选择规则,事后挑最有利的指标宣布获胜。
实际应用
- 模型调参
- Pipeline 参数选择
常见错误
- 搜索前在全部样本上拟合预处理,导致每个候选的验证折都泄漏信息。
- 读取 best_score_ 后称其为最终泛化分数,或以测试集决定候选范围。
- 多指标搜索没有明确选择规则,事后挑最有利的指标宣布获胜。
推荐学习资料
参考库不会生成虚假资源或无效外部链接。