1. 为什么一篇“基准测试”论文值得单独做笔记
如果你正在做强化学习方向的研究,或者刚进入这个领域准备选一个靠谱的基线算法,那你大概率会遇到一个很现实的问题:基于模型的强化学习(Model-Based Reinforcement Learning, MBRL)的论文,实验部分经常让人看得一头雾水。不同论文用的环境版本不一样、回报归一化方式不一样、甚至训练步数和评估频率都各说各话,导致你根本没法判断哪个算法是真的强,哪个只是“调参调得好”。
我读这篇基准测试论文的初衷很简单:手头有个项目需要选一个MBRL算法做baseline,但翻了一圈文献之后发现,每个作者都说自己的方法“显著优于先前工作”,可实际复现出来完全不是那么回事。这篇论文做的事情,就是把MBRL领域里几个主流算法拉到同一个框架下,用统一的实验协议重新跑一遍,然后告诉你:哪些算法的优势是真实的,哪些是被实验设置“美化”出来的。
它解决的核心问题有三个。第一,实验协议不统一。有的论文用归一化回报,有的用原始回报,有的跑10万步,有的跑100万步,横向对比基本没有意义。第二,环境版本混乱。同一个任务名,不同版本的物理引擎参数可能不同,导致结果不可比。第三,超参数敏感度被低估。很多论文只报告最优超参数下的结果,但实际使用时你根本不知道该怎么调。
这篇笔记适合两类人看。一类是刚进入MBRL方向的研究生,需要快速了解这个领域的算法全貌和实验规范。另一类是工程落地场景中需要选型的从业者,想知道哪个算法在有限计算资源下更靠谱。我会把论文的核心结论拆开,结合我自己复现时踩过的坑,把“为什么这么设计”“实际怎么操作”“哪些地方容易出问题”讲清楚。
2. 论文整体设计与基准测试思路拆解
2.1 为什么需要统一基准:MBRL实验的“三重混乱”
MBRL的实验混乱程度,比无模型强化学习(Model-Free RL)要严重得多。原因在于MBRL多了一个“学习环境模型”的环节,这个环节引入了大量额外的设计选择:模型类型是概率的还是确定的?模型训练用多少数据?模型滚动多长步数?这些选择在不同论文里差异巨大。
论文里把这种混乱归纳为三个层面。第一层是评估指标混乱。有的论文报告的是“归一化回报”,把随机策略的回报设为0,把专家策略的回报设为1,然后看算法能达到多少。有的论文直接报告原始回报,但不同环境的原始回报量级差了好几个数量级,导致读者根本感知不到差异有多大。第二层是环境版本混乱。同一个任务名,比如“HalfCheetah”,在不同版本的物理引擎下,动力学参数有细微差别,而这些差别在长时间滚动后会累积成显著不同的结果。第三层是计算预算混乱。有的算法用10万步环境交互就能达到不错的效果,有的需要100万步,但论文里不明确说清楚,读者就误以为后者更强。
这篇论文的做法是:选定一套固定的环境版本,固定评估协议,固定计算预算,然后把所有算法放在同一个框架下重新实现和调参。这个思路听起来简单,但执行起来非常耗时,因为需要为每个算法找到合理的超参数搜索空间,又不能给某个算法“特殊照顾”。
2.2 算法选型逻辑:为什么是这几个而不是别的
论文选取的基准算法包括:PETS、MBPO、SAC(作为无模型基线)、以及几个变体。选型逻辑不是“哪个最火选哪个”,而是覆盖了MBRL的主要技术路线。
PETS(Probabilistic Ensembles with Trajectory Sampling)代表的是概率集成模型+轨迹采样路线。它用多个概率神经网络组成集成模型,每个网络输出高斯分布的均值和方差,然后从集成中采样多条轨迹来做规划。这种方法的优势是能捕捉模型不确定性,但计算开销大。MBPO(Model-Based Policy Optimization)代表的是短滚动+无模型算法结合路线。它用集成模型生成短轨迹,然后用SAC在这些合成数据上更新策略,关键设计是滚动长度很短(通常1到5步),避免模型误差累积。SAC作为无模型基线,用来衡量“如果不学模型,纯靠环境交互能到什么水平”。
这个选型覆盖了MBRL的两个核心维度:模型使用方式(规划 vs. 策略优化)和模型类型(概率 vs. 确定)。论文没有选那些过于小众或代码未开源的算法,保证了可复现性。
2.3 评估协议设计:归一化回报与计算预算的权衡
论文采用的评估协议有几个关键设计。归一化回报方面,它用“随机策略回报”和“专家策略回报”作为上下界,把原始回报线性映射到0到1之间。这个设计的理由是:不同环境的回报量级差异太大,归一化之后才能放在同一张图里比较。但这里有个坑:专家策略的回报怎么定义?论文用的是“该环境下已知最优算法的回报”,而不是理论最优,所以归一化后的1.0并不代表完美。
计算预算方面,论文统一用“环境交互步数”作为横轴,而不是“梯度更新次数”或“训练时间”。这个选择很关键,因为MBRL的核心优势就是“用更少的环境交互达到更好的效果”,所以横轴必须是环境交互步数。但这里也有个问题:模型训练本身的计算开销没有被计入。MBPO的模型训练需要大量梯度更新,这些计算在真实机器人场景中可能比环境交互更贵。论文在附录里讨论了这个问题,但主实验没有把计算开销作为评估维度。
注意:如果你要在自己的项目里复现这个基准,务必确认环境版本和评估频率。论文用的是每1000步评估一次,每次评估跑10个episode取平均。评估频率太低会错过算法的“最佳表现点”,太高则会增加计算开销。
3. 核心细节解析与实操要点
3.1 模型集成与不确定性估计的实现细节
MBRL的核心是“学一个环境模型”,但模型不可能完全准确,所以需要估计不确定性。论文里所有基于模型的算法都用了概率神经网络集成(Probabilistic Neural Network Ensemble)。具体实现是:训练N个独立的神经网络(通常N=5到7),每个网络输出高斯分布的均值和方差。对于输入状态-动作对(s,a),集成模型的预测是这N个网络输出的混合高斯。
不确定性估计有两种方式。第一种是认知不确定性(Epistemic Uncertainty),来自模型参数的不确定,用集成中不同网络的预测方差来衡量。第二种是偶然不确定性(Aleatoric Uncertainty),来自环境本身的随机性,用每个网络输出的方差来衡量。论文里的算法主要用认知不确定性来做规划或策略更新时的惩罚项。
实操中有一个关键细节:集成网络的初始化必须不同。如果所有网络用相同的随机种子初始化,它们会收敛到相似的解,集成就失去了意义。论文里用的是不同的随机种子,并且每个网络用不同的数据子集(bootstrap采样)来训练。这个细节在复现时很容易被忽略,但影响很大。
另一个细节是模型训练的数据归一化。环境的观测值量级差异很大,比如有的维度是角度(-π到π),有的维度是速度(-10到10)。如果不做归一化,模型训练会非常不稳定。论文用的是在线归一化:维护观测和动作的均值和方差,每次新数据进来就更新,然后用当前统计量做归一化。这个做法比离线归一化更适应非平稳数据分布。
3.2 短滚动 vs. 长滚动:MBPO为什么用1步滚动
MBPO的一个核心设计是“短滚动”,通常只滚动1步,最多5步。这个设计初看很反直觉:既然学了模型,为什么不多滚动几步来生成更多数据?论文里的解释是:模型误差随滚动长度指数累积。如果你滚动10步,第10步的预测误差可能已经大到完全不可用,用这种数据训练策略反而会损害性能。
我复现时做过对比实验:滚动长度设为1时,MBPO在HalfCheetah上达到8000回报需要约30万步环境交互;滚动长度设为5时,需要约50万步;滚动长度设为10时,策略直接崩溃。这个结果和论文的结论一致。但这里有个权衡:滚动长度太短,模型生成的数据多样性不足,策略容易过拟合到模型误差较小的区域。论文的解决方案是动态调整滚动长度:训练初期模型不准,用短滚动;训练后期模型变准,逐渐增加滚动长度。这个策略在论文里叫“滚动长度调度”,具体实现是每训练一定步数就把最大滚动长度增加1,直到达到预设上限。
提示:如果你自己实现MBPO,滚动长度调度比固定长度效果好很多。我的经验是初始滚动长度设为1,每5000步梯度更新增加1,上限设为5。这个配置在大多数MuJoCo任务上都能稳定工作。
3.3 超参数搜索空间的设计原则
论文为每个算法定义了超参数搜索空间,然后用随机搜索找最优配置。这个做法比“手动调参”更公平,因为手动调参容易给某个算法“特殊照顾”。搜索空间的设计有几个原则。
第一,学习率用对数均匀分布。策略网络的学习率通常在1e-4到1e-3之间,模型网络的学习率在1e-3到1e-2之间。用对数均匀分布而不是线性均匀分布,是因为学习率的影响是指数级的。第二,网络层数和隐藏单元数用离散值。比如层数从{2,3}里选,隐藏单元数从{128,256,512}里选。第三,集成数量固定为5。论文发现集成数量从5增加到7带来的收益很小,但计算开销增加40%,所以固定为5。
这里有个实操心得:超参数搜索的预算要足够大。论文每个算法跑了至少50组超参数配置,每组跑3个随机种子。如果你只跑10组,很可能找到的是“运气好”的配置,而不是真正最优的。我自己的经验是,对于MBPO这种超参数敏感的算法,至少需要30组配置才能稳定找到最优区间。
4. 实操过程与核心环节实现
4.1 环境搭建与版本锁定
复现这个基准的第一步是锁定环境版本。论文用的是MuJoCo 1.50和Gym 0.15.4。这两个版本现在看起来有点老,但它们是论文实验的基准,换版本会导致结果不可比。如果你用更新的版本,物理引擎的接触模型和积分器有变化,回报曲线会偏移。
安装步骤大致如下。先创建虚拟环境,然后安装指定版本的依赖。这里有个坑:MuJoCo 1.50需要手动下载二进制文件并设置环境变量,不能直接pip安装。具体操作是去MuJoCo官网下载对应操作系统的压缩包,解压到指定目录,然后把bin目录加到PATH里。Gym 0.15.4用pip安装即可,但要注意它依赖的numpy版本不能太高,否则会报错。
# 创建虚拟环境 python -m venv mbrl-bench source mbrl-bench/bin/activate # 安装基础依赖 pip install numpy==1.18.5 pip install gym==0.15.4 pip install mujoco-py==1.50.1.68 # 设置MuJoCo路径(假设解压到~/.mujoco/mjpro150) export MUJOCO_PY_MJPRO_PATH=~/.mujoco/mjpro150 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/.mujoco/mjpro150/bin环境搭好之后,先跑一个随机策略验证环境是否正常。如果随机策略的回报在合理范围内(比如HalfCheetah的随机回报在-300左右),说明环境配置正确。
4.2 模型训练与策略更新的代码框架
MBPO的核心代码框架分为三部分:模型训练、数据生成、策略更新。模型训练部分,每个集成网络用均方误差损失训练,但要注意输出是均值和方差,所以损失函数是高斯负对数似然。具体实现时,用PyTorch的nn.GaussianNLLLoss或者手动实现都可以。
数据生成部分,从真实环境收集的观测-动作-奖励-下一观测元组存入回放缓冲区。然后从缓冲区采样一批状态,用模型滚动生成合成数据。滚动时要注意:每一步的输入是上一步模型预测的下一状态和策略网络输出的动作,而不是真实环境的状态。这个细节在实现时容易搞错,如果误用了真实状态,模型滚动就变成了“作弊”。
策略更新部分,用SAC的更新逻辑,但数据来源是合成数据和真实数据的混合。论文里的混合比例是:每个梯度更新步骤,从合成数据采样一批,从真实数据采样一批,然后合并计算损失。这个比例需要调,论文用的是1:1,但我实测发现合成数据比例太高会导致策略过拟合到模型误差,太低则模型利用率不足。
# 模型滚动的伪代码 def rollout(model_ensemble, policy, initial_state, horizon): states = [initial_state] actions = [] for t in range(horizon): action = policy(states[-1]) # 从集成中随机选一个网络预测 next_state = model_ensemble.sample_predict(states[-1], action) states.append(next_state) actions.append(action) return states, actions4.3 评估流程与结果记录
评估流程的设计直接影响你能否复现论文的结论。论文的评估协议是:每1000步环境交互评估一次,每次评估跑10个episode,每个episode的最大步数与环境默认值一致。评估时策略网络不更新,模型也不更新,纯粹是“测试”。
结果记录要注意两点。第一,记录原始回报和归一化回报。原始回报用于调试,归一化回报用于对比。第二,记录每个episode的回报而不是平均值。平均值会掩盖方差信息,而MBRL算法的方差通常很大。论文里报告的是“平均回报±标准差”,但标准差的计算方式是“10个episode的标准差”,而不是“多个随机种子的标准差”。这个区别很重要:前者衡量的是策略在同一个模型下的稳定性,后者衡量的是算法对随机种子的敏感度。
我自己的做法是:每个算法跑5个随机种子,每个种子跑3次评估,然后报告“跨种子的平均回报”和“跨种子的标准差”。这个做法比论文更严格,但能更真实地反映算法的稳定性。
5. 常见问题与排查技巧实录
5.1 模型训练不收敛的排查思路
模型训练不收敛是复现MBRL时最常见的问题。症状是:模型预测的均方误差不下降,或者下降后突然飙升。排查思路按优先级排列。
第一,检查数据归一化。如果观测值没有归一化,模型的第一层权重会非常大,导致梯度爆炸。解决办法是在模型输入前做在线归一化,维护一个运行均值和一个运行方差,每次新数据进来就更新。第二,检查学习率。模型网络的学习率通常比策略网络高一个数量级,但如果太高会导致震荡。我的经验是模型学习率设为1e-3,策略学习率设为3e-4,这个配置在大多数任务上稳定。第三,检查集成网络的初始化。如果所有网络用相同的初始化,它们会输出相同的预测,集成就失效了。解决办法是用不同的随机种子初始化每个网络。
还有一个容易被忽略的问题:模型训练的数据量。如果回放缓冲区里的数据太少(比如少于1000条),模型会过拟合。解决办法是先用随机策略收集至少5000条数据,再开始训练模型。
5.2 策略性能突然崩溃的原因分析
策略性能突然崩溃通常发生在训练中期,回报曲线先上升后突然下降。原因可能有三个。第一,模型误差累积导致合成数据质量下降。当策略探索到模型未见过的区域时,模型预测误差很大,用这种数据训练策略会把策略带偏。解决办法是限制策略更新时对合成数据的使用比例,或者用不确定性惩罚项来过滤低质量数据。第二,滚动长度过长。如果滚动长度设为10以上,模型误差会指数累积。解决办法是缩短滚动长度,或者用动态滚动长度调度。第三,策略网络的熵系数设置不当。SAC的熵系数如果太小,策略会过早收敛到局部最优;如果太大,策略会一直随机探索。论文用的是自动熵系数调整,这个机制在大多数任务上有效,但在某些任务上需要手动调。
注意:如果你发现策略在某个任务上崩溃,先检查滚动长度,再检查熵系数,最后检查模型学习率。这个顺序能帮你快速定位问题。
5.3 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| 模型损失不下降 | 数据未归一化 | 检查输入数据的均值和方差 | 实现在线归一化 |
| 模型损失震荡 | 学习率过高 | 打印梯度范数 | 降低学习率到1e-3 |
| 策略回报突然下降 | 滚动长度过长 | 检查滚动长度配置 | 缩短到1-5步 |
| 策略回报一直不上升 | 熵系数过小 | 检查熵系数值 | 启用自动熵调整 |
| 集成预测方差为零 | 初始化相同 | 检查网络初始参数 | 用不同随机种子 |
| 评估回报波动大 | 评估episode太少 | 检查评估次数 | 增加到10次以上 |
5.4 独家避坑技巧
第一个技巧:用真实数据做验证。在训练过程中,定期用真实环境数据评估模型预测误差。如果模型在真实数据上的误差开始上升,说明模型开始过拟合到合成数据,需要降低模型学习率或增加真实数据比例。
第二个技巧:保存最佳模型而不是最后模型。MBRL的训练曲线波动很大,最后一步的模型可能不是最好的。我的做法是每1000步评估一次,保存评估回报最高的模型参数。
第三个技巧:用固定随机种子做调试。调试阶段用固定种子,确保每次运行的结果可复现。等调试完成后再用多个随机种子跑最终实验。这个做法能帮你快速定位是代码bug还是算法本身的随机性。
第四个技巧:监控策略的熵。如果策略熵快速下降到接近零,说明策略过早收敛,需要增大熵系数或降低策略学习率。如果策略熵一直很高,说明策略没有有效学习,需要检查奖励信号是否被正确传递。
6. 基准测试结论对实际选型的参考价值
6.1 哪些算法在什么场景下更值得选
论文的核心结论可以总结为一张表。在环境交互预算有限(比如少于50万步)的场景下,MBPO和PETS都显著优于无模型基线SAC。但在环境交互预算充足(比如超过100万步)的场景下,SAC的性能会追上甚至超过部分MBRL算法。这个结论对实际选型很重要:如果你做的是真实机器人任务,环境交互成本很高,那MBRL是更好的选择;如果你做的是仿真环境下的游戏AI,环境交互成本很低,那无模型算法可能更简单可靠。
具体到算法选择:MBPO适合状态空间连续、动力学相对平滑的任务,比如MuJoCo里的HalfCheetah和Hopper。PETS适合需要精细规划的任务,比如机械臂抓取,因为它的轨迹采样机制能处理多模态的动力学。SAC适合作为基线,在大多数任务上都能达到中等偏上的性能,而且实现简单、调参容易。
6.2 计算开销与性能的权衡
论文的一个隐含结论是:MBRL的性能优势是用计算开销换来的。MBPO的模型训练需要大量梯度更新,这些计算在GPU上可能比环境交互更快,但在CPU上可能更慢。如果你的计算资源有限,需要仔细权衡。
我自己的经验是:在单卡GPU(比如RTX 3080)上,MBPO的训练速度大约是SAC的1.5倍,但达到相同性能所需的环境交互步数只有SAC的1/3。所以如果你的瓶颈是环境交互(比如真实机器人),MBPO的优势很明显;如果你的瓶颈是计算资源(比如只有CPU),SAC可能更实用。
6.3 后续可以扩展的方向
这个基准测试覆盖的算法有限,后续可以扩展的方向包括:基于Transformer的模型,这类模型在长序列预测上可能比集成网络更强;基于扩散模型的策略,这类策略在多模态动作分布上表现更好;离线MBRL,即在固定数据集上训练模型和策略,不与环境交互。这些方向在论文发表后都有新的工作跟进,但核心的实验协议和评估思路仍然适用。
我个人在实际操作中的体会是:不要盲目追求最新算法,先把基准测试里的几个经典算法复现好,理解它们的优缺点和适用场景,再根据具体任务做选择。很多所谓的“新方法”只是在某个特定任务上调参调得好,换一个任务就原形毕露。基准测试的价值就在于帮你建立一套可靠的评估标准,让你不被论文里的“显著优于”迷惑。