机器学习调参的关键是先固定数据边界。用 GridSearchCV 在训练集内部做交叉验证搜索,找到参数后重拟合,再只用保留的测试集做最终检查。这样才能区分“这组参数适合搜索数据”和“它对未参与搜索的样本有效”。
搜索什么,为什么放进 Pipeline
本文用 scikit-learn 自带鸢尾花数据和 SVC 教学:C 控制正则化取舍,gamma 影响 RBF 核的作用范围。示例只搜索这两个参数,不保证找到所有任务的最好方案。数据为内置教学数据,不能推断真实生产性能。

GridSearchCV 官方接口按给定参数网格搜索,用 scoring 比较候选;refit=True 会在传入的完整训练集上拟合最优候选。这里的完整训练集仍不包括留出的测试集。
官方常见错误指南建议先分割,再拟合预处理。把 StandardScaler 放进 Pipeline,可以让每一折只用该折训练部分学习均值与方差。先对全部样本标准化再搜索,会让验证折或测试集的信息提前流入。
准备独立 Python 环境
本文使用 Python 3.13。下面命令适用于 Windows PowerShell,在新建练习目录运行;其他系统用对应的 Python 路径。先用 python –version 确认版本,再创建环境。
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install "scikit-learn==1.9.1" "numpy==2.5.3" "pandas==3.0.6"
以下代码和数据只用于教学。本站于 2026-10-01 在 Windows、Python 3.13.14、scikit-learn 1.9.1、NumPy 2.5.3、pandas 3.0.6 环境运行了本文脚本;这只验证示例能执行和断言通过,不代表真实业务效果。
完整代码:9 个组合与独立测试
保存为 grid_demo.py,运行 .\.venv\Scripts\python.exe grid_demo.py。3 个 C 值乘 3 个 gamma 值,共 9 个组合;每个组合进行 3 折验证。30 条独立测试样本不参与缩放器拟合或 GridSearchCV 搜索。
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split, StratifiedKFold, GridSearchCV
from sklearn.metrics import f1_score
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, stratify=y, random_state=42)
pipeline = Pipeline([("scale", StandardScaler()), ("svc", SVC())])
grid = {"svc__C": [0.1, 1, 10], "svc__gamma": [0.01, 0.1, 1]}
cv = StratifiedKFold(n_splits=3, shuffle=True, random_state=42)
search = GridSearchCV(pipeline, grid, cv=cv, scoring="f1_macro",
n_jobs=1, refit=True, error_score="raise",
return_train_score=True)
search.fit(X_train, y_train)
table = pd.DataFrame(search.cv_results_)
cols = ["param_svc__C", "param_svc__gamma", "mean_train_score",
"mean_test_score", "std_test_score", "rank_test_score"]
print(table[cols].sort_values("rank_test_score").to_string(index=False))
print("best_params", search.best_params_)
print("best_cv_macro_f1", round(search.best_score_, 4))
pred = search.predict(X_test)
print("heldout_test_macro_f1", round(f1_score(y_test, pred, average="macro"), 4))
table[cols].to_csv("search_results.csv", index=False, encoding="utf-8-sig")
assert len(table) == 9 and len(X_test) == 30
assert len(pred) == len(y_test)
把交叉验证成绩和测试成绩分开读
param_svc__C param_svc__gamma mean_train_score mean_test_score std_test_score rank_test_score
1.0 0.10 0.975054 0.974957 0.020193 1
10.0 0.10 0.975068 0.966726 0.011446 2
10.0 0.01 0.979261 0.966726 0.011446 3
1.0 1.00 0.979171 0.958483 0.023100 4
10.0 1.00 0.995883 0.958483 0.023100 4
0.1 1.00 0.946287 0.909851 0.056266 6
1.0 0.01 0.895041 0.891145 0.045921 7
0.1 0.10 0.873195 0.874344 0.034063 8
0.1 0.01 0.515268 0.515961 0.034744 9
best_params {'svc__C': 1, 'svc__gamma': 0.1}
best_cv_macro_f1 0.975
heldout_test_macro_f1 0.9666
这是上述内置教学数据的一次本地运行输出。best_cv_macro_f1 是被选参数在训练集内部三折上的平均成绩;heldout_test_macro_f1 是保留测试集上的成绩,二者不是同一口径。样本小,分数可能因分割方式改变,不能把某次高分当可靠商用表现。
search_results.csv 应有 9 行,每行对应一个 C 与 gamma 组合。检查最优参数是否与 rank_test_score 排名一致,并看 std_test_score 的折间波动。若多个组合分数相同或很接近,应结合复杂度和稳定性选择,不必声称第一名具有明显优势。
自己的任务怎样替换
换成表格后,先确定类别定义、独立样本单位和评分。重复客户或同一设备跨记录时,要用分组划分与相应交叉验证;时间任务按时间边界切分。类别不均衡时关注宏平均 F1 或业务需要的精确率、召回率,并检查每折是否含有足够正类。
网格变大前先算成本:参数组合数乘折数是交叉验证拟合次数,refit=True 通常再拟合一次。此例 9×3=27 次交叉验证拟合,再进行一次最终训练。电脑内存受限时先用 n_jobs=1;error_score=”raise” 让非法参数或拟合错误立即显现。
失败与限制
不能看测试分数后反复扩大网格再挑参数,那会让测试集变成调参集。若结果不理想,回到训练集内部分析,并另备最终测试数据;不要继续用同一测试集证明改进。
出现 svc__C 等参数名错误时先核对 Pipeline 步骤名;少数类别样本少于折数时减少折数或补充代表数据;训练分数很高但验证分数低时优先排查过拟合、泄漏和样本分布,而不是无限增大搜索范围。
Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/30162.html