想象你是一位刚考下教练证的驾校教练,手上带了两个性格迥异的学员。第一个学员参加的是“场地考试”:方向盘只有三个固定挡位——左打满、右打满、回正,所有操作都是按按钮式的,要么按、要么不按。第二个学员参加的是“路考”:方向盘可以转到任意角度,油门可以踩到任意深度,每一个细微的力度都影响着车辆姿态。你很快发现,两套考场需要的教学策略完全不同:场地考试靠“背评分卡”就能拿高分,路考则必须培养一种“驾驶风格”——这就是 Atari 与 MuJoCo 两大强化学习基准环境给算法出题的两种方式。 作为教练(强化学习算法),你要在 Atari 考场里教会学员用 DQN 记下每张评分卡,在 MuJoCo 考场里用 PPO 帮学员摸索出平稳的驾驶风格。而训练中的所有诀窍——怎么打分、怎么复盘、怎么防止学员猛打方向盘、怎么公平地验证教学成果——都藏在超参数调优与工程复现的细节里。这篇教程,会把“驾校”两个考场的秘密一次讲透。

岗位关联

掌握 Atari 与 MuJoCo 两大 benchmark,是 RL 从业者的基本功。它能让你读懂论文实验、快速验证算法想法、用标准环境客观评估自己模型的效果。

目录
  1. 可视化演示
  2. 环境基座对比
  3. DQN离散控制
  4. PPO连续控制
  5. 超参数调优
  6. 训练稳定技巧
  7. 复现论文结果
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

本节配有交互动效(进入视口后自动加载,约 3KB)。

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

环境基座对比

在驾校圈里流传着一句话:学员可以傻,但教练不能不知道考场长什么样。你手下有两个训练场,格局完全不同。第一个是室内模拟机房,老式街机屏幕闪着荧光,摇杆上只有几个方向键和功能键——学员要么按,要么不按,动作天然是“离散”的。第二个是动态驾驶模拟舱,方向盘能转到任意角度,油门能踩到任意深度——一切数值都是连续可调的。不了解这两个考场,再好的教学法也用不出来。

这两个考场,就是强化学习世界里最出名的两组基准环境。Atari 来自上世纪 80 年代雅达利街机,包含打砖块、吃豆人、太空侵略者等几十款游戏,动作空间是“离散按键集合”。MuJoCo 则是一个多层接触物理仿真引擎,模拟机械臂、人形机器人、四足行走等连续控制任务,动作空间是“高维连续向量”。为了让所有算法用同一套驾考流程考试,OpenAI Gym 提供了统一接口:reset() 开考、step() 出题、reward() 打分、done() 交卷。

从数学上看,强化学习任务可以统一描述为马尔可夫决策过程(MDP)五元组:

认识了这两个考场,教练才能对症下药:场地考试动作少、状态变化快,适合背“评分卡”;路考动作连续、细微力度差别大,适合练“驾驶风格”。接下来,我们就分别讲这两套教法。

(S,A,P,R,γ)(\mathcal{S}, \mathcal{A}, \mathcal{P}, \mathcal{R}, \gamma)
这是所有 RL 问题的“公因数”:五个字母分别代表状态、动作、转移规律、奖励规则和折扣因子。Atari 与 MuJoCo 的核心差异,就集中在动作集合 \mathcal{A} 上——前者是有穷离散集合,后者是连续向量空间。
  1. 状态集合智能体感知到的世界信息。Atari 中是最近几帧游戏画面,MuJoCo 中是各关节的位置与速度向量。
    S\mathcal{S}
  2. 动作集合考场允许的所有操作。Atari 是有限按键集(离散),MuJoCo 是连续空间(逼真摇杆)。
    A\mathcal{A}
  3. 转移概率环境的物理规律——按下按钮后,世界状态会如何变化。
    P(s′∣s,a)\mathcal{P}(s'|s,a)
  4. 奖励函数每次动作能得到多少分。Atari 击碎砖块加分,MuJoCo 向前走得越远分数越高。
    R(s,a)\mathcal{R}(s,a)
  5. 折扣因子未来的分数今天值多少?范围在 0 到 1 之间,越接近 1 眼光越长。
    γ\gamma

DQN离散控制

离散考场的学员记性不太好,教练的办法是发一本“评分卡”:看到什么画面,按什么按钮,大约能赚多少分,全部记下来。每考完一局就根据实际结果更新一次。Atari 里的 DQN(深度 Q 网络),就是把这本评分卡交给深度神经网络代笔——卷积层负责“看画面”,全连接层负责“查分数”。

Q-learning 是强化学习最经典的价值迭代方法。它维护一张 Q 表(或者深度 Q 网络),估计状态-动作价值函数 Q(s,a),回答“在这个画面下,按这个按键,预期总共能拿多少收益”。DQN 用神经网络逼近这个函数,输入是帧栈叠好的游戏画面,输出是所有离散动作各自的 Q 值。

核心更新公式如下:

DQN 还配了两个防止训练崩盘的关键零件。第一是经验回放:把过去的 (状态,动作,奖励,新状态) 存进记忆池,训练时随机抽样,避免相邻样本高度相关导致网络“反复背同一道题”而忘掉其他知识。第二是目标网络:保留一份参数缓慢同步的“副校长”来为未来 Q 值打分,避免“自己给自己出题、自己给自己判卷”造成的震荡发散。Atari 特有的一步预处理是帧栈——把最近 4 帧黑白缩略图叠在一起作为状态,让智能体“看到”物体的运动速度与方向。

拿着评分卡、回顾练车录像、固定考官打分,DQN 就这样在打砖块、吃豆人等游戏上打出了超越人类玩家的分数。但这套装备到了连续考场就失灵了——评分卡没法回答“方向盘打 37 度”这种无穷多的问题。于是,轮到 PPO 登场。

Q(s,a)←Q(s,a)+α[r+γmax⁡a′Q(s′,a′)−Q(s,a)]Q(s,a) \leftarrow Q(s,a) + \alpha \left[ r + \gamma \max_{a'} Q(s',a') - Q(s,a) \right]
这条公式的意思是:把“当前对某个动作的估分”向“现实分”拉近一点。现实分 = 即时奖励 + 折扣后的未来最优分;估分与现实的差,决定了这次调整的力度。
  1. 学习率每次调整的步子大小。步子太大容易震荡,太小则进度缓慢。
    α\alpha
  2. 当前估分记录“在状态 s 下执行动作 a”的期望收益,是评分卡上被更新的一格。
    Q(s,a)Q(s,a)
  3. 未来最优分站在新状态 s' 上,挑一个 Q 值最大的动作,代表“未来最正确的决策”。
    max⁡a′Q(s′,a′)\max_{a'} Q(s',a')
  4. 折扣未来未来的收益要打折,离现在越远,今天看起来越不值钱。
    γmax⁡a′Q(s′,a′)\gamma \max_{a'} Q(s',a')

PPO连续控制

连续考场里,教练换了一套打法:不再记“每个动作值多少分”,而是观察学员的驾驶风格——这个弯你打得太早,下次晚一点;那个坡你刹车太狠,下次轻一些。每次调整都讲究“微调”两个字。这就是策略梯度家族的核心思路。

策略梯度方法直接优化策略网络 \pi_\theta(a|s)。在 MuJoCo 中,网络输出一个高斯分布的均值和标准差,动作从该分布中采样——相当于教练说“方向盘大概打 30 度,但允许 ±5 度的自然手抖”。训练时根据回报调整分布形状:带来好结果的动作提高概率,带来坏结果的动作压低概率。

但直接梯度上升容易把策略带跑偏——学员一次调整太猛,车直接冲出考场。PPO(近端策略优化)通过裁剪目标函数,把每次参数更新的幅度锁死在安全区内:

PPO 就这样成了 MuJoCo 路考里的“满分教练”:每次小幅调整风格、用 GAE(广义优势估计)平滑地评估每一步是好是坏、再用裁剪锁死更新上限,让学员在连续控制的物理世界里稳稳跑向终点。理解了 PPO,再去看大语言模型的 RLHF 对齐,你会发现同样的“稳字诀”统治了多个领域。

LCLIP(θ)=Et[min⁡(ρt(θ)A^t, clip⁡(ρt(θ),1−ϵ,1+ϵ)A^t)]L^{CLIP}(\theta) = \mathbb{E}_t \left[ \min \left( \rho_t(\theta) \hat{A}_t, \, \operatorname{clip}(\rho_t(\theta), 1-\epsilon, 1+\epsilon) \hat{A}_t \right) \right]
公式里的 \rho_t 是新旧策略在同一个动作上的概率比,\hat{A}_t 是优势估计(这个动作比平均水平好多少)。PPO 的核心是“稳”:每次教学命令的改动幅度被 \epsilon 限制住,绝不冒进。
  1. 概率比新策略与旧策略在动作上的概率之比。等于 1 说明风格没变,大于 1 说明新策略更喜欢做这个动作。
    ρt(θ)=πθ(at∣st)πθold(at∣st)\rho_t(\theta) = \frac{\pi_\theta(a_t|s_t)}{\pi_{\theta_{old}}(a_t|s_t)}
  2. 优势估计评价“这一步比平均水平好还是差”。正数鼓励,负数抑制,是教练表扬与批评的方向盘。
    A^t\hat{A}_t
  3. 裁剪操作把概率比限制在 [1-ε, 1+ε] 区间内,相当于给教练的命令加限速——每步最多调整 ε 那么多。
    clip⁡(ρt(θ),1−ϵ,1+ϵ)\operatorname{clip}(\rho_t(\theta), 1-\epsilon, 1+\epsilon)
  4. 取最小值用 min 把乐观的估计也压住,宁可少激励,也不让策略冒进。
    min⁡(⋅,⋅)\min(\cdot, \cdot)

超参数调优

同一个教练,对不同学员要用不同语气。语速太快,学员还没看清动作就过去了;语速太慢,练一下午没进步。这个“语速”就是学习率。同样地,考试扣分标准(奖励缩放)定得太严,学员畏手畏脚;定得太松,学员胡作非为。而“学员看多远”(折扣因子 γ),决定了她盯的是眼前一分,还是整条路线。

超参数是 RL 训练中“看不见的算法”——论文的正文写得再漂亮,真正决定实验成败的往往是附录里的超参数表。在 Atari 上,DQN 的经典配置包括:学习率 1e-4(Adam)、奖励裁剪到 [-1, 1] 以统一量纲、帧栈 4 帧、ε-greedy 探索率从 1.0 线性衰减到 0.1。在 MuJoCo 上,PPO 通常使用学习率 3e-4,GAE 的 λ=0.95,γ=0.99,每轮收集 2048 步再做一次更新。

所有超参数最终都服务于一个目标:最大化长期折扣累积回报:

调超参数就像调教练的语速、扣分标准和眼光,没有放之四海而皆准的秘方。最有效的做法是:先跑通论文的默认配置,再基于验证曲线逐步微调——先保证能跑,再追求好。

Gt=∑k=0∞γkrt+kG_t = \sum_{k=0}^{\infty} \gamma^k r_{t+k}
G_t 是从 t 时刻开始把所有未来奖励按 γ 的指数折现后的总和。γ 越小,智能体越短视、训练越稳定;γ 越大,智能体越有远见、但方差也越大。
  1. 折扣回报把未来每一步的即时奖励全部折现到今天,得到的“总收益”。
    Gt=∑k=0∞γkrt+kG_t = \sum_{k=0}^{\infty} \gamma^k r_{t+k}
  2. 折现权重时间距离越远,k 越大,\gamma^k 越小,未来的钱在今天越不值钱。
    γk\gamma^k
  3. 单步奖励未来第 k 步的即时得分。
    rt+kr_{t+k}
  4. 优化目标强化学习的全部任务,就是找到一个策略使 G_t 的期望最大——所有超参数调节都是为了让这个优化过程更顺滑。

训练稳定技巧

新手学员最怕两件事:一是心态崩了猛打方向盘,二是永远只走同一条熟路。教练的应对是给车装上限速器,隔段时间就让学员换条路线,并且每次训练结束后认真看复盘曲线。这三招,对应到 RL 训练里分别是梯度裁剪、探索策略和训练监控。

在 RL 训练中,稳定性是工程的核心痛点。深度网络反向传播时,梯度范数可能指数级放大,导致参数一步跨出十万八千里——就像学员在高速上猛打方向盘,车直接失控。梯度裁剪是最直接的盾牌:

除了梯度裁剪,还有几个实战技巧。网络初始化:正交初始化(Orthogonal Initialization)在 RL 中比标准高斯初始化稳得多,能让信号在深层网络中传播时保持量级稳定。探索策略:Atari 用 ε-greedy(以概率 ε 随机选动作),MuJoCo 在动作采样中加入可学习的噪声,两者都会随时间衰减——就像学员熟悉路况后,不再需要盲目试错。训练监控:每个 epoch 记录平均奖励、策略损失、价值估计和策略熵。熵值骤降往往是策略过早固化、陷入局部最优的警报。

有了这些限速器和保险杠,训练的曲线才敢说“稳定收敛”。记住:RL 训练不追求单步精彩,而追求整条轨迹的长久平稳。

g={g,∥g∥≤δδ⋅g∥g∥,∥g∥>δg = \begin{cases} g, & \|g\| \le \delta \\ \delta \cdot \dfrac{g}{\|g\|}, & \|g\| > \delta \end{cases}
翻译成人话:当梯度的“长度”超过阈值 \delta 时,把梯度按比例压缩回 \delta,但方向完全不变。限速,但不改方向盘指向。
  1. 梯度向量损失函数对每个参数的偏导组成的向量,指向“最能降低损失”的方向。
    g=∇θLg = \nabla_\theta L
  2. 裁剪阈值允许梯度的最大长度,一个需要根据任务调节的常数。
    δ\delta
  3. 归一化缩放超限时把梯度乘上 \delta / \|g\|,让长度刚好等于阈值、方向保持不变。
    δ⋅g∥g∥\delta \cdot \dfrac{g}{\|g\|}
  4. 整体效果保方向、限步长,防止一次参数更新把策略推得太远。

复现论文结果

最后,所有驾校学员都要参加统一的标准化考试:固定考题顺序(同一个随机种子)、统一评分标准(同一套评估指标)、同一款考试用车(相同环境版本和超参数)。否则,你声称学员考了 100 分,别人拿不同考题一测只有 60 分,那就说不清了。

复现论文结果是 RL 研究中最锻炼人的环节。论文里一句 "we tune hyperparameters",背后可能是几百个小时的调参。要复现,关键是把整个实验流程标准化——从随机种子到环境包装,每一步都不能随心所欲。

评估指标的数学表达:

复现时常见的坑位包括:Atari 的帧跳(frame skip 默认 4 帧)、no-op reset(开局先随机跑若干步空操作)、奖励裁剪的开关;MuJoCo 的环境版本差异(v2 与 v4)、是否固定初始状态、评估时是否关闭探索噪声。这些细节写在论文附录里,却是决定曲线成败的暗流。

复现是 RL 的成人礼。当你能用三个随机种子稳定跑出 DQN 在 Atari 上的学习曲线、用 PPO 在 MuJoCo 上拿到与论文一致的均值 ± 标准差,你才算真正掌控了这套训练流程。

Rˉ=1N∑i=1NRi,σ=1N−1∑i=1N(Ri−Rˉ)2\bar{R} = \frac{1}{N} \sum_{i=1}^{N} R_i, \qquad \sigma = \sqrt{\frac{1}{N-1} \sum_{i=1}^{N} (R_i - \bar{R})^2}
在固定随机种子下用同一策略跑 N 条评估轨迹,报告均值 ± 标准差。均值代表水平,标准差代表稳定性——两个数字一起看,才是一份可信的成绩单。
  1. 单条回报第 i 条评估轨迹中累积的总奖励。
    RiR_i
  2. 平均回报所有轨迹的平均分,衡量策略的整体水平。
    Rˉ=1N∑i=1NRi\bar{R} = \frac{1}{N} \sum_{i=1}^{N} R_i
  3. 标准差各次成绩的波动程度,反映策略的稳定性。小 σ 意味着每次考试都差不多。
    σ=1N−1∑i=1N(Ri−Rˉ)2\sigma = \sqrt{\frac{1}{N-1} \sum_{i=1}^{N} (R_i - \bar{R})^2}
  4. 标准报告论文通常报告固定环境下若干万步的评估曲线,或最终时刻的均值 ± 标准差。

AI 应用场景

游戏版本回归测试

阶段:模型评测与回归测试

解决的问题:游戏版本迭代后,关卡难度可能因数值调整而突变,人工 QA 只能“凭感觉”评估,既耗时又主观。用 DQN 训练一个“黄金测试员”AI,在固定随机种子下自动跑完整局,用通关率与平均得分作为客观回归指标,可以在版本发布前自动发现难度失控的关卡。

具体案例:某休闲游戏工作室把自家小游戏包装成 Gym 接口,用 DQN(CnnPolicy)训练 AI 测试员。每个版本更新后自动跑 50 万步,输出通关率变化曲线,曾在一次平衡性调整中提前发现第 7 关难度骤升 30%,避免了上线后的差评潮。

机器人策略仿真训练

阶段:策略训练与部署前验证

解决的问题:真实机器人试错成本高、存在安全隐患,直接在硬件上训练 PPO 策略几乎不可行。MuJoCo 提供高保真物理仿真,让策略先在虚拟世界里“学会走路”,再迁移到真实机体上,大幅缩短迭代周期。

具体案例:某机器人创业公司在 MuJoCo 中训练四足机器狗的 PPO 行走策略,配合域随机化(domain randomization)增强对不同路面与重量的鲁棒性。两周内完成仿真训练与 sim-to-real 迁移,而传统硬件调试方法需要三个月。

论文基线复现

阶段:算法研究中的基准对比

解决的问题:强化学习论文需要与 DQN/PPO 的公开基线对比,但直接引用论文曲线不可行,必须自己在 Atari/MuJoCo 上重新训练基线。这个场景最考验工程细节的把控能力。

具体案例:某高校实验室复现 Rainbow DQN 在 Breakout 上的结果,严格遵循论文的 frame skip=4、reward clip、no-op reset 等设置,用 3 个随机种子各训练 1000 万步,最终报告的均值 ± 标准差与论文曲线几乎重合,为后续新算法对比打下了可靠底座。

Python 演示

python80 行
import torchimport torch.nn as nnfrom collections import dequeimport random # 经验回放池: 存 (状态, 动作, 奖励, 下一状态, 是否终止)class ReplayBuffer:    def __init__(self, capacity):        self.buf = deque(maxlen=capacity)     def push(self, state, action, reward, next_state, done):        self.buf.append((state, action, reward, next_state, done))     def sample(self, batch_size):        batch = random.sample(self.buf, batch_size)        states, actions, rewards, next_states, dones = zip(*batch)        s = torch.stack(states)        a = torch.tensor(actions)        r = torch.tensor(rewards, dtype=torch.float32)        ns = torch.stack(next_states)        d = torch.tensor(dones, dtype=torch.float32)        return s, a, r, ns, d     def __len__(self):        return len(self.buf)  class DQN(nn.Module):    def __init__(self, n_ch, n_action):        super().__init__()        self.cnn = nn.Sequential(            nn.Conv2d(n_ch, 32, 8, stride=4),            nn.ReLU(),            nn.Conv2d(32, 64, 4, stride=2),            nn.ReLU(),            nn.Conv2d(64, 64, 3, stride=1),            nn.ReLU(),            nn.Flatten(),        )        self.fc = nn.Sequential(            nn.Linear(64 * 7 * 7, 512),            nn.ReLU(),            nn.Linear(512, n_action),        )     def forward(self, x):        return self.fc(self.cnn(x))  def train_step(q_net, target_net, replay, optim, gamma, batch_size):    if len(replay) < batch_size:        return None    s, a, r, ns, d = replay.sample(batch_size)    q = q_net(s).gather(1, a.unsqueeze(1)).squeeze(1)    with torch.no_grad():        q_next = target_net(ns).max(1)[0]        target = r + gamma * q_next * (1 - d)    loss = nn.functional.mse_loss(q, target)    optim.zero_grad()    loss.backward()    nn.utils.clip_grad_norm_(q_net.parameters(), 10.0)    optim.step()    return loss.item()  def main():    # 4 帧 84x84 灰白图输入, 6 个离散动作 (Atari 风格)    q_net = DQN(4, 6)    target_net = DQN(4, 6)    target_net.load_state_dict(q_net.state_dict())    replay = ReplayBuffer(10000)    optim = torch.optim.Adam(q_net.parameters(), lr=1e-4)    for step in range(1000):        loss_val = train_step(q_net, target_net, replay, optim, gamma=0.99, batch_size=32)        if step % 100 == 0 and loss_val is not None:            print("step", step, "loss", loss_val)  if __name__ == "__main__":    main()
目的:这是 DQN 在 Atari 风格离散动作环境上训练的核心组件——经验回放池 + 卷积 Q 网络 + 目标网络 + 梯度裁剪,所有关键工程细节浓缩在一个可运行的 Python 脚本中。
  1. self.buf = deque(maxlen=capacity)用双端队列当记忆池,容量满了自动丢弃最旧的经验。
  2. batch = random.sample(self.buf, batch_size)从记忆池里随机抽样,打破相邻样本的时间相关性,让神经网络的复习顺序更科学。
  3. q = q_net(s).gather(1, a.unsqueeze(1)).squeeze(1)取出智能体实际执行的那个动作对应的 Q 值,而不是所有动作的 Q 值。
  4. q_next = target_net(ns).max(1)[0]用目标网络(“副校长”)而非主网络计算未来最优分 Q 值,避免自举式打分引发震荡。
  5. target = r + gamma * q_next * (1 - d)构造 Q 学习的“现实分”:即时奖励 + 折扣未来分;终止态 (d=1) 时未来分归零。
  6. nn.utils.clip_grad_norm_(q_net.parameters(), 10.0)梯度裁剪:限制梯度向量的最大范数为 10,防止梯度爆炸导致的“猛打方向盘”。
  7. target_net.load_state_dict(q_net.state_dict())训练开始时让目标网络与主网络参数完全相同。
  8. optim.step()根据裁剪后的梯度更新一次网络参数,完成一步“评分卡”修正。

常见误区

误区DQN 在 Atari 上这么强,那直接把 DQN 用到 MuJoCo 上不就行了吗?都是游戏 AI,算法应该通用吧。

正解DQN 需要通过 \max_a Q(s,a) 在所有动作中取最大值,这对离散按键(几十个)可行,但 MuJoCo 的动作是连续向量——理论上无穷多个动作,根本无法枚举求最大值。强行把连续动作离散化,又会遭遇维度爆炸。连续控制任务应使用 PPO、SAC 等策略梯度或 Actor-Critic 方法。

为何常见:DQN 在 Atari 上的名气太大,新手误以为强化学习算法是通用的,忽略了“动作空间类型决定算法选择”这个最基本的约束。就像拿了游戏手柄想开真车,按钮再多也转不出 37 度的方向盘角度。

误区环境返回的原始得分本来就是越大越好,直接用就行吧?论文里没提 reward scaling,就不需要处理。

正解Atari 不同游戏得分量纲差异巨大——有的游戏每步只有 ±1 分,有的动辄上百万分。DQN 论文把每步奖励裁剪到 [-1, 1](reward clipping),才能让 Q 值规模可控。MuJoCo 则通常保留原始 reward 或做均值归一化。忽略奖励缩放,Q 值数量级可能失控,训练直接发散。

为何常见:监督学习中标签尺度不需要刻意处理,新手把这种惯性带到了强化学习。但 RL 的奖励是反馈信号而非标签,量纲不一致会让网络对高分游戏过度敏感。

误区经验回放不是学习历史经验吗?那缓冲区设得越大,见过的样本越多,应该学得越好。

正解缓冲区太大,样本过于陈旧,与当前策略的数据分布严重不匹配,Q 值学习会偏向旧策略的行为;太小则样本相关性高,违背了回放打破相关性的初衷。Atari DQN 的经典 buffer 大小是 1e6(约最近 100 万步),需要根据训练规模平衡。

为何常见:“越多越好”的直觉在非平稳分布问题上失灵了——RL 的数据分布随策略演化而不断变化,旧数据太多反而成了噪音,就像让学员反复观看三年前的教学录像去考今天的新交规。

误区我把 Python、NumPy、Gym 的随机种子都固定了,跑出来的结果应该和论文一模一样吧?

正解即使种子全部固定,GPU 浮点运算顺序、线程调度、CUDA 版本、依赖库版本的差异都会导致微小偏差。更重要的是,论文报告的是多个随机种子下的均值 ± 标准差,单种子对上的概率本就不大。此外 frame skip、no-op reset、reward clip 等隐含细节不核对,复现必然失败。

为何常见:初学者把复现想成“确定性需求”,但 RL 训练本身充满随机性,论文结果本质上是统计量而非精确值。这就像以为用同一张考卷就能让所有考生考出同样的分数——考生状态不同,成绩自然有波动。

误区探索就是随机选动作嘛,那所有环境都用 ε-greedy 就行,简单又有效。

正解ε-greedy 在离散动作空间(Atari)有效,但在连续动作空间(MuJoCo)几乎失效——以概率 ε 随机选一个关节角度,得到的几乎总是无意义的动作。连续控制通常用高斯探索:网络输出动作分布的均值和方差,采样时叠加可学习的噪声,训练中方差逐步收缩,实现“从大范围试探到小范围精调”。

为何常见:从 DQN 入门的人把 ε-greedy 当成了“探索”的唯一形态。就像新手上路,如果只会随机猛打方向盘(ε 探索),而不是逐渐收窄对方向盘角度的手感(方差收缩),永远学不会精细驾驶。

面试题

Q1. 下面哪个环境通常使用离散动作空间?

单选题 · easy

  • A.MuJoCo 四足行走
  • B.Atari 街机游戏← 正确答案
  • C.MuJoCo 机械臂
  • D.自动驾驶连续转向

答案:B。Atari 来自街机游戏,按键动作天然是离散的(左/右/开火)。MuJoCo 是物理仿真引擎,动作为连续向量。选 A/C/D 都把连续控制任务误当成了离散空间。

Q2. DQN 中经验回放(Replay Buffer)的核心作用是什么?

单选题 · easy

  • A.减少环境交互次数
  • B.打破样本时间相关性使训练稳定← 正确答案
  • C.增加探索动作的数量
  • D.直接代替目标网络

答案:B。相邻时间步的样本高度相关,按顺序训练会让网络反复强化局部的模式。经验回放随机抽样,相当于学员打乱顺序刷题,避免连续记忆同一类型的题目,从而稳定训练。

Q3. MuJoCo 中 PPO 策略网络的输出通常是什么?

单选题 · easy

  • A.离散动作的 Q 值表
  • B.连续动作分布的均值和标准差← 正确答案
  • C.下一帧观测的像素预测
  • D.环境的转移概率矩阵

答案:B。PPO 在连续控制中用高斯策略,网络输出每个动作维度的均值与标准差,动作从该分布中采样。Q 值表只能表示有限离散动作,无法覆盖连续空间。

Q4. 下列哪个超参数最能体现“策略眼光的长短”?

单选题 · mid

  • A.学习率 α
  • B.折扣因子 γ← 正确答案
  • C.批大小 batch size
  • D.裁剪阈值 ε

答案:B。γ 决定未来奖励的折现程度:γ 接近 1 重视远期收益,γ 接近 0 只顾眼前。学习率管步子大小,批大小管更新频率,ε 管 PPO 更新幅度上限,都与“眼光长短”无关。

Q5. DQN 中引入目标网络(Target Network)的主要原因是?

单选题 · mid

  • A.减少每次更新的计算量
  • B.让 Q 值目标不随主网络同步波动避免发散← 正确答案
  • C.提高动作采样速度
  • D.替代奖励函数

答案:B。DQN 的更新目标里包含 \max_a Q(s',a'),若用主网络自算,等于“自己给自己判卷”,目标不断移动导致震荡。目标网络固定打分标准,学员才能稳定进步,这和考试时考官不能同时是考生的道理一样。

Q6. 关于梯度裁剪,下列说法正确的是?

单选题 · mid

  • A.裁剪的是损失函数的值而不是梯度
  • B.当梯度范数超过阈值时缩放回阈值且方向不变← 正确答案
  • C.梯度裁剪会使所有梯度归零
  • D.梯度裁剪只适用于卷积神经网络

答案:B。梯度裁剪作用于梯度向量:范数超限时按比例缩回阈值 δ,方向完全保留。它是 RL 训练防止“猛打方向盘”的限速器,与网络结构类型无关。

Q7. 复现 DQN 在 Atari 上的论文结果时,下列哪项不是常见的隐藏工程细节?

单选题 · mid

  • A.Frame skip 固定为 4 帧
  • B.奖励裁剪到 [-1, 1]
  • C.开局 no-op 随机空操作
  • D.GPU 训练必须开启 fp16 混合精度← 正确答案

答案:D。论文并不强制 fp16 精度,硬件和浮点误差只带来微小波动。而 frame skip、reward clip、no-op reset 是 Atari DQN 实验三大标准工程细节,漏掉任何一个都会导致曲线对不上。

Q8. 关于 DQN 与 PPO 的适用场景,正确的说法有?

多选题 · hard

  • A.DQN 可以直接处理八维连续关节动作
  • B.PPO 输出动作的概率分布可用于离散或连续动作空间← 正确答案
  • C.DQN 依靠帧栈捕捉运动信息适合像素输入← 正确答案
  • D.PPO 的裁剪机制限制了每次策略更新的幅度← 正确答案

答案:BCD。DQN 需要枚举动作求最大值,无法处理连续动作(A 错)。PPO 输出概率分布,离散用 categorical、连续用高斯(B 对)。帧栈是 Atari 像素观测的标准预处理(C 对)。裁剪目标把新旧策略概率比限制在 1±ε 内(D 对)。

Q9. 设折扣因子 γ=0.9,从 t 时刻起连续四步奖励分别为 1, 2, 3, 0,折扣累积回报 G_t 最接近?

单选题 · hard

  • A.4.83
  • B.5.23← 正确答案
  • C.6.00
  • D.3.70

答案:B。G_t = 1 + 0.9×2 + 0.81×3 + 0.729×0 = 1 + 1.8 + 2.43 = 5.23。未来的奖励要按 γ 的指数逐渐打折,第三步奖励 3 因为隔了两步,只值 2.43。

Q10. 关于 PPO 目标函数中的概率比 ρ_t,以下说法正确的是?

多选题 · extreme

  • A.ρ_t = π_θ(a_t|s_t) / π_θold(a_t|s_t)← 正确答案
  • B.ρ_t 为负值时说明新策略完全放弃该动作
  • C.clip(ρ_t, 1-ε, 1+ε) 限制新旧策略差异防止更新过大← 正确答案
  • D.当 ρ_t > 1+ε 且优势为正时,裁剪使该分量的梯度为零← 正确答案

答案:ACD。ρ_t 是概率的比值,而两个概率都是非负数,所以 ρ_t 恒非负(B 错)。A 是定义;C 描述 clip 的作用;D 正确——超出裁剪区间后梯度为 0,相当于教练对激进调整“不下命令”,强制让策略冷静。