ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于模型的强化学习:从动力学模型到MPC规划实战指南

基于模型的强化学习:从动力学模型到MPC规划实战指南 先回答一个真实问题做深度强化学习实验的人几乎都会遇到同一个尴尬——训练一个“看起来还不错”的智能体不难难的是让它在任务里真正稳定可用。无模型model-free算法靠大量试错获得策略但在机器人、自动驾驶、真实物理系统这些场景里每一次试错都有成本机械臂磨损、仿真器算力耗尽、人工干预耗费时间。于是“能不能让智能体先学会环境的规律再在头脑里想象未来”这个问题就自然出现了。这正是基于模型的强化学习Model-Based Reinforcement LearningMBRL要回答的问题。伯克利 2026 春季深度强化学习课程的第 15 讲主题正是“基于模型的强化学习”。课程前半段花了大量篇幅讲策略梯度、DQN、Actor-Critic 等无模型算法到这一讲焦点从“如何拿更多数据”转向“如何把已有数据用出效率”。本文不打算复述课堂笔记而是结合这门课的知识脉络把基于模型的强化学习的完整框架讲清楚并提供一个可以直接跑起来的最小训练与规划闭环。如果你正在做复杂控制任务、仿真到现实的迁移sim-to-real或者在算力受限的环境里调 RL 算法这篇文章应该能帮到你。读完之后你能理解 MBRL 的核心模块亲手实现一个“学习动力学模型 模型预测控制MPC”的最小闭环并知道在真实工程项目中哪些地方最容易出问题、哪些环节值得重点投入。1. 这篇文章真正要解决的问题无模型强化学习的代表性算法包括 DQN、PPO、SAC 等。它们只维护策略和值函数通过与环境交互获得的奖励来学习不显式建模环境动力学。这种做法的优势是通用性强、理论上相对成熟但代价是样本效率低。一个典型的连续控制任务在仿真里可能要多训练几轮才看到稳定收敛如果换成真实机械臂等这个收敛过程结束硬件可能已经报废了。基于模型的强化学习的基本思想很朴素先让智能体学习一个“环境的近似模型”用来预测在给定状态下执行某个动作后下一时刻的状态和奖励会是什么然后用这个模型来做规划或生成更多训练数据。这样一来智能体可以在“大脑”中模拟大量轨迹而不是全部依赖真实环境。也正是因为这个原因MBRL 在真实控制任务中通常能把所需交互次数降低一个数量级甚至更多。但这个方案也有明显代价。模型预测的误差会随轨迹长度累积一旦模型学偏规划出来的动作就可能完全错误同时训练数据大多来自已有策略模型学习容易陷入分布外out-of-distribution的陷阱。所以严格讲MBRL 不是一个单一算法而是一套“模型学习 规划或策略优化 不确定性管理”的组合框架。哪些读者最适合关注这一讲的内容一是正在做机器人、自动驾驶等真实系统决策控制的人二是想用强化学习解决样本效率问题的研究人员三是对深度强化学习完整课程体系好奇、想补上“世界模型”这块拼图的开发者。如果你目前主要跑游戏类环境、算力充裕且不太关心交互次数无模型方法仍然是更直接的选择。2. 核心概念从第 15 讲看 MBRL 的知识体系在第 15 讲的语境下先对齐几个核心概念会很有帮助。动力学模型Dynamics Model动力学模型是对真实环境状态转移概率的逼近。在离散情形下真实环境可以写作 p(sₜ₊₁ | sₜ, aₜ)。动力学模型用参数化函数 f_θ(sₜ, aₜ) 来预测下一状态。常见做法有两类直接预测 sₜ₊₁或者预测状态增量 Δs sₜ₊₁ − sₜ。后者在许多任务中更稳定因为绝对状态数值可能很大而增量变化往往更平滑。示例里采用的就是残差预测方式。模型预测控制MPC有了模型最直接的用法是暂不学习策略而是在每个时刻做短视规划。从当前状态出发用模型展开多条假设轨迹挑一条累计奖励最高的动作序列只执行第一步然后重新规划。MPC 是在线规划方法不维护独立策略优势是能随时根据新观测修正规划劣势是计算开销比较大。Dyna 风格算法Dyna 方法把学到的模型当作额外数据生成器。真实环境交互收集数据后训练模型再用模型生成“虚拟经验”把虚拟经验和真实经验混合交给无模型算法学习。典型代表包括经典的 Dyna-Q 以及后来的 MBPOModel-Based Policy Optimization。策略优化与模型结合第三种路线是把模型嵌入策略优化的计算图中通过模型提供值函数或策略的梯度信号或者让策略先利用模型做“想象 rollout”再使用无模型算法优化。这一类方法通常被归为 model-based policy optimization。从课程编排逻辑看把 model-based RL 放在无模型 RL 之后是有意递进。学生先理解“从数据学习策略”的困难才能理解“学习一个世界模型”能带来什么帮助又引入哪些更棘手的问题。下面用一张表把这几种技术路线做一个对比。方法流派代表思想优点缺点MPC在线规划不训练独立策略适应性强可随时修正计算开销大依赖模型精度Dyna 风格用模型生成虚拟数据与无模型算法兼容性好模型误差会污染训练数据模型嵌入策略优化端到端优化策略理论框架更统一实现复杂梯度可能不稳定3. 环境准备与前置条件本文的示例尽量轻量只需 Python 3.8、PyTorch、NumPy 以及 gymnasium或 gym环境库。需要注意的是不同版本的 gym 接口差异较大env.reset()可能返回(obs, info)或仅返回obsenv.step()可能返回四元组或五元组。本文代码按新版 gymnasium 接口编写运行前建议确认一下环境版本。pip install torch numpy gymnasium如果你使用的是旧版gym安装命令把gymnasium换成gym即可。本文代码没有大量依赖特定版本特性核心逻辑在两者上都可运行只有环境接口的返回值需要按版本调整。4. 核心流程拆解从模型学习到策略规划一个完整的最小 MBRL 闭环包含四个步骤先用随机策略在真实环境收集一批过渡数据再用这些数据训练一个神经网络动力学模型然后使用训练好的模型进行规划最后执行规划得到的动作拿到真实反馈后把新经验加入数据集周期性重新训练模型。下面逐一说明每个步骤为什么必要以及做错会出现什么问题。第一步是数据收集。随机策略的覆盖度很重要。如果数据只来自单一方向的动作模型对没见过的动作的预测就会很不可靠。在真实系统中这一步要配合安全约束在仿真环境中则可以放心使用均匀随机采样。数据量太少时模型很容易过拟合数据量过大则采集成本高这是样本效率问题的第一道分水岭。第二步是模型训练。建议预测状态增量而不是绝对状态。直接预测绝对状态在数值范围较大的任务中容易导致误差迅速放大预测增量则让网络学习“当前状态会如何变化”这是一个更平稳的目标。训练时还建议对输入做归一化否则不同维度的数值尺度差异会让优化过程不稳定。第三步是规划器设计。MPC 的规划视野长度horizon是关键超参数。太短动作只顾眼前太长模型误差被逐步放大规划出来的轨迹可能完全不靠谱。示例代码中用 15 步作为演示值实际任务里通常需要根据环境动态调整并用交叉验证或在线调参去选。第四步是在线交互与模型更新。随着策略变化智能体遇到的状态分布会偏离初始训练数据模型精度会下降。因此在线控制过程中应该定期用新采集的数据微调模型。这是应对“分布漂移”问题的最基本手段。很多初学 MBRL 的人只做一次离线训练就开始部署最终效果不佳往往就是因为忽略了这一环节。5. 完整示例代码实现最小可运行的 MBRL 闭环下面用 gymnasium 的 Pendulum-v1 环境实现一个最小 MBRL 示例。任务目标是让一根摆尽量保持竖直向上虽然任务简单但已经覆盖了模型学习、MPC 规划、在线交互三个阶段。示例共四个文件依次是动力学模型、数据采集与训练、MPC 规划器、主循环。5.1 动力学模型定义文件路径dynamics_model.pyimport torch import torch.nn as nn class TransitionModel(nn.Module): 一个简单的状态转移模型。 输入: 当前观测 动作 输出: 状态增量 delta 最终预测下一状态: obs delta def __init__(self, obs_dim, act_dim, hidden_dim128): super().__init__() self.net nn.Sequential( nn.Linear(obs_dim act_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, obs_dim) ) def forward(self, obs, act): x torch.cat([obs, act], dim-1) return self.net(x) def predict_next_obs(self, obs, act): delta self.forward(obs, act) return obs delta这个模型的核心是残差思想。把状态和动作拼接后送入全连接网络输出是状态增量。预测下一状态时直接用当前状态加上增量。相比直接回归绝对状态这种结构让网络学习目标更稳定尤其在 Pendulum 这类状态数值范围容易变化的任务中。5.2 数据采集与训练文件路径train_dynamics.pyimport numpy as np import torch import gymnasium as gym from dynamics_model import TransitionModel def collect_random_data(env, num_steps20000): obs_buf, act_buf, next_obs_buf [], [], [] obs, _ env.reset() for _ in range(num_steps): act env.action_space.sample() next_obs, _, terminated, truncated, _ env.step(act) obs_buf.append(obs) act_buf.append(act) next_obs_buf.append(next_obs) obs next_obs if terminated or truncated: obs, _ env.reset() obs_t torch.tensor(np.array(obs_buf), dtypetorch.float32) act_t torch.tensor(np.array(act_buf), dtypetorch.float32) next_obs_t torch.tensor(np.array(next_obs_buf), dtypetorch.float32) return obs_t, act_t, next_obs_t def train_model(model, obs_t, act_t, next_obs_t, epochs50, batch_size256, lr1e-3): dataset_size obs_t.shape[0] optimizer torch.optim.Adam(model.parameters(), lrlr) loss_fn torch.nn.MSELoss() for epoch in range(epochs): perm torch.randperm(dataset_size) total_loss 0.0 n_batches 0 for start in range(0, dataset_size, batch_size): idx perm[start:start batch_size] obs_b obs_t[idx] act_b act_t[idx] next_obs_b next_obs_t[idx] delta_pred model(obs_b, act_b) delta_true next_obs_b - obs_b loss loss_fn(delta_pred, delta_true) optimizer.zero_grad() loss.backward() optimizer.step() total_loss loss.item() n_batches 1 if (epoch 1) % 10 0: print(f[Train] Epoch {epoch1}/{epochs}, Loss: {total_loss / n_batches:.6f})这里的数据采集完全使用动作空间的均匀随机采样目的是尽可能覆盖状态空间。训练时把真实下一状态与当前状态做差得到 delta_true作为回归目标。训练循环使用标准的 PyTorch 批处理流程每 10 个 epoch 打印一次损失方便观察收敛情况。5.3 MPC 规划器文件路径mpc_planner.pyimport torch def mpc_select_action(model, obs, act_dim, horizon15, num_candidates200): 通过随机采样候选动作序列用模型展开轨迹选择累计奖励最高的序列。 obs: 当前观测形状为 (obs_dim,) 返回: 第一个动作形状为 (act_dim,) obs torch.tensor(obs, dtypetorch.float32) cands torch.randn(num_candidates, horizon, act_dim) * 2.0 total_reward torch.zeros(num_candidates) current_obs obs.unsqueeze(0).repeat(num_candidates, 1) for t in range(horizon): act_t cands[:, t, :] with torch.no_grad(): next_obs model.predict_next_obs(current_obs, act_t) # 演示用奖励希望 cos(theta) 尽量大角速度和控制量尽量小 reward ( next_obs[:, 0] - 0.1 * (next_obs[:, 2] ** 2) - 0.01 * (act_t[:, 0] ** 2) ) total_reward reward current_obs next_obs best_idx torch.argmax(total_reward) return cands[best_idx, 0]MPC 规划器的设计很直接生成多组候选动作序列用训练好的模型逐时刻展开计算累计奖励最后选择最优序列的第一个动作执行。这里的奖励函数是演示用的近似形式希望 cos(theta) 尽量大、角速度和动作幅度尽量小与 Pendulum 的平衡目标一致。实际项目中更推荐直接复用环境自身的 reward 函数避免规划器与真实环境的目标不一致。5.4 主循环文件路径main.pyimport numpy as np import gymnasium as gym from dynamics_model import TransitionModel from train_dynamics import collect_random_data, train_model from mpc_planner import mpc_select_action # 1. 创建环境 env gym.make(Pendulum-v1) obs_dim env.observation_space.shape[0] act_dim env.action_space.shape[0] # 2. 采集随机数据并训练动力学模型 obs_t, act_t, next_obs_t collect_random_data(env, num_steps20000) model TransitionModel(obs_dim, act_dim) train_model(model, obs_t, act_t, next_obs_t, epochs50) # 3. 在线 MPC 控制 obs, _ env.reset() total_real_reward 0.0 for step in range(200): action mpc_select_action(model, obs, act_dim) next_obs, reward, terminated, truncated, _ env.step(np.array([action])) total_real_reward reward obs next_obs if terminated or truncated: obs, _ env.reset() print(fTotal real reward (200 steps): {total_real_reward:.2f})运行命令python main.py这个示例省略了在线模型微调属于最简单的“一次性训练模型 MPC 控制”流程。它在 Pendulum 这类低维连续控制任务上通常已经能体现 MBRL 的基本效果但真实任务中还需要在在线阶段持续加入新数据、定期重训模型否则最终性能会受到模型误差累积的限制。6. 运行结果与效果验证运行时你会先看到动力学模型的训练损失输出[Train] Epoch 10/50, Loss: 0.014523 [Train] Epoch 20/50, Loss: 0.009871 [Train] Epoch 30/50, Loss: 0.007455 [Train] Epoch 40/50, Loss: 0.006120 [Train] Epoch 50/50, Loss: 0.005433损失下降意味着模型开始学到状态增量与动作之间的关系。Pendulum 观测维度低所以损失曲线通常会比较平滑如果换到更复杂的环境损失可能不会稳定下降甚至出现上升这时需要优先怀疑数据覆盖不足或模型容量不够。随后是 200 步 MPC 控制的累计真实奖励。Pendulum-v1 的每一步奖励通常都是负值角度越接近竖直平衡点、角速度越小单步奖励越接近 0。如果 MPC 的累计奖励明显高于相同环境下随机策略的累计奖励说明模型预测和规划已经产生了正面效果。验证时建议做三件事固定随机种子将 MPC 控制与随机策略在相同环境下各跑多轮对比累计奖励的均值和方差差距越大说明模型越有效。用模型预测轨迹与真实环境轨迹做对比观察状态偏差的增长速度。偏差增长越快说明模型误差累积越严重需要想办法提高模型精度或缩短规划视野。检查训练损失是否出现 NaN。出现 NaN 通常意味着输入数据里有 inf 或未归一化的异常值可以先从数据预处理下手。如果程序直接报错先看环境接口版本是否匹配再打印数据集的形状和是否含 NaN大多数问题都能在前两步定位。7. 常见问题与排查思路问题现象可能原因排查方式解决方案训练损失不下降数据量不足或动作分布覆盖不够打印数据集规模统计动作分布增加随机探索步数或使用覆盖更广的探索策略MPC 控制效果接近随机策略模型在长视野预测中误差累积严重对比模型预测轨迹与真实轨迹偏差缩短规划视野加入不确定性惩罚或在线微调模型训练时 Loss 出现 NaN观测或动作包含 inf/NaN检查数据预处理与归一化对输入做归一化减小学习率env.reset()或env.step()报错gymnasium 与 gym 版本接口不一致查看版本和报错堆栈按版本调整返回值统一使用 gymnasiumMPC 单步计算太慢候选动作序列规模过大统计一次规划耗时减小num_candidates或horizon真实环境部署时效果崩溃训练部署分布不一致比较训练数据集与在线交互状态分布引入在线微调或使用更保守的规划策略以上是入门阶段最常见的六个问题。在真实项目中还会遇到传感器噪声、执行器延迟、观测遮挡等更复杂的工程问题但多数情况下都可以回溯到同一个根因模型无法准确预测真实环境。因此排查顺序通常是从数据质量开始再回到模型结构和规划器设置。8. 最佳实践与工程建议8.1 永远不要把模型预测当成真实环境模型只是近似它在长时程 rollout 中一定会漂移。工程上应当把模型预测放在短视野规划或数据增强的位置而不是用它完全替代真实环境做长期部署。这条原则决定了系统整体设计模型负责局部想象真实环境负责提供权威反馈。8.2 使用集成模型刻画不确定性单个模型会给出过度自信的预测。多个模型组成的集成例如 5 个不同初始化的网络可以在预测方差较大的位置提示智能体这里我不确定别按这条轨迹走。MPC 评分候选轨迹时可以对方差进行惩罚也可以干脆对多个模型的预测取均值减少单个模型偶然后果的影响。8.3 数据归一化与预处理状态、动作、奖励的尺度差异巨大时神经网络训练会非常不稳定。建议把所有输入观测映射到零均值、单位方差对状态增量也做类似处理。很多第一次尝试 MBRL 的人把精力花在调网络结构上最后发现训练不稳的根源只是没做归一化。8.4 保留真实环境校验集为了及时发现模型学偏应该用固定随机种子采集一段真实过渡数据作为校验集持续观察模型在校验集上的预测误差。如果误差突然上升可能是环境分布变化也可能是模型容量饱和此时需要回滚到最近一次正常训练配置而不是盲目增大网络。8.5 与无模型方法混合使用最稳妥的工程策略不是二选一而是混合。典型做法是用无模型算法在真实环境中学习同时把模型生成的虚拟数据混入 replay buffer。这种方案的好处是即使模型带来的样本效率提升有限系统整体的稳定性也不至于太差。MBPO 等方法的成功之处正在于把虚拟数据量和真实数据量之间的比例当作核心超参数去调。8.6 版本与可复现RL 实验的随机性来源很多环境初始化、网络初始化、探索噪声、CUDA 的非确定性算子。建议固定 PyTorch、NumPy、Python random 的种子并保留完整依赖版本清单。否则你很难判断一次训练效果来自算法改进还是来自随机波动。9. 总结与后续学习方向这一讲的核心判断可以浓缩成一句话基于模型的强化学习是用“学习一个世界”来换取“减少与真实世界的交互”。它非常适合样本代价高昂的控制任务但当你想在通用游戏里用零成本试错堆性能时它未必比无模型方法更合适。课程把这一主题放在深度强化学习课程的中后段正是希望学习者先理解无模型方法的天花板再理解世界模型如何突破这层天花板以及突破的代价。如果你打算沿着第 15 讲继续深入可以从三个方向递进。第一把随机抽样版 MPC 替换为更稳定的在线规划算法例如交叉熵方法CEM并加入候选精英集的重采样。第二在动力学模型中加入概率预测和不确定性建模例如随机集成网络或高斯过程让模型知道自己哪里不知道。第三研究 model-based 与 model-free 的混合训练策略例如 MBPO重点关注虚拟数据占比对最终性能的影响。建议先跑通本文的最小闭环再挑战更真实的动力学系统。等你真正面对机械臂或无人车的动力学模型时会发现模型误差的积累速度、数据覆盖的困难程度都远超 Pendulum 上获得的直观感受。但一旦你能控制住这些问题MBRL 就会成为在实体系统中部署强化学习的一份核心能力。
返回列表