关于 hyperparameter-tuning
供 AI Agent 在计算预算内搜索机器学习模型的超参数配置,涵盖搜索空间设计、试验评估与剪枝,以及结果分析,帮助选择最终训练所用参数。
主要功能
- 01定义类别、整数和浮点搜索空间
- 02网格、随机、贝叶斯与 Hyperband 策略
- 03使用交叉验证或留出数据评估
- 04提前剪枝表现不佳的试验
- 05分析参数重要性及交互作用
- 06选定最终模型训练参数
适用场景
- 01根据目标指标调整模型超参数
- 02在试验预算内比较搜索策略
- 03提前终止低效试验以节省计算资源
- 04检查哪些参数影响模型表现
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ seb1n/ awesome-ai-agent-skills --skill hyperparameter-tuning安装后在 Claude Code 中输入/hyperparameter-tuning确认已加载。
详细介绍
超参数调优
此技能可让 AI Agent 系统地搜索机器学习模型的最优超参数配置。它涵盖定义搜索空间、选择搜索策略(网格搜索、随机搜索、贝叶斯优化、Hyperband)、使用交叉验证运行试验、应用提前停止以剪枝表现不佳的配置,以及分析结果以确定表现最佳的参数。Agent 会在探索和利用之间取得平衡,在给定的计算预算内找到效果出色的配置。
工作流
-
定义搜索空间: 指定每个超参数的类型(类别、整数、浮点数)和范围。对于跨越多个数量级的参数(例如,学习率范围为 1e-5 到 1e-1),使用对数均匀分布。将相关参数分组,并定义条件搜索空间,使某些参数仅在其他参数取特定值时适用。
-
选择搜索策略: 根据计算预算和搜索空间大小选择调优算法。网格搜索会穷举搜索,但仅适用于较小的搜索空间。随机搜索是一个强有力的基线,且可扩展性更好。对于评估成本高昂的情况,贝叶斯优化(树结构 Parzen 估计器或高斯过程)的样本效率最高。Hyperband 和 ASHA 将提前停止与随机搜索结合,适用于深度学习工作负载。
-
配置评估: 设置 k 折交叉验证(通常为 5 折),以便在中小型数据集上获得可靠的性能估计。对于大型数据集或计算成本高昂的模型,请使用单个留出验证集。定义要优化的目标指标(例如,验证集 F1、AUC-ROC、RMSE),并指定要最小化还是最大化该指标。
-
运行试验并进行剪枝: 执行搜索,并尽可能并行启动试验。启用剪枝,根据中间结果(例如,训练几个轮次后)提前终止表现不佳的试验,从而将计算资源用于更有希望的配置。
-
分析并选择结果: 检查优化历史,了解哪些超参数最重要(重要性分析)。通过等高线图或平行坐标图可视化参数之间的交互。选择最佳配置,并使用这些参数在完整训练集上重新训练最终模型。
支持的技术
- 框架: Optuna、Ray Tune、scikit-learn GridSearchCV/RandomizedSearchCV、Hyperopt、Keras Tuner
- 剪枝算法: 中位数剪枝、Hyperband(逐次减半)、ASHA
- 贝叶斯方法: TPE(树结构 Parzen 估计器)、GP(高斯过程)、CMA-ES
- 可视化: Optuna 可视化(plotly)、TensorBoard HParams、Weights & Biases Sweeps
- 分布式执行: Ray Tune 集群、使用分布式存储(MySQL、PostgreSQL)的 Optuna
用法
向 Agent 提供模型、数据集、要调优的超参数及其范围、计算预算(试验次数或墙上时钟时间)和目标指标。Agent 将执行调优工作流,并返回最佳超参数配置及性能分析。
示例
示例 1:使用 Optuna Study 调优随机森林
import optuna
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score
import numpy as np
X, y = load_breast_cancer(return_X_y=True)
def objective(trial):
params = {
"n_estimators": trial.suggest_int("n_estimators", 50, 500, step=50),
"max_depth": trial.suggest_int("max_depth", 3, 30),
"min_samples_split": trial.suggest_int("min_samples_split", 2, 20),
"min_samples_leaf": trial.suggest_int("min_samples_leaf", 1, 10),
"max_features": trial.suggest_categorical("max_features", ["sqrt", "log2", None]),
"criterion": trial.suggest_categorical("criterion", ["gini", "entropy"]),
}
clf = RandomForestClassifier(**params, random_state=42, n_jobs=-1)
scores = cross_val_score(clf, X, y, cv=5, scoring="f1")
return scores.mean()
study = optuna.create_study(direction="maximize", sampler=optuna.samplers.TPESampler(seed=42))
study.optimize(objective, n_trials=100, show_progress_bar=True)
print(f"Best F1: {study.best_value:.4f}")
print(f"Best params: {study.best_params}")
# Visualization
fig_importance = optuna.visualization.plot_param_importances(study)
fig_history = optuna.visualization.plot_optimization_history(study)
fig_contour = optuna.visualization.plot_contour(study, params=["n_estimators", "max_depth"])
示例 2:使用 Ray Tune 和提前停止调优神经网络
import torch
import torch.nn as nn
from torch.utils.data import DataLoader, TensorDataset, random_split
from ray import tune
from ray.tune.schedulers import ASHAScheduler
from ray.air import session
import numpy as np
def train_nn(config):
X = torch.randn(2000, 20)
y = (X[:, 0] + X[:, 1] * 2 > 0).long()
dataset = TensorDataset(X, y)
train_set, val_set = random_split(dataset, [1600, 400])
train_loader = DataLoader(train_set, batch_size=config["batch_size"], shuffle=True)
val_loader = DataLoader(val_set, batch_size=256)
model = nn.Sequential(
nn.Linear(20, config["hidden_size"]),
nn.ReLU(),
nn.Dropout(config["dropout"]),
nn.Linear(config["hidden_size"], config["hidden_size"] // 2),
nn.ReLU(),
nn.Linear(config["hidden_size"] // 2, 2),
)
optimizer = torch.optim.Adam(model.parameters(), lr=config["lr"], weight_decay=config["weight_decay"])
criterion = nn.CrossEntropyLoss()
for epoch in range(50):
model.train()
for xb, yb in train_loader:
loss = criterion(model(xb), yb)
optimizer.zero_grad()
loss.backward()
optimizer.step()
model.eval()
correct, total = 0, 0
with torch.no_grad():
for xb, yb in val_loader:
correct += (model(xb).argmax(1) == yb).sum().item()
total += yb.size(0)
session.report({"val_accuracy": correct / total})
search_space = {
"hidden_size": tune.choice([64, 128, 256]),
"lr": tune.loguniform(1e-4, 1e-1),
"dropout": tune.uniform(0.1, 0.5),
"batch_size": tune.choice([32, 64, 128]),
"weight_decay": tune.loguniform(1e-5, 1e-2),
}
scheduler = ASHAScheduler(max_t=50, grace_period=5, reduction_factor=3)
result = tune.run(
train_nn,
config=search_space,
num_samples=50,
scheduler=scheduler,
metric="val_accuracy",
mode="max",
resources_per_trial={"cpu": 2},
)
print(f"Best config: {result.best_config}")
print(f"Best val accuracy: {result.best_result['val_accuracy']:.4f}")
最佳实践
- 对学习率、权重衰减和正则化强度使用对数均匀分布,因为最优值通常跨越多个数量级。
- 从随机搜索开始,快速找出有希望的搜索空间区域,然后切换到贝叶斯优化进行精细探索。
- 启用早停/剪枝,避免在训练数轮后明显表现不佳的配置上浪费计算资源。
- 对于小型数据集(< 50k 个样本),始终使用交叉验证计算目标分数,以降低性能估计的方差,并避免对单次验证集划分过拟合。
- 调优后运行超参数重要性分析,以了解哪些参数真正重要——通常只有 2~3 个参数决定了大部分性能差异。
- 预先设定计算预算(试验次数、GPU 小时数或实际运行时间),并选择最能充分利用该预算的搜索策略。
边缘情况
- 搜索空间巨大(> 10 个维度): 贝叶斯优化在高维情况下会退化。先使用随机搜索或 Hyperband 进行初步搜索,然后针对初步搜索识别出的最重要的 3~5 个参数运行贝叶斯优化。
- 目标值存在噪声: 当交叉验证分数的方差很大时,单次试验结果并不可靠。增加 CV 折数,使用重复 k 折交叉验证,或在比较配置前对多个随机种子取平均值。
- 超参数相关: 某些超参数会强烈相互影响(例如,学习率和批次大小)。使用 Optuna 的等高线图或 fANOVA 重要性分析来检测交互作用,并考虑一起调优相关参数组。
- 评估开销大(每次试验 > 1 小时): 使用 Hyperband 等多保真度方法,先以较小预算训练,只将有希望的配置提升至完整训练。还可考虑使用代理基准或较小的代理数据集进行初步筛选。
- 类别组合爆炸: 多个类别型超参数会导致组合数量激增时,使用条件搜索空间剪除无效组合,降低有效搜索空间的大小。