超参数调优方法与实践

专栏:人工智能训练师(三级)备考全攻略
模块:卷三·知识体系 — 第三部分·模型训练与优化
难度:⭐⭐⭐☆☆
考试权重:中频(选择题+简答题)


一、什么是超参数?

模型参数(Parameters)由训练自动学习,超参数(Hyperparameters)需要人为设定

超参数分类总览
┌─────────────────────────────────────────────────────┐
│  训练超参数          │  模型结构超参数                  │
│  ─────────────────  │  ─────────────────────────     │
│  学习率 lr           │  网络层数 num_layers            │
│  批量大小 batch_size  │  隐藏层维度 hidden_size         │
│  训练轮数 epochs     │  Dropout率 dropout_rate        │
│  权重衰减 weight_decay│  激活函数类型                   │
│  学习率调度策略       │  卷积核大小 kernel_size         │
│                     │  注意力头数 num_heads           │
└─────────────────────────────────────────────────────┘

超参数影响分析

超参数 过小的影响 过大的影响 典型范围
学习率 收敛极慢,可能卡局部最优 震荡不收敛,Loss爆炸 1e-5 ~ 1e-1
batch_size 内存压力小,噪声大,泛化好 内存压力大,泛化差 16 ~ 512
weight_decay 无正则化效果 欠拟合 1e-6 ~ 1e-2
Dropout率 过拟合风险 欠拟合,训练慢 0.1 ~ 0.5

二、超参数搜索策略

2.1 四种主流方法对比

超参数搜索策略进化史:

网格搜索 → 随机搜索 → 贝叶斯优化 → 进化算法
  暴力穷举    随机采样    建模加速        种群优化
  简单可靠    效率提升    智能导向        全局最优
方法 原理 优点 缺点 适用场景
网格搜索 遍历所有参数组合 全面,结果稳定 计算量指数级增长 参数少(≤3个)
随机搜索 随机采样参数空间 同预算内更高效 不保证最优 参数多(5个以上)
贝叶斯优化 代理模型+采集函数 少次迭代找最优 实现复杂 计算代价高的模型
进化算法 模拟自然选择 全局搜索能力强 超参数多,较复杂 神经架构搜索NAS

2.2 随机搜索 vs 网格搜索(经典对比图)

网格搜索(9次评估):        随机搜索(9次评估):
  ┌───┬───┬───┐               ┌───────────┐
  │ × │ × │ × │               │  ·  ·     │
  ├───┼───┼───┤               │     ·   · │
  │ × │ × │ × │               │  ·      · │
  ├───┼───┼───┤               │    ·  ·   │
  │ × │ × │ × │               │  ·     ·  │
  └───┴───┴───┘               └───────────┘
  参数A仅3种取值              参数A探索更多区间
  → 若最优点在行间则全部漏掉  → 覆盖更多有效区间

三、代码实现:全套调优工具箱

import numpy as np
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
from scipy.stats import randint, uniform

X, y = make_classification(n_samples=1000, n_features=20, random_state=42)

# =========================================
# 方法1:网格搜索 Grid Search
# =========================================
param_grid = {
    'n_estimators': [100, 200, 300],
    'max_depth': [3, 5, 10, None],
    'min_samples_split': [2, 5, 10],
    'min_samples_leaf': [1, 2, 4]
}

grid_search = GridSearchCV(
    estimator=RandomForestClassifier(random_state=42),
    param_grid=param_grid,
    cv=5,              # 5折交叉验证
    scoring='accuracy',
    n_jobs=-1,         # 并行加速
    verbose=2
)

grid_search.fit(X, y)
print(f"最优参数: {grid_search.best_params_}")
print(f"最优分数: {grid_search.best_score_:.4f}")

# =========================================
# 方法2:随机搜索 Random Search
# =========================================
param_dist = {
    'n_estimators': randint(50, 500),       # 均匀整数分布
    'max_depth': randint(3, 20),
    'min_samples_split': randint(2, 20),
    'min_samples_leaf': randint(1, 10),
    'max_features': uniform(0.1, 0.9)       # 均匀浮点分布
}

random_search = RandomizedSearchCV(
    estimator=RandomForestClassifier(random_state=42),
    param_distributions=param_dist,
    n_iter=50,          # 只评估50个随机组合(而非全部)
    cv=5,
    scoring='accuracy',
    n_jobs=-1,
    random_state=42,
    verbose=1
)

random_search.fit(X, y)
print(f"\n随机搜索最优参数: {random_search.best_params_}")
print(f"随机搜索最优分数: {random_search.best_score_:.4f}")

# =========================================
# 方法3:贝叶斯优化(使用 optuna)
# =========================================
import optuna
optuna.logging.set_verbosity(optuna.logging.WARNING)

def objective(trial):
    """
    定义目标函数:trial.suggest_* 自动采样超参数
    贝叶斯优化会基于历史结果智能选择下一组参数
    """
    params = {
        'n_estimators': trial.suggest_int('n_estimators', 50, 500),
        'max_depth': trial.suggest_int('max_depth', 3, 20),
        '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_float('max_features', 0.1, 1.0)
    }
    
    model = RandomForestClassifier(**params, random_state=42, n_jobs=-1)
    
    from sklearn.model_selection import cross_val_score
    scores = cross_val_score(model, X, y, cv=5, scoring='accuracy', n_jobs=-1)
    return scores.mean()

# 创建研究并优化(默认TPE算法,贝叶斯变体)
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=100, timeout=60)

print(f"\nOptuna最优参数: {study.best_params}")
print(f"Optuna最优分数: {study.best_value:.4f}")

# 可视化优化历史
# optuna.visualization.plot_optimization_history(study).show()
# optuna.visualization.plot_param_importances(study).show()

四、学习率调度策略

学习率是最重要的超参数,通常配合学习率调度器使用。

4.1 常用调度策略对比

调度器 策略 适用场景
StepLR 每N轮乘以gamma 简单场景,稳定下降
CosineAnnealingLR 余弦曲线衰减 深度学习主流选择
ReduceLROnPlateau 验证集不改善则降低 自适应,适合不确定训练轮次
OneCycleLR 先升后降(超收敛) 快速训练,ResNet/BERT
WarmupScheduler 先预热再衰减 Transformer必用
import torch
import torch.optim as optim
import torch.nn as nn

model = nn.Linear(10, 1)
optimizer = optim.Adam(model.parameters(), lr=1e-3)

# ── 策略1:StepLR(每30轮×0.1)──
scheduler_step = optim.lr_scheduler.StepLR(
    optimizer, step_size=30, gamma=0.1
)

# ── 策略2:CosineAnnealingLR ──
scheduler_cosine = optim.lr_scheduler.CosineAnnealingLR(
    optimizer, T_max=100, eta_min=1e-6
)

# ── 策略3:ReduceLROnPlateau(最实用)──
scheduler_plateau = optim.lr_scheduler.ReduceLROnPlateau(
    optimizer,
    mode='min',
    factor=0.5,        # 缩小为原来的0.5
    patience=5,        # 5轮无改善则触发
    min_lr=1e-7,
    verbose=True
)

# ── 策略4:Warmup + CosineDecay(Transformer标配)──
def get_cosine_schedule_with_warmup(optimizer, num_warmup_steps, num_training_steps):
    def lr_lambda(current_step):
        if current_step < num_warmup_steps:
            return float(current_step) / float(max(1, num_warmup_steps))
        progress = float(current_step - num_warmup_steps) / \
                   float(max(1, num_training_steps - num_warmup_steps))
        return max(0.0, 0.5 * (1.0 + np.cos(np.pi * progress)))
    return optim.lr_scheduler.LambdaLR(optimizer, lr_lambda)

warmup_scheduler = get_cosine_schedule_with_warmup(
    optimizer, num_warmup_steps=100, num_training_steps=1000
)

# 训练循环中的使用方式
for epoch in range(100):
    train_loss = 0.5  # 假设训练
    val_loss = 0.6    # 假设验证
    
    # 不同调度器的step位置
    scheduler_step.step()        # 每轮结束调用
    scheduler_cosine.step()
    scheduler_plateau.step(val_loss)  # 传入验证损失

五、批量大小(Batch Size)与学习率的关系

线性缩放规则(Linear Scaling Rule):
  batch_size × k  →  lr × k
  
例:
  batch=32, lr=1e-3  →  batch=128, lr=4e-3

直觉解释:
  大batch每步梯度方向更准确(噪声小),
  可以用更大步长(学习率),加速收敛。
  但太大的batch会损失泛化能力。

六、自动化调参框架对比

框架 开发者 特点 适用场景
Optuna Preferred Networks 轻量、API简洁、支持剪枝 中小规模实验 ✅
Ray Tune Anyscale 分布式、支持所有框架 大规模实验
Hyperopt 学术界 TPE算法成熟 经典机器学习
NNI Microsoft 神经架构搜索+超参 企业级项目
W&B Sweeps Weights & Biases 与实验记录深度集成 团队协作

七、考试重点总结

7.1 核心概念辨析

概念 关键点
超参数 vs 参数 超参数人为设定,参数训练学习
网格搜索 vs 随机搜索 参数多时随机搜索更高效(Bergstra et al. 2012)
贝叶斯优化 利用代理模型预测下一个最有希望的超参数组合
学习率预热 Transformer 必用,前N步从小值线性增大到目标学习率

7.2 选择题高频考点

Q: 下列哪种方法最适合高维超参数空间调优?
A: 随机搜索 ✅(网格搜索指数爆炸,贝叶斯计算复杂)

Q: ReduceLROnPlateau 触发条件是?
A: 验证集指标连续 patience 轮无改善

Q: 学习率过大会导致?
A: Loss震荡/发散,梯度爆炸

Q: 超参数调优过程中应该用哪个集合评估?
A: 验证集(不能用测试集,否则数据泄露)

八、思维导图

超参数调优

超参数分类

训练超参数

学习率

batch_size

epochs

weight_decay

模型结构超参数

层数/维度

Dropout率

激活函数

搜索策略

网格搜索

全面但指数级

适合参数少

随机搜索

高效

参数多时更优

贝叶斯优化

Optuna/TPE

代理模型

进化算法

神经架构搜索NAS

学习率调度

StepLR

CosineAnnealing

ReduceLROnPlateau

Warmup预热

实践工具

Optuna轻量

Ray Tune分布式

W&B Sweeps


📌 备考贴士:超参数中学习率最重要,选择题常考"学习率过大/过小的现象"。贝叶斯优化是近年高频考点,记住其核心是"代理模型+采集函数",不需要手推公式,理解原理即可。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐