在真实环境里训练强化学习最贵的从来不是 GPU而是试错本身。自动驾驶策略一次错误决策可能就是一次事故机器人一次错误抓取可能就是一台舵机的维修单LLM 智能体一次错误工具调用可能就写坏了生产库。这三件事的共同点是采样成本极高且不可逆。于是过去两年工业界和学术界都在往同一个方向挪先把环境学出来让策略在模型内部练练到差不多了再回到真实环境做校准和验收。这条路就是世界模型World Model接入强化学习。它不是一个新算法名字而是一层新的抽象——把环境的采样成本从物理世界搬到神经网络里。这里要先给一个明确判断世界模型不会取代真实环境它改变的是真实环境的使用比例。以前真实环境要承担训练全程的采样现在它只需要承担数据采集、模型校准、最终验收这三段。这个比例变化才是世界模型真正的价值所在而不是能不能不用真机这种二元问题。本文会把这件事拆开讲世界模型的原理边界在哪、三条主流路线各自适合谁、怎么用两百行左右的 PyTorch 代码跑通一个最小可用的潜空间世界模型、自动驾驶和机器人以及 LLM 智能体这三类场景分别在哪一层接入、以及落地时最容易踩的坑。如果你正在做具身智能、自动驾驶决策、或者 Agent 的规划模块这篇文章的内容可以直接对照你的项目结构看。1. 为什么强化学习一定要碰真实环境先说清楚问题的来源否则后面所有关于世界模型的讨论都会变成空中楼阁。强化学习的样本效率问题是结构性的它不像监督学习那样有一条固定的数据分布策略更新会改变数据分布数据分布改变又会反过来影响策略更新。这意味着你不能像训练图像分类那样先离线收一批数据然后闭着眼睛训。无模型model-free方法把这个矛盾推到了极致。PPO、SAC 这类算法在 Atari 或者 MuJoCo 上能跑出漂亮曲线但代价是百万级甚至千万级的交互步数。在仿真里这只是电费在真机上这就是时间、磨损和风险。具体到三类典型场景代价的形态各不相同自动驾驶真实路测的成本不只是油钱和人力更关键的是长尾场景根本采不到。一个前车突然掉落货物的场景可能几十万公里才遇到一次。靠真实里程去覆盖长尾在工程上是不成立的。机器人机械臂、四足、人形的硬件损耗是硬成本。更麻烦的是安全问题你不能让一个还在探索阶段的策略去控制一台几十公斤的机器在有人环境里乱动。LLM 智能体这一类最容易被忽视。Agent 调用工具是有副作用的发邮件、改数据库、提交代码这些操作不像游戏里的按键可以随便按。所以 Agent 的规划模块天然缺乏低成本试错的土壤。传统的应对办法是仿真。CARLA、Isaac Sim、MuJoCo 这些仿真器确实缓解了一部分压力但它们也带来了新问题仿真与现实的差距sim-to-real gap。你手工调物理参数、加域随机化本质上是在用人力去弥补仿真器的表达能力不足。世界模型换了一个思路不去手工建模仿真器而是从数据里学一个环境的动力学。学出来的模型可能不满足物理定律但它只需要在你的任务分布上够准。这个取舍很关键——它把一个通用物理仿真的难题降解成了一个任务相关的预测问题。所以什么样的读者最该读这篇正在被样本效率卡住的强化学习工程师、想让 Agent 在沙箱里先演练一遍的 LLM 应用开发者、以及需要评估要不要引入世界模型的技术负责人。如果你只是想让模型在 CartPole 上跑通那这篇文章对你来说偏重了。2. 世界模型是什么把环境换成可学习的预测器2.1 从马尔可夫决策过程说起标准强化学习把问题建模成马尔可夫决策过程状态 s、动作 a、转移概率 P(s|s,a)、奖励函数 R(s,a)。无模型方法直接在这个五元组上做策略优化不显式建模 P 和 R。世界模型做的事情很直白用神经网络去拟合 P 和 R。给定当前状态和动作预测下一个状态和即时奖励。有了这个预测器策略就可以在预测出来的状态序列上做优化这条序列在文献里通常叫想象轨迹imagined rollout。听起来简单但真正的难点在状态表示。如果你直接在像素上预测下一帧误差会迅速累积——预测 5 步之后画面就糊成一团预测 20 步基本全是噪声。所以主流做法是把观测压缩到一个低维潜空间latent space在潜空间里做动力学预测需要的时候再解码回观测。这个思路最早由 Ha 和 Schmidhuber 在 2018 年的 World Models 论文里系统化用 VAE 把每一帧压成潜向量用一个循环网络MDN-RNN预测下一个潜向量最后用 CMA-ES 在这个梦境里进化出一个线性策略。整个策略训练过程完全没碰真实环境这是它最有冲击力的地方。2.2 世界模型的四个组成部分一个完整的世界模型通常包含四块缺一块都会影响最终效果组件作用缺失后的后果观测编码器把高维观测压成低维潜表示直接在像素上预测误差爆炸动力学模型给定潜状态和动作预测下一潜状态无法做多步推演只能做单步预测奖励/终止预测头预测即时奖励和 episode 是否结束想象轨迹无法评估好坏策略学不到目标观测解码器把潜状态还原成观测无法做可视化调试也难以做表征学习约束这里容易被误解的一点是解码器在很多现代实现里是可选的。MuZero 系列就完全不重建观测只在潜空间里预测奖励、价值和策略。TD-MPC2 也走的是 decoder-free 路线。原因很实际——重建像素会消耗大量模型容量而这些容量对决策本身未必有用。所以要不要解码器取决于你的目标如果是为了调试和可视化值得加如果纯粹为了策略优化可以省掉。2.3 三条主流技术路线与它们的取舍到今天为止世界模型在强化学习里的落地大致有三条路线它们的差异不在是否预测未来而在预测什么和怎么用。第一条是重建路线代表工作是 World Models 和 Dreamer 系列。Dreamer 从 V1 到 V3 一直在打磨这套架构核心是 RSSMRecurrent State Space Model隐状态分成确定性的循环部分和随机性的潜变量部分前者负责记忆后者负责表达不确定性。DreamerV3 的几个工程细节值得单独拎出来说——symlog 变换用符号函数压缩数值范围解决了不同任务奖励尺度差异巨大的问题two-hot 编码把回归问题转成分类问题提升了稳定性KL 平衡项则防止后验过快坍缩。这些设计让同一套超参能跨任务工作这是它出圈的主要原因。第二条是价值等价路线代表是 MuZero。它不重建观测只保证预测出的奖励、价值和策略与真实环境一致。这个思路的好处是模型容量全部用在决策相关的信息上坏处是失去了可解释性——你没法看模型想象出来的未来长什么样。第三条是生成式路线代表是近两年的视频生成模型在自动驾驶和机器人仿真上的应用。这类模型参数量巨大能在像素层面生成相当逼真的未来帧适合做感知层的仿真和闭环测试。但它作为强化学习的训练环境目前还不够成熟主要问题是生成速度慢、动作可控性弱、物理一致性无法保证。路线代表工作优点主要限制适合谁重建路线World Models、Dreamer 系列可解释、能可视化、通用性强模型容量被重建任务占用机器人、通用控制价值等价路线MuZero 系列容量集中在决策、样本效率高不可解释、需要大量搜索棋类、规划密集型任务生成式路线视频生成类世界模型视觉逼真、适合感知仿真推理慢、动作可控性弱自动驾驶闭环测试我的判断是如果你现在要在一个真实的工程项目里引入世界模型第一条路线的风险最低因为它有成熟的开源实现和大量公开的任务验证第二条路线上手门槛高适合有明确规划需求且愿意投入搜索算力的团队第三条路线目前更适合做评测和仿真不适合作为策略训练的主环境。3. 环境准备与最小可跑工程为了让后面的内容可执行这里给一套最小依赖。需要说明的是具体版本请以你项目里实际锁定的为准本文重点演示通用思路不绑定某个精确的小版本号。Python 3.10 或更高3.11 也可以。PyTorch 2.xCPU 版本足够跑通本文示例。Gymnasium注意 0.26 之后的 API 有变化reset()返回(obs, info)step()返回五元组。NumPy。如果要跑 MuJoCo 类任务再额外装仿真器本文用的 Pendulum 属于经典控制环境不需要额外仿真器。# 建议在虚拟环境里执行 python -m venv wm-env source wm-env/bin/activate # Windows 用 wm-env\Scripts\activate pip install --upgrade pip pip install torch numpy gymnasium # 如果后续要跑 MuJoCo 系列任务再补这一行 # pip install gymnasium[mujoco]工程目录我建议这样组织后面加真实场景时也方便扩展wm-demo/ ├── collect.py # 数据采集 ├── model.py # 世界模型结构 ├── train_wm.py # 世界模型训练 ├── plan.py # 在想象中做规划 └── evaluate.py # 真实环境验收这个结构对应了世界模型落地的完整闭环采集、建模、训练、想象、验收。真实项目里每一步都会复杂很多但骨架不变。4. 完整代码实现数据采集、模型训练、想象规划4.1 第一步用随机策略采集交互数据世界模型是监督学习它需要(obs, act, reward, next_obs, done)这样的五元组。第一步就是把数据收上来。这里用随机策略采集是因为我们只关心覆盖状态空间不关心策略好坏。# 文件路径collect.py import numpy as np import gymnasium as gym def collect(env_idPendulum-v1, episodes200, seed0): 用随机策略采集交互数据返回字典形式的 numpy 数组。 env gym.make(env_id) rng np.random.default_rng(seed) obs_buf, act_buf, rew_buf, next_buf, done_buf [], [], [], [], [] for ep in range(episodes): obs, info env.reset(seedseed ep) done False while not done: # Pendulum 的动作空间是 [-2, 2] 的连续区间 act rng.uniform(-2.0, 2.0, sizeenv.action_space.shape).astype(np.float32) next_obs, rew, terminated, truncated, info env.step(act) obs_buf.append(obs) act_buf.append(act) rew_buf.append(rew) next_buf.append(next_obs) done_buf.append(float(terminated)) obs next_obs done terminated or truncated env.close() return { obs: np.asarray(obs_buf, dtypenp.float32), act: np.asarray(act_buf, dtypenp.float32), rew: np.asarray(rew_buf, dtypenp.float32), next_obs: np.asarray(next_buf, dtypenp.float32), done: np.asarray(done_buf, dtypenp.float32), } if __name__ __main__: data collect(episodes5) for k, v in data.items(): print(k, v.shape, v.dtype)这段代码跑完你会看到五个数组的形状。Pendulum 的观测是 3 维cos、sin、角速度动作是 1 维。注意这里用的是truncated or terminated作为循环终止条件但存进done的只有terminated。这个区分很重要截断是时间上限导致的不是环境真正结束如果把它当成终止信号世界模型会学到到时间点就结束这个错误规律。4.2 第二步定义潜空间世界模型下面这个结构是 RSSM 的简化版。它保留了最关键的设计确定性隐状态负责记忆动作编码器和观测编码器分开这样在想象阶段可以只靠动作推进不需要真实观测。# 文件路径model.py import torch import torch.nn as nn class WorldModel(nn.Module): def __init__(self, obs_dim, act_dim, hidden128, latent64): super().__init__() self.obs_dim obs_dim self.act_dim act_dim self.latent latent # 动作编码真实步和想象步共用 self.act_enc nn.Sequential( nn.Linear(act_dim, hidden), nn.SiLU(), nn.Linear(hidden, hidden), nn.SiLU(), ) # 观测编码只在真实步使用 self.obs_enc nn.Sequential( nn.Linear(obs_dim, hidden), nn.SiLU(), nn.Linear(hidden, hidden), nn.SiLU(), ) # 循环单元维护确定性隐状态 self.gru nn.GRUCell(hidden, latent) # 解码与预测头 self.dec nn.Sequential( nn.Linear(latent, hidden), nn.SiLU(), nn.Linear(hidden, obs_dim), ) self.rew nn.Sequential( nn.Linear(latent, hidden), nn.SiLU(), nn.Linear(hidden, 1), ) self.term nn.Linear(latent, 1) def init_hidden(self, batch_size, device): return torch.zeros(batch_size, self.latent, devicedevice) def posterior_step(self, obs, act, h): 训练阶段观测和动作都可见走这一步。 x self.act_enc(act) self.obs_enc(obs) return self.gru(x, h) def prior_step(self, act, h): 想象阶段只有动作可见走这一步。 return self.gru(self.act_enc(act), h)为什么要区分 posterior 和 prior因为在训练时我们有真实的下一帧观测可以用它来校正隐状态但在想象时没有观测只能靠动作往前推。这两条路径必须在同一个 GRU 上共享参数否则想象出来的状态会偏离训练分布。这个设计是 RSSM 的核心也是很多简化实现容易忽略的地方。4.3 第三步用序列损失训练世界模型世界模型不能只做单步预测必须做多步展开否则累积误差无法暴露。下面用固定长度的序列窗口做 BPTT。# 文件路径train_wm.py import numpy as np import torch import torch.nn.functional as F from collect import collect from model import WorldModel def window_batches(data, seq_len16, batch_size64, num_batches300, devicecpu): n data[obs].shape[0] for _ in range(num_batches): starts np.random.randint(0, n - seq_len - 1, sizebatch_size) idx starts[:, None] np.arange(seq_len)[None, :] yield { k: torch.as_tensor(v[idx], dtypetorch.float32, devicedevice) for k, v in data.items() } def sequence_loss(model, batch): obs batch[obs] act batch[act] rew batch[rew] next_obs batch[next_obs] done batch[done] b, t, _ act.shape h model.init_hidden(b, obs.device) total 0.0 for i in range(t): h model.posterior_step(obs[:, i], act[:, i], h) pred_next model.dec(h) pred_rew model.rew(h).squeeze(-1) pred_done model.term(h).squeeze(-1) total total F.mse_loss(pred_next, next_obs[:, i]) total total F.mse_loss(pred_rew, rew[:, i]) total total F.binary_cross_entropy_with_logits(pred_done, done[:, i]) return total / t def main(): torch.manual_seed(0) device cuda if torch.cuda.is_available() else cpu data collect(episodes200) obs_dim data[obs].shape[-1] act_dim data[act].shape[-1] model WorldModel(obs_dim, act_dim).to(device) opt torch.optim.Adam(model.parameters(), lr3e-4) for step, batch in enumerate(window_batches(data, devicedevice)): loss sequence_loss(model, batch) opt.zero_grad() loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), 100.0) opt.step() if step % 20 0: print(fstep {step:04d} loss {loss.item():.4f}) torch.save( {state_dict: model.state_dict(), obs_dim: obs_dim, act_dim: act_dim}, wm.pt, ) print(saved - wm.pt) if __name__ __main__: main()三个损失项要一起看曲线。如果观测重建损失下降但奖励损失不降说明模型把容量全用在了重建上对决策没帮助。这时候可以考虑降低解码器的宽度或者引入类似 DreamerV3 的奖励尺度归一化。梯度裁剪这里给了 100.0 这个比较宽松的值是因为循环网络在长序列上容易爆梯度你可以根据实际曲线调小。4.4 第四步在想象中做规划模型训好之后策略训练就可以完全脱离真实环境了。下面用随机打靶random shooting做规划这是最简单的一种够用且好理解。# 文件路径plan.py import torch torch.no_grad() def plan_action(model, obs, horizon20, num_samples512, top_k32, gamma0.99, act_low-2.0, act_high2.0, devicecpu): model.eval() obs_t torch.as_tensor(obs, dtypetorch.float32, devicedevice).unsqueeze(0) zero_act torch.zeros(1, model.act_dim, devicedevice) # 先用真实观测把隐状态对齐到当前时刻 h model.init_hidden(1, device) h model.posterior_step(obs_t, zero_act, h) # 采样一批动作序列 act_seq torch.empty(num_samples, horizon, model.act_dim, devicedevice) act_seq.uniform_(act_low, act_high) # 在想象中并行展开 h_batch h.expand(num_samples, -1).contiguous() ret torch.zeros(num_samples, devicedevice) for t in range(horizon): h_batch model.prior_step(act_seq[:, t], h_batch) r model.rew(h_batch).squeeze(-1) ret ret (gamma ** t) * r # 取回报最高的一批返回其中第一条序列的首个动作 best torch.topk(ret, top_k).indices return act_seq[best[0], 0].cpu().numpy()这里有个细节值得说说规划时用top_k而不只用最优的一条是为了后续扩展成 CEM交叉熵方法。CEM 会用 top-k 样本的均值和方差重新采样迭代几轮就能得到更平滑的动作分布。在真实的机器人控制里动作平滑性往往比单步回报更重要因为抖动的控制信号会加速机械磨损。4.5 第五步回到真实环境做验收想象出来的策略必须回到真实环境验证这是整条链路里不能省的一步。# 文件路径evaluate.py import numpy as np import gymnasium as gym import torch from model import WorldModel from plan import plan_action def load_model(pathwm.pt, devicecpu): ckpt torch.load(path, map_locationdevice) model WorldModel(ckpt[obs_dim], ckpt[act_dim]).to(device) model.load_state_dict(ckpt[state_dict]) model.eval() return model def evaluate(model, env_idPendulum-v1, episodes5, horizon20, devicecpu): env gym.make(env_id) returns [] for ep in range(episodes): obs, info env.reset(seed1000 ep) done False total 0.0 steps 0 while not done: act plan_action(model, obs, horizonhorizon, devicedevice) obs, rew, terminated, truncated, info env.step(act) total rew steps 1 done terminated or truncated returns.append(total) print(fepisode {ep} steps {steps} return {total:.2f}) env.close() print(fmean return: {np.mean(returns):.2f}) return float(np.mean(returns)) if __name__ __main__: device cuda if torch.cuda.is_available() else cpu model load_model(wm.pt, devicedevice) evaluate(model, devicedevice)5. 运行结果与效果验证按顺序跑这三条命令python train_wm.py python evaluate.py预期输出大致是这样训练阶段每 20 步打印一次 loss数值从几下降到零点几的量级评估阶段每个 episode 打印步数和累计回报。判断成功的标准分两层。第一层是模型层面观测重建损失和奖励预测损失都稳定下降没有剧烈震荡这说明动力学模型学到了东西。第二层是决策层面评估回报明显高于随机策略的基准。Pendulum 这个环境随机策略的回报大概在一个负数区间如果你的规划策略回报没有超过它说明模型还不够准或者规划视野设置不合理。如果评估结果不理想排查顺序建议是先看训练损失有没有收敛。如果 loss 一直在高位先加数据量或者加训练步数别急着改模型结构。再看多步预测误差。可以在训练脚本里额外打印第 1 步、第 5 步、第 10 步的预测误差如果误差随步数指数增长说明想象视野设太长了把horizon从 20 降到 8 试试。最后看规划采样量。num_samples太小会导致规划噪声大可以尝试从 512 提到 2048代价是推理变慢。必须坦率说明一点这个最小示例在 Pendulum 上能跑出效果是因为状态维度极低、动力学简单。换到高维图像输入或者真实机器人上需要补的东西非常多——表征学习、奖励归一化、更长的训练、更复杂的规划器。这个示例的价值在于让你把这套流程跑通一遍知道每个模块在做什么而不是直接拿去上线。6. 三类落地场景的接入点6.1 自动驾驶世界模型主要解决长尾覆盖自动驾驶的接入点不在控制层而在场景生成和闭环测试。具体做法是用真实路采数据训练一个能预测未来若干帧鸟瞰图或传感器数据的模型然后在模型里做闭环 rollout让规划模块在大量合成但合理的长尾场景里跑。这里的核心难点是动作条件化。很多视频生成模型只能做无条件生成或简单条件生成但自动驾驶需要如果我此时向左打方向盘 15 度未来三秒会怎样这种精确的动作条件预测。这也是为什么价值等价路线和重建路线在这个领域仍然比纯生成式路线更受工程团队欢迎——它们对动作的响应更可靠。落地建议是先把世界模型用在评测而不是训练。用它批量生成边缘场景让已有的规划模块去跑看失败率。这个用法风险低、收益明确而且不需要改动现有训练管线。6.2 机器人世界模型补的是硬件损耗和安全边界机器人领域的痛点更具体真机采样慢、贵、危险。世界模型在这里的价值是把策略迭代的主战场从真机搬到模型里。Dreamer 系列在 MuJoCo 和 DeepMind Control Suite 上的公开结果证明了这条路在连续控制上是可行的。接入时的关键决策是选哪个状态表示。如果你的机器人只有本体感知关节角度、速度、力矩状态维度低直接用低维世界模型就够了成本很低。如果涉及视觉输入就必须处理高维观测这时候建议先用预训练视觉编码器把图像压成特征向量再在世界模型里做动力学而不是端到端从像素学起。还有一个容易被忽略的点是安全性。世界模型预测错了不会有人受伤但策略如果在错误的模型里被训练得很激进回到真机就是事故。所以从模型迁移到真机时必须有一套独立于模型的安全约束比如力矩上限、工作空间限制、急停逻辑。这层约束不能交给世界模型来判断。6.3 LLM 智能体世界模型是行动后果预测器LLM 智能体这一类的接入逻辑和前两类不太一样。这里的世界模型不一定是一个神经网络动力学模型它更接近给定当前状态和拟执行动作预测系统会变成什么样的模拟器。实际形态有三种。第一种是代码沙箱Agent 在执行rm或者git push之前先在沙箱里跑一遍看结果是否符合预期。第二种是状态模拟器比如在网页操作任务里维护一个 DOM 树的抽象表示预测点击某个按钮后页面会变成什么样。第三种是结果预测模型用一个小模型去评估这个工具调用会不会失败失败率高就换方案。用一个简化的接口表达大概是这个形状# 文件路径agent_world_model.py from dataclasses import dataclass, field dataclass class AgentState: history: list field(default_factorylist) env_snapshot: dict field(default_factorydict) class AgentWorldModel: LLM Agent 的世界模型预测动作后果不预测像素。 def __init__(self, simulator): # simulator 可以是沙箱、mock 服务、或一个学出来的预测模型 self.simulator simulator def predict(self, state: AgentState, action: dict) - AgentState: 返回执行 action 之后预期的状态不产生真实副作用。 snapshot self.simulator.step(state.env_snapshot, action) return AgentState( historystate.history [action], env_snapshotsnapshot, ) def score(self, state: AgentState, goal: str) - float: 给预测出的状态打分用于在多个候选动作里做选择。 return self.simulator.evaluate(state.env_snapshot, goal)这个类的价值在于把想和做分开了。Agent 可以先生成多个候选动作全部在predict里过一遍用score排序只把最高分的那一个真正执行。这个模式在需要调用有副作用工具的场景里几乎是必需的。要提醒的是LLM 智能体的世界模型目前最大的问题是保真度。沙箱和真实环境的行为差异可能很大尤其是涉及并发、权限、外部服务的时候。所以这套机制更适合做粗筛把明显不合理的动作挡掉而不是做最终决策。7. 常见问题与排查思路问题现象可能原因排查方式解决方案训练 loss 不下降学习率过大或数据量不足打印每步 loss观察是否震荡降低学习率增加采集 episode 数单步预测准多步崩溃误差累积模型对分布外状态无准备分别打印第 1/5/10 步的预测误差缩短想象视野加入多步训练目标规划策略在真实环境表现差模型在真实状态分布上不准对比真实状态与模型隐状态的分布用真实数据微调模型扩大采集覆盖奖励预测全是常数奖励尺度差异大或损失权重失衡统计真实奖励的均值方差做奖励归一化调整损失权重显存不足序列长度和 batch 太大看nvidia-smi显存占用缩短seq_len减小batch_size规划耗时过长采样数过多或网络太宽计时单次规划调用的耗时减小num_samples用 CEM 替代随机打靶隐状态塌缩成常数KL 项权重过大或缺少观测约束检查隐状态的方差调整 KL 权重加强重建损失这里重点说两个最有代表性的。第一个是单步准、多步崩。这是世界模型的通病本质上是因为模型在训练时见到的都是真实状态分布但在想象时它会走进自己预测出的状态一旦某一步偏了后面就再也回不来。缓解手段有几个一是训练时也用模型自己的预测做输入scheduled sampling 的思路让模型见过自己的错误二是缩短想象视野宁可在短视野里多规划几次也不要一次规划很远三是在损失里加大后期步的权重。第二个是规划策略在真实环境失效。这个往往不是模型的问题而是规划器的问题。比如随机打靶每次采样的动作序列是独立的相邻时间步的动作可能剧烈跳变这种抖动在简单环境里看不出来在真实机器人上会直接导致执行失败。解决办法是引入动作平滑约束或者改用 CEM 让采样分布逐步收敛。8. 最佳实践与工程建议8.1 数据质量比模型结构更重要这一点在实践里被反复验证。世界模型是监督学习它学到的东西上限由数据决定。如果采集数据用的是纯随机策略那么模型在状态空间的边缘区域策略真正会走到的区域可能根本没有数据预测自然不准。所以更推荐的做法是用当前策略采一批数据训一轮模型用模型训一代策略再用新策略采数据。这个循环就是 Dyna 架构的现代版本也是 Dreamer 系列能work的工程基础。8.2 想象视野要短规划频率要高很多人直觉上觉得想得越远越聪明实际恰恰相反。世界模型的预测误差随步数增长20 步之后的预测基本没有参考价值。工程上更稳妥的做法是 horizon 设短一点然后每一步都重新规划receding horizon control。这样即使模型有误差也能靠频繁的真实观测校正回来。8.3 奖励预测要单独归一化不同任务的奖励尺度差异极大有的是每步 -0.1有的是每步 -1000。如果直接把原始奖励喂给网络梯度会被大数值主导。DreamerV3 用 symlog 变换解决这个问题具体做法是对奖励做sign(x) * log(1 |x|)的压缩预测时再反变换回去。如果你不想引入这个复杂度至少也要做标准的均值方差归一化。8.4 训练和推理必须用同一套状态初始化这是个非常隐蔽的坑。训练时隐状态从零向量开始经过一段序列逐渐收敛到合理值但推理时你只有单帧观测如果也直接从零向量开始前几步的预测会严重偏离。正确做法是在推理时用一段历史观测预热隐状态或者像本文示例那样显式调用一次posterior_step做对齐。8.5 安全边界不能交给模型这一条适用于所有涉及物理系统的场景。世界模型的输出只能用于生成候选动作最终执行必须经过独立的安全层校验。速度上限、力矩上限、工作空间约束、急停逻辑这些必须是硬编码的规则不能是模型学出来的偏好。同样的道理也适用于 LLM 智能体——涉及数据删除、生产变更、权限提升的动作必须有独立于 Agent 的审批环节。8.6 版本与依赖要锁死世界模型的实验结论对依赖版本非常敏感。PyTorch 的 GRU 实现在不同版本间可能有数值差异Gymnasium 的 API 在 0.26 前后有断裂性变化仿真器的物理引擎更新可能直接改变任务难度。所以生产项目里必须锁死依赖版本并且把数据采集脚本和模型训练脚本放在同一个环境里跑避免出现训练时是这个分布评估时是另一个分布的情况。9. 总结与下一步该做什么回到最开始那个判断世界模型改变的不是要不要碰真实环境而是碰多少。它把真实环境的角色从训练数据的主要来源变成了校准和验收的标尺。这个转变对自动驾驶、机器人、LLM 智能体这三类高采样成本场景来说价值是实打实的。本文讲清楚了几件事。世界模型的四个组成部分和各部分缺失的后果重建、价值等价、生成式三条路线的真实取舍以及为什么重建路线在工程落地时风险最低一个能在几十行代码里跑通的潜空间世界模型包含 posterior 与 prior 分离这个关键设计以及三类场景分别该在哪一层接入。如果你现在要往下走我建议的路径是这样先把你手头项目的数据采集管线跑通确认能稳定产出(obs, act, reward, next_obs, done)五元组。然后在这个数据上训一个最小世界模型只关注损失曲线是否收敛别急着接策略。等模型能稳定做多步预测了再接规划器并且一开始只在仿真里验证。最后才是真机迁移而且迁移时务必保留一套独立的安全校验。值得继续深挖的方向有三个一是表征学习怎么让潜空间既能重建又对决策有用这是当前研究最活跃的地方二是长视野下的误差控制目前还没有特别优雅的解法三是世界模型与 LLM 的结合让语言模型来做高层规划、世界模型来做低层后果预测这条路线在具身智能里已经有不少探索。最后一句提醒世界模型是一个放大器它放大的是你数据里的规律也包括数据里的偏差。如果你的采集策略本身有问题世界模型只会把这个问题学得更牢。所以在投入模型复杂度之前先把数据管线打磨好收益会大得多。建议把这篇文章里的代码骨架收藏下来换成你自己的环境接口很快就能跑出第一版对照实验。
阅读完成 · 觉得有帮助?