GridSearchCV 与 RandomizedSearchCV 都可以为分类器选超参数,但“哪个更好”必须先对齐搜索预算与交叉验证。下面让二者都评估9个候选、每个候选做同样3折验证,再比较它们探索了哪些参数与得到的验证分数。
准备环境与教学数据
以下代码已在 Windows 的 Python 3.11 独立环境运行。文中数据是人为构造或库自带的教学样本,不代表任何业务系统的效果;例子不调用在线大模型。

在空目录安装依赖,把完整代码保存为 demo.py,运行 python demo.py。使用现有 Python 环境时,先核对依赖版本。
python -m pip install numpy==2.4.6 scipy==1.17.1 scikit-learn==1.9.1
统一候选次数,但说明搜索空间
使用 scikit-learn 自带鸢尾花教学数据,先留出20%作为最终测试。训练部分走 StandardScaler 加 SVC 的 Pipeline;两种搜索共享同一个 StratifiedKFold。网格搜索在 C 与 gamma 的三个固定值上取3×3=9个组合;随机搜索在相同数值范围内按对数均匀分布抽9组,所以候选次数相同,但具体参数不相同。
RandomizedSearchCV 的 n_iter 控制抽样次数。用连续分布时不保证抽到网格端点,也不能把单次结果写成算法优劣结论。若成本主要是模型拟合,两者这里都是9×3次交叉验证拟合,另有各自 refit;实际耗时还受候选参数影响。
只在开发阶段作选择
程序打印候选数、两种搜索各自的最佳交叉验证分数与参数。只根据训练阶段的交叉验证分数选择演示赢家,再对这一个模型查看留出测试集准确率;不能反复看测试分数后重调范围。
小而明确、必须覆盖指定组合时,网格适合;连续范围大、只能试有限次数时,随机搜索更容易覆盖不同量级。对自己的任务还要先写可接受的预算、评分指标和参数范围,不能直接照抄鸢尾花的最佳参数。
完整可运行代码
from scipy.stats import loguniform
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score
from sklearn.model_selection import (GridSearchCV, RandomizedSearchCV,
StratifiedKFold, train_test_split)
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
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=19)
base = Pipeline([("scale", StandardScaler()), ("svc", SVC())])
cv = StratifiedKFold(n_splits=3, shuffle=True, random_state=5)
grid = GridSearchCV(base, {"svc__C": [0.1, 1, 10],
"svc__gamma": [0.01, 0.1, 1]},
scoring="accuracy", cv=cv, n_jobs=1)
random = RandomizedSearchCV(
base, {"svc__C": loguniform(0.1, 10),
"svc__gamma": loguniform(0.01, 1)},
n_iter=9, scoring="accuracy", cv=cv, random_state=5, n_jobs=1)
grid.fit(X_train, y_train)
random.fit(X_train, y_train)
assert len(grid.cv_results_["params"]) == len(random.cv_results_["params"]) == 9
print("candidates_grid_random", 9, 9)
print("grid_cv_accuracy", round(float(grid.best_score_), 3),
"params", grid.best_params_)
print("random_cv_accuracy", round(float(random.best_score_), 3),
"params", {k: round(float(v), 4)
for k, v in random.best_params_.items()})
winner = grid if grid.best_score_ >= random.best_score_ else random
print("chosen_by_cv", "grid" if winner is grid else "random")
print("one_final_test_accuracy",
round(float(accuracy_score(y_test, winner.predict(X_test))), 3))
运行结果与核对
下列是本文代码在上述环境的实际输出。更换运行环境时,先核对输入、代码和断言,再比较输出数值。
candidates_grid_random 9 9
grid_cv_accuracy 0.975 params {'svc__C': 10, 'svc__gamma': 0.1}
random_cv_accuracy 0.967 params {'svc__C': 3.4026, 'svc__gamma': 0.1089}
chosen_by_cv grid
one_final_test_accuracy 1.0
确认 candidates_grid_random 为9和9、两种搜索使用同一个3折对象。核对 chosen_by_cv 仅取决于开发阶段的 best_score_,最后只报告获选模型的一次保留测试分数。若真实模型训练很慢,先缩小预算再做实验,不能暗中增加某一方候选数。
适用边界
鸢尾花是小型内置教学数据,单次随机抽样和测试分数不支持宣称某工具普遍更优。相同候选次数不意味着相同参数点或完全相同计算时间;本文没有估算内存和并行作业开销。
常见问题
为什么随机搜索的最好参数不在网格表中?
它从连续分布抽值,而网格只测试列出的固定值。比较时要同时记录参数范围、抽样方式、随机种子、候选次数和评分指标。
参考资料
以下接口行为依据官方文档核对于 2026 年 10 月 1 日;本文的运行结果仅覆盖上述教学输入。
Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/31754.html