Skip to content

调参与超参数优化

本页速览 RL 对超参数极度敏感:学习率、γ、GAE λ、熵系数、clip 范围、网络宽度;从默认值出发的调参顺序;AutoRL 与批量实验;"先诊断后调参"的方法论。

调参与超参数优化 ​

一句话定位:这一页教你一套"先诊断、后调参"的 RL 超参数方法论——先学会读学习曲线判断病灶,再按顺序动最少、最有效的旋钮;从默认值出发,到批量实验(Optuna)与 AutoRL。它解决"照着默认值跑、不涨,就乱调一通"的日常困境,读完你会有一个清晰的调参决策树。

先立一个认知:RL 对超参数的敏感度比监督学习高一个量级。监督学习里 learning_rate=1e-3 和 1e-2 往往只是收敛快慢的区别;RL 里同一个 1e-3,换一个算法实现(PPO 的 GAE 细节、奖励归一化做没做)都可能决定"能学"还是"学崩"。而 RL 调参还有一个监督学习没有的维度:同样的超参,不同 seed 表现差异巨大。这两件事叠加,决定了"凭感觉调参"在 RL 里几乎是必败策略。

本页与评估实践是姊妹篇:评估负责"如何知道实验结果的置信度",调参负责"如何高效找到好配置"。两者共享同一套实验基础设施。

一、敏感度真相:为什么 RL 调参这么难 ​

事实监督学习RL工程含义
对学习率敏感度高(但范围宽)极高且范围窄先查学习率
训练目标稳定性静态损失目标随策略漂移(非平稳)曲线会"先好后崩"
评估噪声验证集稳定回报方差大 + seed 敏感必须多 seed 确认
实现细节影响有巨大(奖励归一化、done 处理)先复现,再调参
一次实验成本分钟级分钟~天级批量实验基建要早建

有两篇论文把这件事钉死了:Henderson et al. (2018) 证明 RL 算法对 seed 和实现细节的敏感度可以掩盖算法差异;Engstrom et al. (2020) 直接对 PPO 做消融,发现光改实现细节(学习率调度、奖励归一化)就能产生与"改进算法"同量级的性能差异。所以调参的第一守则:先确认你的"实验基准"正确,再谈调参。

最贵的坑:在"实现有 bug"的基础上调参

如果你的 PPO 忘记做 GAE mask、奖励没归一化、或者把 truncated 当失败——调参永远调不好,因为病灶不在参数。诊断调参问题的第一步永远是"跑一个已知基准(比如 CartPole 或官方默认配置)"确认管线本身是对的。见常见陷阱的复现诊断清单。

二、核心超参数速查表 ​

按算法族分,主流的超参就这几组。表中"敏感度"指"动它影响有多大"。

1. 通用(所有算法) ​

参数作用典型范围敏感度调参直觉
learning_rate步长3e-4 ~ 3e-3(PPO);1e-4 ~ 1e-3(SAC)★★★★★第一大嫌疑犯,先查它
gamma (γ)折扣因子0.9 ~ 0.999★★★★任务越长视(延迟奖励),γ 越接近 1
network width/depth容量64~512 宽、2~3 层★★★过小欠拟合、过大慢且易过拟合
seed随机性固定集合★★★★不是超参,但必须多 seed 确认
batch/minibatch size更新粒度64~4096★★★大 batch 稳但慢

2. PPO 专属 ​

参数作用典型范围敏感度调参直觉
n_steps每次更新的采样步数512 ~ 2048(单环境);向量化后按总步数★★★★太小 → 更新太频繁不稳;太大 → 数据旧
gae_lambda (λ)优势估计偏差/方差权衡0.9 ~ 0.99★★★接近 1 偏 MC(高方差);接近 0 偏 TD
clip_range (ε)单轮更新步长上限0.1 ~ 0.3★★★越大更新越激进
update_epochs复用同一批数据的轮数3 ~ 10★★★过多 → 同一批数据过拟合
ent_coef熵正则强度0 ~ 0.05★★★★探索不足调大;训练崩/随机化调小或归零

3. SAC/DDPG 等 off-policy 专属 ​

参数作用典型范围敏感度调参直觉
buffer_size回放容量1e5 ~ 1e6★★越大样本越多样,但陈旧
tau目标网络软更新系数0.005 ~ 0.01★★越小目标更新越慢
ent_coef / target_entropy熵项自动(auto)★★★首选自动温度,见Actor-Critic 家族
learning_starts回放预热步数1e3 ~ 1e4★★回放没攒够就学会振荡

从默认值出发,先别碰这些

SB3/CleanRL 的默认值都是经过调优的(SB3 的 PPO 默认 lr=3e-4、n_steps=2048、clip=0.2,是 RL 社区公认的"稳健起跑点")。第一轮实验只动一个参数,其余全默认。 你调的不是"最好配置",而是"确认每个旋钮的影响方向"。

三、调参顺序:奖励 → 环境 → 算法 → 超参 ​

调参最大的误区是一上来就动 learning_rate。正确的优先级是从最上游的病灶开始:

text
① 奖励         奖励稀疏/写歪/量级不对 → 算法再好也没用
   │              (先检查:平均回报量级、奖励项来源,见奖励工程)
② 环境         环境 bug / 观测缺信息 / 动作空间错误
   │              (先检查:环境冒烟测试、启发式基线能打几分)
③ 算法         算法族选错(该用 off-policy 用了 on-policy)
   │              (先检查:样本预算、动作空间、稳定需求)
④ 超参         前三步没问题,才是动旋钮的时候
                  (按第二节表从敏感度最高的开始)

每一步都有"一句话检查":

层检查问题如果异常
奖励启发式策略能拿到多少回报?奖励有界吗?先修奖励,别调参(奖励工程)
环境随机策略冒烟测试通过吗?观测维度正确吗?先修环境
算法样本预算够 off-policy 发挥吗?动作空间匹配吗?先换算法族(Actor-Critic 家族)
超参学习曲线形态是哪种病?按第四节诊断表对症下药

为什么顺序这么重要

一个真实案例:某团队把 PPO 的 lr 从 3e-4 调到 3e-3、clip 从 0.2 调到 0.1,折腾两周毫无起色——最后发现奖励函数漏了一个负项,导致所有策略都在"同分"区域打转。在奖励没修好之前调超参,等于给一栋地基倾斜的楼换瓷砖。

四、诊断工具:学习曲线形态分析 ​

调参要"对症下药",先学会读曲线。以下五种形态是 RL 调参最常见的"病",每种对应明确药方:

text
① 根本不涨            ② 涨了又崩          ③ 剧烈振荡
回报                  回报                 回报
 │                     │┐                   │╱╲╱╲╱╲
 │   ─────────          │╱└──┐              │╱╲╱╲╱╲╱
 │   ▁▁▁▁▁             │   ╲╲              │╱╲╱╲╱╲
 └──────────────步数    └────────步数        └────────步数

④ 缓慢爬升(没收敛)   ⑤ 前期飞涨后停滞
回报                  回报
 │      ─────          │    ────────
 │    ╱               │   ╱
 │  ╱                 │ ╱
 │╱                   │╱
 └────────────步数     └────────────步数
形态主要病因首选药方次选
① 根本不涨奖励/环境问题,或学习率过小回到第三节排查奖励与环境lr 上调一档
② 涨了又崩学习率过大 / clip 过大 / 熵太小lr 降一档(PPO 还可降 clip)加梯度裁剪
③ 剧烈振荡高方差(on-policy + 小 batch)增大 n_steps/batch增大 gae_lambda 或熵正则
④ 缓慢爬升学习率过小 / 熵过大 / 网络太小lr 上调加宽网络
⑤ 飞涨后停滞卡在局部最优 / 探索不足调大熵正则或初始探索换 seed 确认是方差还是真停滞

曲线诊断要在"多 seed"上做

单条曲线"涨了又崩"可能是真崩,也可能只是这个 seed 运气差。形态判断至少看 3 个 seed 的重叠曲线,形态一致才下诊断。这也是评估实践把 IQR 带作为默认视图的原因——IQR 带本身就是最好的诊断图。

补充诊断量:不止看回报 ​

回报是最终结果,但中间量能提前告诉你病灶在哪:

诊断量正常形态异常形态 → 病因
策略熵缓慢下降骤降 → 过早收敛;不降 → 没在学
价值损失 / TD 误差缓慢下降剧烈波动 → 学习率过大或 bootstrap 不稳
概率比(PPO)集中在 1 附近远离 1 → clip 频繁生效,更新过猛
平均回报上升见上表

五、随机搜索 vs 贝叶斯优化(Optuna) ​

当"对症单点调参"到瓶颈、或者要探一个陌生配置空间时,上批量搜索。

方法原理优点缺点适用
网格搜索每个参数取若干档全组合简单、可解释组合爆炸、浪费参数很少时
随机搜索在范围里随机采样 N 组比网格高效(高维更明显)、简单不利用历史结果起步默认
贝叶斯优化(Optuna/TPE)用历史结果建概率模型,选最可能提升的点样本效率高、自动剪枝实现复杂度高、单点串行预算有限、二次调优

实践要点:

  1. 先随机搜索探路:用随机搜索跑 30~50 组,确认"什么范围的配置能学",同时拿到一个粗糙上界。
  2. 再贝叶斯收尾:把随机搜索的结果喂给 Optuna,让它围绕好区域精挖。
  3. 每次搜索都记录:每组配置 + 结果存表,搜索结束时你得到的不只是最优配置,还有"哪个参数影响最大"(Optuna 的 importance 分析)。

Optuna 最小示例(PPO-CartPole) ​

python
import optuna
from stable_baselines3 import PPO
from stable_baselines3.common.env_util import make_vec_env

def objective(trial):
    # 每次 trial 采样一组超参
    lr = trial.suggest_float("learning_rate", 1e-4, 1e-2, log=True)
    gae = trial.suggest_float("gae_lambda", 0.9, 0.99)
    ent = trial.suggest_float("ent_coef", 0.0, 0.05)
    env = make_vec_env("CartPole-v1", n_envs=4)
    model = PPO("MlpPolicy", env, learning_rate=lr,
                gae_lambda=gae, ent_coef=ent, seed=0)
    model.learn(total_timesteps=20_000)
    # 评估(用固定评估种子,别用训练时的轨迹)
    eval_env = make_vec_env("CartPole-v1", n_envs=1)
    obs = eval_env.reset()
    total = 0.0
    for _ in range(500):
        action, _ = model.predict(obs, deterministic=True)
        obs, r, done, info = eval_env.step(action)
        total += r.item()
        if done.all():
            break
    return total   # Optuna 最大化这个值

study = optuna.create_study(direction="maximize")
study.optimize(objective, n_trials=30)
print("best params:", study.best_params)

Optuna 的隐藏陷阱

  1. 固定 seed 陷阱:上面的示例固定 seed=0——如果它对某个参数组合运气好,Optuna 会追着运气跑。正规做法是每组参数跑 3 个 seed,用中位数当目标值。
  2. 预算一致性:trial 之间 total_timesteps 必须一致,否则是在比预算不是比参数。
  3. 剪枝要小心:Optuna 的 early stopping 会砍掉"前期差"的配置,但 RL 的某些配置恰恰是"先差后好"(如熵大、探索久)。剪枝请谨慎。

六、固定 seed 陷阱与多 seed 确认 ​

这是 RL 调参里被坑得最惨的一条。完整背景见常见陷阱与反模式,这里只给操作规则:

场景允许的 seed 用法不允许
快速试参(探路)单 seed 看形态把单 seed 结果当最终结论
两配置对比同一组 seed,成对比较A 用 seed 0-4、B 用 seed 5-9
最终结论3~5+ seed,中位数 ± IQR报告"最好的一次运行"

最阴的坑:用测试配置调参

如果你先跑了一组配置、把 seed=0 跑得最好的那组选出来,然后再用 seed=0 验证——你已经在同一份随机性上"过拟合"了。验证必须换新的 seed 集合。这就是"seed 过拟合":你的"调优"其实在记忆一组随机数。

七、AutoRL 简介 ​

AutoRL 试图把整个"算法 + 超参 + 结构"的搜索自动化——本质是用元学习/进化在 RL 训练循环的外层再套一层优化。几个方向:

方向做法代表工作现状
超参搜索Optuna/BOHB 等跑批量实验SB3 + Optuna 教程成熟、工程可用
训练中动态调参训练过程中按指标调 lr/熵PBT(Population Based Training)论文常用,工程少见
学习目标自动设计让算法自动学更新规则/目标函数Learned Policy Gradient、Meta-RL研究前沿

工程视角的判断:

  • **PBT(群体并行训练)**是 AutoRL 里最"划得来"的:一群训练并行跑,表现差的个体复制好个体的权重和超参再变异。OpenAI 当年就用它调出了多个基准上的 SOTA(Lilian Weng 博客有详细介绍)。
  • 别指望 AutoRL 替代你的理解:搜索只是把"调参手艺"外包给算力,它需要你先把搜索空间、目标函数、评估协议定对——这些恰恰是前几节教的东西。

AutoRL 与搜索的边界

你以为的 AutoRL:"随便给个环境,自动找到能打 SOTA 的算法。"实际的 AutoRL:"你把搜索空间、评估协议、预算、seed 方案全部定好,它帮你穷举。"前者不存在,后者价值很大。 务实路线:先手动诊断 + 随机搜索,再 Optuna 收尾;PBT 只在团队有分布式基建时考虑。

八、实验管理:配置、日志、复现 ​

调参效率的最终决定因素不是"调得快",而是"每轮实验不浪费"。一个可追溯的实验系统让你敢大规模搜索——否则每次调参都是一次"盲盒"。

1. 配置即代码:Hydra ​

yaml
# config.yaml(一次实验的完整身份证)
seed: 42
env_id: HalfCheetah-v4

algorithm:
  name: ppo
  learning_rate: 3.0e-4
  gamma: 0.99
  gae_lambda: 0.95
  clip_range: 0.2
  ent_coef: 0.0

search:            # 若是批量搜索,记录搜索方法
  method: random
  n_trials: 40

用 Hydra 或简单的 yaml 加载器,命令行覆盖任意字段(python train.py algorithm.learning_rate=1e-3),每个实验自动存档完整 config——"复现"就退化成"重跑一个目录"。

2. 日志与版本 ​

  • 训练时记录:每 N 步写一行 (step, train_return, eval_return, entropy, loss, lr) 到 CSV 或 W&B。
  • 代码版本:实验目录里记下 git commit。
  • 依赖版本:记 pip freeze 或 lockfile。

3. 一次调参会话的最小纪律 ​

text
每一轮实验(建议画成 checklist):
  □ 只改一个变量(或明确记录改了哪些)
  □ 记录"改前/改后"的超参与结果
  □ 至少 3 个 seed 确认形态
  □ 把结论写进实验日志(哪怕一句话:"lr 3e-4→1e-3 崩了,形态③")

"只改一个变量"是纪律不是教条

批量搜索(Optuna)同时改多个变量没问题——那是系统化的探索。真正要避免的是"同时手改 5 个参数还说不清为什么"的随机式调参。纪律 = 每个改动都有记录、每个结论都有依据。

九、调参决策树总结 ​

text
策略学不动?
  ├─ 先跑已知基准(CartPole/官方默认)确认管线 OK? ── 否 → 修实现,别调参
  ├─ 奖励有问题?                                    ── 是 → 修奖励
  ├─ 环境有问题?                                    ── 是 → 修环境
  ├─ 算法族选错?                                   ── 是 → 换算法
  └─ 读学习曲线形态
       ├─ 不涨 → lr 上调
       ├─ 涨了崩 → lr/clip 下调,加梯度裁剪
       ├─ 振荡 → 加大 n_steps/batch
       ├─ 爬升慢 → lr 上调 / 熵下调
       └─ 停滞 → 熵上调 / 换 seed 确认
    之后:多 seed 确认 → 批量搜索(随机 → Optuna)→ 记录 + 报告

延伸阅读 ​

参考资料 ​

  • Henderson, P. et al. (2018). Deep Reinforcement Learning that Matters. AAAI 2018. arXiv:1709.06560
  • Engstrom, L. et al. (2020). Implementation Matters in Deep RL: A Case Study on PPO and TRPO. ICLR 2020. arXiv:1805.08292
  • Islam, R. et al. (2017). Reproducibility of Benchmarked Deep Reinforcement Learning Tasks. arXiv:1708.04133
  • Bergstra, J. & Bengio, Y. (2012). Random Search for Hyper-Parameter Optimization. JMLR 13, 281–305.(随机搜索优于网格搜索的经典论证)
  • Optuna 官方文档:optuna.org;SB3 的 Optuna 集成示例见 github.com/DLR-RM/rl-baselines3-zoo
  • Jaderberg, M. et al. (2017). Population Based Training of Neural Networks. arXiv:1711.09846(PBT 论文)
  • Lilian Weng (2019). A Gentle Introduction to PBT / AutoRL 综述. lilianweng.github.io
  • Hydra 官方文档:hydra.cc