第 6 章 学习世界模型 + 采样规划——TD-MPC 系列¶
📋 前置自测¶
怎么用这份自测:第 1–5 题考查前置知识(前几章 MPPI/CEM + RL 基础),答不出 ≥ 2 题,建议先回第 2 章(MPPI 主循环、加权更新)、第 4 章(CEM、采样 MPC 统一视角)和 RL 基础(TD learning、Q-function、SAC)再读本章。第 6、7 题不是前置知识,而是"先记下你的直觉、本章会给你答案"的引子——答不上来很正常,带着好奇读下去即可。
- 第 2 章 MPPI / 第 4 章 CEM 的规划,是在什么空间里 rollout 的?rollout 一条轨迹需要什么(动力学模型 + 代价)?
- vanilla MPPI/CEM 的规划 horizon 通常是多少(几十步)?为什么不能无限加长 horizon?(提示:计算成本、以及更微妙的原因。)
- 强化学习里的 价值函数 \(V(s)\) / 动作价值 \(Q(s,a)\) 是什么意思?它估计的是"从当前状态出发的什么量"?
- RL 里的 TD learning(时序差分) 大致怎么工作?\(Q(s,a) \leftarrow r + \gamma Q(s', a')\) 这个 bootstrap 更新在做什么?
- SAC 里为什么用 两个 Q 网络取较小值(double Q / clipped double-Q)?它在防止什么问题?
- 如果让你的 MPPI 只规划很短的 horizon(比如 3 步),但又想让它做出"有远见"的决策,你能想到什么办法补足"3 步之后的长期信息"?(本章的核心答案就藏在这里。)
- 你做控制时用的动力学模型,是"物理方程/仿真器"还是"从数据学出来的神经网络"?两者各有什么利弊?(本章会系统对比。)
参考答案要点(自评用,不必逐字对照):(1) 在**真实状态空间**里 rollout,每条轨迹需要一个动力学模型(仿真器或方程)把状态往前推,并对每步算代价/reward。
(2) 通常几十步(H=30~100);不能无限加长,一是计算成本随 horizon 线性增长,二是更微妙——若用学习的模型,rollout 越长**累积误差**越大(本章 §6.8 会量化)。
(3) \(V(s)\) 估计"从状态 \(s\) 出发、按某策略一直走下去能拿到的期望(折扣)回报";\(Q(s,a)\) 是"在 \(s\) 先做 \(a\)、之后按策略走的期望回报"。它们把"无穷远的未来"压缩成一个数。
(4) TD learning 用"当前估计 + 一步真实反馈"去更新价值:\(Q(s,a)\leftarrow r+\gamma Q(s',a')\) 把"下一步的价值估计"当作"剩余未来"的代理,bootstrap 地修正当前估计,无需走到 episode 结束。
(5) 防止 价值过估计——单个 Q 网络的近似误差会被 max 操作系统性放大,取两个 Q 的较小值抑制这种乐观偏差。
(6) 用一个**学习的价值函数**估计"3 步之后的长期回报",把它加到 3 步 rollout 的末端作为"终端代价/价值"——这正是 TD-MPC 的核心思想。
(7) 物理/仿真器:精确、可解释、不用训练,但可能慢、且复杂接触/形变难建准;学习的网络:快、能拟合难建模的现象、任务导向,但要数据训练、有泛化和误差累积问题。本章讲的就是"学习模型"这一端。
符号说明:本章 \(\lambda\) 表示训练损失的时步衰减权重(\(\in(0,1)\)),不同于第 1–4 章的 MPPI 温度参数 \(\lambda\)。
本章目标¶
学完本章后,你应该能够:
- 说清 TD-MPC 的三大组件——编码器 \(h_\theta\)(观测→latent)、latent 动力学 \(d_\theta\)(在 latent 空间预测下一状态)、价值 \(Q_\theta\)(终端长期价值),以及它们为什么要在 latent 空间而非原始观测空间工作;
- 理解 为什么在 latent 空间做采样规划(MPPI/CEM)有优势——latent 动力学是轻量规整的网络、可大批量并行 rollout,且"任务导向"地只编码与决策相关的信息;
- 吃透本章核心洞察——用学习的 \(Q_\theta\) 作终端价值,让"短 horizon 采样"获得"长 horizon 的远见",从而同时绕开 vanilla MPPI 的两个限制(长 horizon 的计算成本 + 学习模型的累积误差);
- 理解 TD-MPC 的联合训练——编码器/动力学/reward/价值四个网络如何用 TD 误差 + reward 预测 + latent 一致性损失联合训练,以及为什么用 latent 一致性而非重建观测;
- 理解 TD-MPC2 的规模化——单一超参集 + implicit(decoder-free) world model + 架构改进(SimNorm、Q 集成、离散回归等)如何让一套方法覆盖 100+ 任务、并随模型/数据规模提升;
- 把本章方法**准确接回采样式 MPC 的脉络**——它和第 2–4 章的 MPPI/CEM 用的是同一个采样规划内核,只是把"真实动力学 + 短 horizon"换成了"学习的 latent 动力学 + 学习的终端价值";
- 清醒地认识学习世界模型的边界——compounding error(OOD 状态下尤甚)、价值过估计/policy mismatch、以及"模型保真度 vs 速度/可学习性"这个贯穿始终的根本权衡。
本章知识导航¶
前一章(扩散启发采样 MPC)我们站在 model-based 光谱的一端:用已知的动力学和代价免训练地算 score,不学任何东西。本章走到光谱的另一端:训练一个学习的世界模型——既学动力学、又学价值——再用我们熟悉的采样规划(MPPI/CEM)在这个学出来的模型里规划。
为什么要费力学一个模型?因为 vanilla 采样式 MPC(第 2–4 章)有两个绕不开的限制,而学习的世界模型恰好同时回应了它们——
- 一是 rollout 依赖真实动力学:真实仿真器/物理步可能慢、或在高维接触下昂贵,且每个新任务都要重写。学习的 latent 动力学 是个轻量规整的网络,前向极快、可大批量并行、且能"任务导向"地只保留与决策相关的信息。
- 二是 短 horizon 看不到长期:采样规划的 horizon 受限(计算成本 + 学习模型的累积误差都不允许太长),于是长期目标信息缺失、决策短视。TD-MPC 用一个学习的 价值函数 \(Q_\theta\) 作终端价值,把"horizon 之后的长期回报"一并估进来——短 horizon 采样 + 学习的长期价值 = 兼得二者之长。
本章的逻辑链:
| 节 | 主题 | 在全章中的位置 |
|---|---|---|
| §6.1 | 从已知模型到学习的世界模型 | 动机——vanilla MPPI 的两个限制 + model↔data 光谱定位 |
| §6.2 | TD-MPC 三组件架构 | 编码器 + latent 动力学 + reward + 价值;为什么在 latent 空间 |
| §6.3 | 在 latent 空间做采样规划 | 把熟悉的 MPPI/CEM 搬进 latent 空间;plan 算法全解 |
| §6.4 | 价值作终端代价:短 horizon + 学习的长期价值 | 全章核心洞察——Q 如何让短 horizon 不再短视 |
| §6.5 | 联合训练:四网络 + TD + latent 一致性 | 这套世界模型怎么从数据学出来 |
| §6.6 | TD-MPC2 规模化 | 单一超参、implicit world model、100+ 任务、工程改进 |
| §6.7 | 实战与代码精读 | planning.py 精读 + 最小 latent 规划实现 |
| §6.8 | 局限与前沿 | compounding error、过估计、模型保真度 vs 速度的根本权衡 |
一条贯穿全章的主线:学习的世界模型,把采样式 MPC 从"在真实动力学里做短视的局部优化"升级为"在学习的 latent 空间里做有远见的规划"。 它不改采样规划的内核(还是 MPPI/CEM 的"采样—rollout—加权/精英更新"),而是换掉了两个零件——动力学(真实→学习的 latent)和终端处理(截断→学习的价值)。抓住这一点,你就明白本章既是采样式 MPC 的延续,又是它与强化学习(价值学习)的一次深度联姻。
§6.1–§6.2 建立"为什么学模型、模型长什么样",§6.3–§6.4 讲"怎么在里面规划、核心洞察是什么",§6.5 讲"模型怎么训练出来",§6.6 讲"怎么规模化到通用",§6.7–§6.8 落到实战与诚实的边界——前半章建立"是什么、为什么",后半章解决"怎么用、怎么训、何时不灵"。
前置知识桥接¶
本章建立在前几章的采样式 MPC 和你的 RL 基础之上,先把要反复用到的关键点温习一遍:
- MPPI / CEM 的采样规划(第 2–4 章):采 \(K\) 条动作序列、用模型 rollout 算每条的回报、按回报做指数加权(MPPI)或精英平均(CEM)更新分布、迭代几轮、执行第一个动作。本章把这套内核**原封不动**搬进 latent 空间——变的只是"在哪 rollout"和"末端怎么收尾"。
- 滚动时域与 warm-start(第 2 章):MPC 每个控制周期重新规划、只执行第一步、用上周期解平移作初值。TD-MPC 的 plan 同样是滚动时域 + warm-start。
- 价值函数与 TD learning(RL 基础):\(Q(s,a)\) 估计"从 \(s\) 做 \(a\) 之后的长期折扣回报";TD 用 \(Q(s,a)\leftarrow r+\gamma Q(s',a')\) bootstrap 地学它。本章的核心就是把这个 \(Q\) 接到采样规划的末端当终端价值。若这块生疏,务必先回顾——它是本章的另一半地基。
- SAC 与双 Q(RL 基础):SAC 用最大熵目标学随机策略,用两个 Q 取较小值抑制过估计。TD-MPC2 的 policy prior 用类 SAC 的最大熵目标、价值用 Q 集成——这些 RL 直觉直接迁移。
- model-based vs model-free(RL 基础):model-free(如 SAC)直接学策略/价值、不学模型;model-based 学一个环境模型再用它规划。TD-MPC 是 model-based,但它学的模型是"任务导向的 latent 模型",且融合了 model-free 的价值学习——本章会讲清这个融合。
- 第 5 章的 model↔data 光谱:上一章(扩散启发采样 MPC)我们看到方法可以按"靠模型还是靠数据"排成一条光谱,免训练的扩散 MPC 在纯模型一端。本章的 TD-MPC 在另一端(学习的模型 + 数据),正好补全这条光谱——建议回看第 5 章那条光谱,本章是它的自然延伸。
如果上面某条记不清,对应来源会帮你补上;但务必把"MPPI/CEM 采样规划"和"价值函数 / TD learning"这两块记牢,本章是这两者的交汇。
如果跳过本章会怎样¶
设想几个场景,它们会让你卡住:
场景一:你想把采样式 MPC 用在一个真实动力学很贵、或根本没有解析模型的任务上(如从像素观测做控制),却发现每步 rollout 慢到无法实时、或压根没有可 rollout 的模型。 vanilla MPPI 假设你有一个能快速 rollout 的模型,这个假设并不总成立。
不懂学习世界模型,你会卡在"没有快模型就用不了采样 MPC";懂了,你知道可以**学一个轻量的 latent 动力学**当 rollout 模型——它快、可并行、还能直接吃像素观测。这是把采样式 MPC 推广到"无快模型/高维观测"任务的关键。
场景二:你的 MPPI 规划 horizon 调来调去都不对——调短了短视(只顾眼前、错过远处更优解),调长了既慢、又因模型不准而 rollout 失真。 这是采样式 MPC 一个深层的两难。
不懂 TD-MPC,你会在 horizon 长短之间反复横跳、找不到甜点;懂了,你知道正确答案不是"调 horizon",而是**用一个学习的价值函数补足长期信息**,让短 horizon 也有远见(本章 §6.4 的核心洞察,配 demo)。这会改变你设计采样规划器的思路。
场景三:你读到"world model""TD-MPC""DreamerV3""latent planning"这些近年最热的 model-based RL 工作,却看不懂它们和你会的 MPPI/CEM 是什么关系。 学习世界模型 + 规划是当前具身智能最活跃的方向之一。
不懂本章,你会把它们当成全新的、和采样 MPC 无关的 RL 领域;懂了,你会发现 TD-MPC 的规划内核就是你已经会的 MPPI/CEM,只是搬进了 latent 空间、加了个学习的终端价值——学习成本骤降。这把"采样式 MPC"和"现代 model-based RL"接通了。
一句话:前几章把采样式 MPC 的"采样规划内核"讲透了(在真实动力学里、短 horizon),本章教你把这个内核搬进一个**学习的 latent 世界模型**、并用**学习的价值**补足长期信息——这是采样式 MPC 与现代 RL 的交汇,也是把它推向高维、无模型、通用任务的关键一步。
预计阅读时间¶
- 精读(推导 + 代码 + 跑 demo):约 4.5–6 小时。§6.2 的三组件架构和 §6.4 的核心洞察是全章地基,值得慢读;§6.5 的训练流程稍密,可结合代码理解。
- 速读(抓主线、跳过部分细节):约 2 小时。重点读 §6.1 的两个限制、§6.4 的"短 horizon + Q"核心洞察、§6.6 的 TD-MPC2 规模化。
- 速查(按需查阅):三组件架构看 §6.2 的结构图;plan 算法看 §6.3 的伪代码;TD-MPC2 超参看 §6.6 的参数表。
本章学习路径建议¶
本章是采样式 MPC 与强化学习的交汇,概念密度大,按背景和目标可走不同路径:
如果你 RL 基础扎实、想快速抓住核心:精读 §6.2(三组件)+ §6.4(核心洞察,配 demo),再看每节末尾的"本质洞察"。这条最短路径能让你建立"学习的 latent 模型 + 学习的价值 = 短 horizon 也有远见"的核心直觉。
如果你想理解工程实现:在上面基础上重点读 §6.3(plan 算法逐行)、§6.5(训练流程与损失)、§6.7(代码精读 + 最小实现)。这条路径帮你把 TD-MPC 真正落成可运行的代码。
如果你 RL 基础较薄:先补 §6.1 的动机和前置桥接里的价值函数/TD 部分,再慢读 §6.2、§6.4,把"价值函数是什么、为什么能当终端代价"彻底搞懂——这是本章相对前几章新增的最关键概念。
如果你关心研究前沿:在理解前几节后,读 §6.6(规模化)+ §6.8(局限与前沿),重点掌握"compounding error""价值过估计""模型保真度 vs 速度"这几个开放问题——它们是这个方向当下最活跃的题目来源。
无论走哪条路径,都建议亲手跑本章 §6.4 和 §6.8 的两个 NumPy demo(短 horizon + Q 解决短视、compounding error 累积)——它们用几十行就把本章最核心的两个论点演示得清清楚楚,胜过反复读文字。
科研发展脉络¶
本章的两项核心工作都出自 UCSD(Hansen 等),是"学习世界模型 + 采样规划"这条线的代表:
| 年份 | 工作 | Venue | 一句话贡献 |
|---|---|---|---|
| 2022 | Hansen, Wang, Su, Temporal Difference Learning for Model Predictive Control(TD-MPC) | ICML 2022(arXiv:2203.04955) | 学习的任务导向 latent 动力学 + 学习的终端价值,用 TD 联合训练;首次在 1M 步内解决高维 Dog 运动任务 |
| 2024 | Hansen, Su, Wang, TD-MPC2: Scalable, Robust World Models for Continuous Control | ICLR 2024(arXiv:2310.16828) | implicit(decoder-free) world model + 单一超参集,覆盖 104 任务;单个 317M agent 做 80 任务 |
这条脉络的内在逻辑可以这样读。
model-based RL 长期有一个尴尬:理论上"学个模型再规划"应该比 model-free 更省样本、更强,但实践中 model-based 方法常常**跑不赢** model-free(如 SAC)——原因是学到的模型不准、长 horizon 规划时误差累积,且学一个能精确重建观测的模型本身很难。
2022 年的 TD-MPC 给出一个漂亮的融合:不追求精确重建的模型,只学一个"任务导向"的 latent 模型(只编码与回报相关的信息),并把 model-free 的**价值学习**接进来当终端价值。这样既用短 horizon 规划(避开长 rollout 的误差累积),又用学习的价值补足长期信息——model-based 的样本效率和 model-free 的渐近性能兼得。TD-MPC 由此首次在 1M 步内解决了高维 Humanoid 和 Dog 任务。
2024 年的 TD-MPC2 把这套方法**规模化、鲁棒化**:去掉解码器(implicit world model,连 latent 重建都不要了)、引入一系列稳定训练的架构改进(SimNorm、Q 集成、离散回归等),最关键的是做到**单一超参集覆盖所有任务**——104 个任务不调参,还训练了单个 317M 参数的 agent 做 80 个跨域任务。这把"学习世界模型 + 规划"从"每任务精调的研究原型"推向了"一套方法通吃"的通用控制器。
一个值得留意的趋势:这条线在"让学习的模型既准又通用"上持续发力,而它的规划内核,自始至终是你已经熟悉的采样式 MPC(MPPI/CEM)。本章带你走完这一段——从单任务的 TD-MPC,到通用的 TD-MPC2。
§6.1 从已知模型到学习的世界模型:vanilla MPPI 的两个限制 ⭐⭐¶
动机:采样规划一直假设你"有一个能快速 rollout 的真实模型"¶
回顾前几章,无论是第 2 章的 MPPI 还是第 4 章的 CEM,它们的规划循环都长这样:采一批动作序列、用**动力学模型**把每条序列 rollout 成一条状态轨迹、对每步算代价、按回报更新分布、迭代、执行第一个动作。这套内核里有一个一直被默认、却很关键的前提——你手上有一个能快速 rollout 的真实动力学模型。
这个前提在很多场景下成立:你有机器人的刚体动力学方程(Pinocchio)、有一个 MuJoCo 仿真器、或一个写得出的解析模型。前几章正是建立在这个前提上的。但当你想把采样式 MPC 推得更远时,这个前提开始出现两道裂缝,而本章要讲的"学习世界模型",恰恰就是来补这两道裂缝的。
先把这两道裂缝(vanilla 采样式 MPC 的两个限制)说清楚,它们是本章全部动机的源头。
限制一:rollout 依赖真实动力学——它可能慢、贵,或根本不存在。 采样式 MPC 每个控制周期要 rollout 成百上千条轨迹、每条几十步,总 rollout 量巨大。如果单步 rollout 很贵(高维全阶动力学、复杂接触求解、或一个重型仿真器),这个成本会压垮实时性。更极端的情形是:你**根本没有可 rollout 的模型**——比如你的观测是一堆像素(摄像头图像),你没有"像素的动力学方程",无法在像素空间 rollout。这时 vanilla 采样 MPC 直接卡住。
限制二:短 horizon 看不到长期——决策短视。 采样式 MPC 的规划 horizon 受限(通常 H=30~100)。为什么不能无限加长?两个原因:一是**计算成本**随 horizon 线性增长;二是更微妙的——后面会讲到,如果用学习的模型,rollout 越长**累积误差**越大(§6.8 会量化)。horizon 受限带来一个根本问题:horizon 之外的长期回报,规划器完全看不到。 如果最优解需要"先忍受短期的低回报、换取远期的高回报"(比如先绕路、先蓄力、先离开一个局部舒适区),而那个远期回报落在 horizon 之外,短 horizon 的规划器就会做出短视的决策——只顾眼前 H 步内的回报,错过真正的全局最优。
读到这里你可能会问:第 5 章的扩散退火不是已经让采样 MPC 上了高维全阶控制吗?这两个限制不是解决了? 没有——退火解决的是"高维非凸下如何高效搜索",但它**仍在真实动力学里 rollout、仍是有限 horizon**。退火让你在给定的真实模型和 horizon 下搜得更好,但没有改变"依赖真实模型"和"horizon 受限"这两件事本身。本章要动的,正是这两个更底层的前提。
读到这里你可能会问:这两个限制前几章一直存在,为什么到本章才拿出来解决?前几章是怎么"容忍"它们的? 这是个好问题,答案揭示了本章的定位。前几章其实是通过"挑选合适的问题"来回避这两个限制的——它们默认你研究的是"有现成快模型、且短 horizon 够用"的任务(如有解析动力学的机器人、目标不太远的控制问题)。在这些任务上,两个限制不致命:有快模型所以 rollout 不慢、目标不远所以短 horizon 不短视。前几章把精力放在"在这类问题上,如何把采样规划做得更好"(更鲁棒、更平滑、更高维、用退火逃局部最优)。
但现实里有大量任务**不满足**这两个前提——观测是像素(没有快模型)、或最优解需要长远规划(短 horizon 必短视)。前几章的方法在这些任务上会直接卡住。本章正是来解决这类任务的:它不再回避两个限制,而是用学习世界模型正面解决它们,从而把采样式 MPC 的适用范围从"有快模型、短 horizon 够用"扩展到"无快模型、需要远见"。这就是本章在整个采样式 MPC 脉络里的独特位置——前几章深耕"容易的问题域",本章拓展"困难的问题域"。
那怎么补这两道裂缝?本章的答案是一个听起来朴素、做起来精妙的转变:不再依赖真实动力学,而是从数据里学一个"世界模型"——既学一个轻量的动力学(补限制一),又学一个价值函数当终端价值(补限制二)。
如果不这样做会怎样:把"采样 MPC"和"学习世界模型"当成两个无关的领域¶
如果你不建立"学习世界模型 = 给采样 MPC 换两个零件"这个连接,会付出什么代价?
第一,面对"无快模型/像素观测"的任务束手无策。你会觉得采样式 MPC 只能用在"有现成快模型"的任务上,遇到像素输入或昂贵动力学就放弃,转而去学一个纯 model-free 的策略(如 PPO/SAC)——错过了"学个 latent 模型继续用采样规划"这条样本效率高得多的路。
第二,在 horizon 长短间反复横跳、找不到甜点。不知道"用价值补长期"这条路,你只会在"调短了短视、调长了又慢又失真"之间徒劳地试,把它当成一个无解的两难——而 TD-MPC 早就给出了答案。
第三,看不懂现代 model-based RL。TD-MPC、DreamerV3、PlaNet、世界模型……这些近年最热的工作,内核都是"学一个 latent 世界模型 + 在里面规划/想象"。不把它们和你会的采样 MPC 接上,你会把它们当成全新的 RL 领域从头学,而看不出它们的规划内核就是你熟悉的 MPPI/CEM。
所以"看穿学习世界模型 = 采样 MPC 换两个零件"不是一个炫技的联系,而是让你能低成本接住整个现代 model-based RL 方向、并把采样 MPC 推向高维通用任务的地基。
历史:model-based RL 为什么常常跑不赢 model-free¶
要理解 TD-MPC 的设计,得先知道它要解决的历史困境。这段背景不长,但能让你明白 TD-MPC 的每个设计选择都不是凭空来的。
强化学习大致分两条路。model-free(如 PPO、SAC)直接从交互数据里学一个策略或价值函数,不显式建模环境——简单、鲁棒,但样本效率低(要大量交互)。model-based(如 PlaNet、PETS、Dreamer)先学一个环境模型(给定状态和动作,预测下一状态和 reward),再用这个模型做规划或想象——理论上样本效率更高(一个模型可以反复"脑内推演"),也更灵活(换个 reward 不用重学模型)。
把 model-based 的优势说得再具体一点,它其实有两个层面,这也是 TD-MPC 论文开篇强调的。其一是样本效率:一个学好的模型可以反复"脑内推演"——同样一段真实交互数据,model-free 只能用它更新一次策略/价值,而 model-based 可以用它训练模型,再让模型生成无数条想象轨迹来规划/训练。数据被"榨"得更充分,所需的真实交互就更少。这对真机机器人尤其宝贵——真实交互又慢又贵(要真机跑、可能损耗硬件),样本效率高意味着省时省钱省硬件。
其二是"计算预算增大时性能更好":model-free 的策略是固定的(一次网络前向出动作,给它再多在线计算也不会更好);而 model-based 的规划可以"花更多算力换更好的决策"——多采样一些轨迹、多迭代几轮、规划更长一点,决策质量就更高。这意味着 model-based 有一个 model-free 没有的旋钮:在线时可以用计算换性能。
正因为这两个诱人的优势,研究者一直执着于把 model-based 做好。按这个逻辑,model-based 应该全面优于 model-free。但在 TD-MPC 出现之前的很长时间里,事实**恰恰相反**:在连续控制基准上,model-based 方法常常**跑不赢**调好的 model-free 方法(如 SAC)。为什么?
原因有三,每一个都直指 TD-MPC 的一个设计:
其一,学一个精确的模型很难,尤其要重建高维观测。 早期 model-based 方法(如 PlaNet、Dreamer)学的模型要能**重建观测**(给定 latent,解码回原始图像/状态)。但高维观测里有大量与决策无关的细节(背景纹理、光照),逼模型去精确重建这些细节,既浪费容量又分散了"学好决策相关动态"的注意力。
其二,长 horizon 规划会累积模型误差。 模型每步预测都有小误差,rollout 越长误差累积越大(§6.8 会量化这个"compounding error")。所以 model-based 方法若用长 horizon 规划/想象,误差会毁掉规划质量。
其三,纯规划是"局部"的,看不到 horizon 之外。 即便模型准、horizon 短以避开误差累积,短 horizon 规划本身就是局部的——它找到的是"未来 H 步内的局部最优",不保证是全局最优(这正是 §6.1 开头讲的限制二)。
TD-MPC 的三个核心设计,恰好一一回应这三个困境:用**任务导向的 latent 模型**(不重建观测,只编码决策相关信息)回应其一;用**短 horizon 规划**(避开长 rollout 的误差累积)回应其二;用**学习的终端价值**(把 horizon 之外的长期回报估进来)回应其三。下面的小节会逐一展开,但先记住这个"三困境 → 三设计"的对应,你就抓住了 TD-MPC 的设计逻辑。
这套设计的成效有多显著?TD-MPC 论文报告了一个标志性结果:它**首次在 100 万环境步内解决了高维的 Humanoid 和 Dog 运动任务**——据其所述,这是当时已知首个解决具有挑战性的 Dog 任务的记录。为什么这是个里程碑值得体会:Dog(约几十个自由度的四足)和 Humanoid 是 DMControl 里最难的连续控制任务之一,维度高、动态复杂、需要精细的全身协调。在 TD-MPC 之前,model-based 方法在这类高维任务上普遍力不从心(要么学不好模型、要么规划被误差毁掉)。TD-MPC 用"任务导向 latent + 短 horizon + 终端价值"的组合,在很少的交互(1M 步,对高维任务来说相当省)内就攻克了它们——这有力地证明了它的设计真正兑现了 model-based 的样本效率优势,而非又一个"理论好、实际跑不赢"的方法。这个结果也是 TD-MPC 引起广泛关注、并催生 TD-MPC2 等后续工作的重要原因。
回顾:采样式 MPC 一路走来,本章在哪¶
在展开本章之前,花一分钟把前几章的采样式 MPC 串起来,看清 TD-MPC 站在这条脉络的哪个位置。这能帮你把本章接入已有的知识树,而非当成孤立的新主题。
| 章 | 方法 | 核心贡献 | 动力学 | 规划空间 |
|---|---|---|---|---|
| 第 1 章 | 路径积分理论 | HJB 经指数变换变线性,奠定采样最优控制的数学 | 真实 | 真实状态 |
| 第 2 章 | MPPI 核心 | 采样—rollout—指数加权的核心算法 + GPU 并行 | 真实 | 真实状态 |
| 第 3 章 | MPPI 六大变体 | 鲁棒/平滑/多模态/不确定性等改进 | 真实 | 真实状态 |
| 第 4 章 | CEM 家族与统一 | 把采样 MPC 统一成"提议分布 + 加权更新"的框架 | 真实 | 真实状态 |
| 第 5 章 | 扩散启发 MPC | MPPI = 单步去噪;多级退火征服高维非凸 | 真实(免训练用) | 真实状态 |
| 第 6 章 | 学习世界模型(本章) | 学 latent 模型 + 价值,短 horizon 有远见 | 学习的 latent | 学习的 latent |
盯住"动力学"和"规划空间"两列:前五章**全在真实动力学、真实状态空间**里做文章——它们改进的是"怎么采样、怎么加权、怎么退火",但始终假设有真实模型、在真实状态里 rollout。本章是第一次跳出真实空间——把动力学换成学习的 latent 模型、把规划搬进 latent 空间、再加学习的价值。
这个"跳出"是本章的根本新意,也是它的位置:前五章把"在真实空间里采样规划"做到了极致(从基础到变体到退火),本章则回答"如果不能或不愿用真实空间,能不能学一个 latent 空间来替代"。所以本章既是采样式 MPC 的延续(规划内核不变),又是它的一次质变(从真实空间到学习空间)。带着这个定位读下去,你会更清楚每一节在整条脉络里的意义。
把本章放进 model↔data 光谱:它在哪一端¶
上一章末尾我们画过一条"模型 ↔ 数据"光谱:一个方法关于任务"知道多少(靠模型)、有多少数据(靠学习)",决定了它落在光谱的哪个位置。回顾一下这条光谱,因为本章正好补上它的另一端。
光谱的**纯模型端**:方法完全靠已知的动力学和代价,不学任何东西。第 5 章的 MBD/DIAL-MPC 就在这一端——免训练、用已知模型算 score。它们的前提是"模型已知且写得清楚"。
光谱的**纯数据端**:方法完全靠数据学,不用任何已知模型。纯 model-free 的 Diffusion Policy、行为克隆在这一端——它们从演示数据学策略,不需要动力学方程。
本章的 TD-MPC 落在中间偏数据一侧:它**学一个模型**(latent 动力学 + 价值,从数据学),但学到模型后,它用的是**基于模型的规划**(采样 MPC)——所以它既不是纯 model-free(它有模型、会规划),也不是纯 model-based 经典方法(它的模型是学出来的、还融了价值学习)。它是 model-based 与 model-free 的一次深度融合。
本质洞察:把第 5 章和第 6 章并排,你会看到采样式 MPC 在 model↔data 光谱上的两种极端用法。第 5 章问:"如果我**完全知道**动力学和代价,怎么用采样把优化做到极致(免训练、算 score)?"——这是纯模型端的智慧。第 6 章问:"如果我**不知道或不愿用**真实动力学(太贵、是像素、没方程),能不能**学一个**模型来代替,再继续用采样规划?"——这是学习端的智慧。两章共享同一个采样规划内核(MPPI/CEM 的采样—rollout—更新),却因为"模型从哪来"这一个问题分居光谱两端:一端算、一端学。理解了这一点,你就不会把"扩散 MPC"和"TD-MPC"当成两个割裂的主题——它们是同一把采样规划之刀,在"已知模型"和"学习模型"两种处境下的不同握法。而决定你该用哪种握法的,永远是那个根本问题:关于这个任务,你的模型够不够好、数据够不够多。
一个常见困惑:TD-MPC 到底算 MPC 还是 RL¶
读到这里你可能已经困惑:TD-MPC 名字里有 MPC,又用了价值函数、TD learning 这些 RL 的东西,它到底算 MPC 还是 RL? 这个困惑很普遍,而答案能帮你看清它的本质——它两者都是,因为 MPC 和 model-based RL 在底层本就是同一件事的两种说法。
想想看:MPC(模型预测控制)的核心是"用一个模型预测未来、优化一段动作、滚动执行";model-based RL 的核心是"学一个环境模型、用它规划或想象来决策"。两者都围绕"用模型预测 + 优化决策"——区别只在传统侧重点不同:MPC 来自控制论,传统上模型是给定的(物理方程)、强调实时滚动优化;model-based RL 来自机器学习,强调模型是学出来的、强调样本效率和长期回报。但它们的内核是相通的。
TD-MPC 恰好站在这个交汇点上,把两边的精华都拿过来:它有 MPC 的"滚动时域 + 在线轨迹优化"(来自控制),又有 RL 的"学习的模型 + 价值函数 + TD learning"(来自机器学习)。 所以它既是一种 MPC(用模型做滚动优化),又是一种 model-based RL(学模型、学价值、最大化长期回报)。它的名字 "TD-MPC" 本身就点明了这个融合——TD(RL 的时序差分)+ MPC(控制的模型预测控制)。
理解这一点,你就不会纠结"它算哪一类",而能欣赏它的真正价值:它打通了控制(MPC)和机器学习(RL)两个传统上分离的领域。 对你(一个同时学过梯度式 MPC 和 RL 的工程师)尤其友好——你两边的知识在这里汇合,不必把它归到某一类、用单一视角去理解。这也是为什么本章既属于"采样式 MPC 系列"(它的规划是采样 MPC),又大量用到你的 RL 基础(价值、TD、SAC)。
一张图看清"换了哪两个零件"¶
为了让"学习世界模型 = 给采样 MPC 换两个零件"这个核心观念彻底落地,把 vanilla 采样 MPC 和 TD-MPC 的规划循环并排,看差异到底在哪:
| 规划循环的环节 | vanilla MPPI/CEM(第 2–4 章) | TD-MPC(本章) |
|---|---|---|
| 在什么空间规划 | 真实状态空间 | 学习的 latent 空间 |
| 采样什么 | 动作序列(高斯) | 动作序列(高斯)——不变 |
| 用什么 rollout | 真实动力学(仿真器/方程) | 学习的 latent 动力学 \(d_\theta\) |
| 每步代价/reward | 真实代价函数 | 学习的 reward 预测 \(r_\theta\) |
| 怎么更新分布 | 指数加权(MPPI)/精英平均(CEM) | 同左——不变 |
| horizon 末端怎么处理 | 直接截断(之后的回报丢失) | 加学习的终端价值 \(Q_\theta\) |
| 执行 | 第一个动作,滚动时域 | 同左——不变 |
盯住这张表的"不变"那几行:采样什么、怎么更新、怎么执行——采样规划的内核一行没改。 变的只有两处:一是用学习的 latent 动力学(+reward)替换真实动力学(补限制一:快、可批量、能吃像素),二是在 horizon 末端加一个学习的价值(补限制二:短 horizon 也有远见)。
这就是本章最该先记住的一句话:TD-MPC 不是一个全新的算法,而是把你已经会的采样规划,换上"学习的动力学"和"学习的终端价值"两个零件。 接下来几节就逐一拆解这两个零件:§6.2 讲学习的模型(动力学+价值)长什么样、为什么在 latent 空间,§6.3–§6.4 讲怎么用它规划、终端价值为什么是点睛之笔,§6.5 讲这套模型怎么训练出来。
为什么恰好是这两个零件、而非别的?因为它们精确对应 §6.1 开头的两个限制——这是一个干净的"问题→解法"闭环,值得最后再钉一遍。限制一是"rollout 依赖真实动力学(慢/贵/没有)",对应的零件就是"学习的 latent 动力学"——它快、可批量、能吃像素,从根上解除对真实动力学的依赖。限制二是"短 horizon 看不到长期(短视)",对应的零件就是"学习的终端价值"——它把 horizon 之外的长期回报估进来,让短 horizon 也有远见。两个限制、两个零件,一一对应,严丝合缝。
记住这个对应,你就抓住了本章的逻辑骨架:本章不是在堆砌"latent 模型""价值函数"这些时髦概念,而是在用最小的改动(换两个零件)精确解决采样式 MPC 的两个具体限制。 后面所有的技术细节(怎么学模型、怎么规划、怎么训练、怎么规模化),都是在落实这两个零件。每当你在后续小节里感到细节繁多、快要迷失时,回到这个"两限制、两零件"的骨架,就能重新看清每个细节在为哪个零件、解哪个限制服务。这是读懂本章的指南针。
⚠️ 常见陷阱¶
概念误区:以为 TD-MPC 是一种全新的、和 MPPI/CEM 无关的强化学习算法。 错误认识:看到"TD""价值函数""世界模型"这些 RL 术语,就把 TD-MPC 当成一个需要从头学的 RL 新方法,和前几章的采样式 MPC 没关系。 现象/后果:重复劳动地从零学它,看不出它的规划内核就是已经掌握的 MPPI/CEM,学习成本徒增;也难以把前几章的采样规划经验迁移过来。 根本原因:没看穿"TD-MPC = 采样规划内核 + 换两个零件(学习的 latent 动力学 + 学习的终端价值)"。它的"新"在于用学习的模型和价值,"不新"在于规划内核完全是你会的采样 MPC。 正确做法:把 TD-MPC 理解为"在学习的 latent 空间里跑 MPPI/CEM,末端加一个学习的价值"。前几章的采样规划直觉(warm-start、温度、精英、滚动时域)全部适用,新增的只是"模型和价值从数据学"这一层。
思维陷阱:以为"学习世界模型"总比"用真实模型"好(或总比它差)。 错误认识:要么觉得学个模型是更高级的做法、应该总用;要么觉得学的模型不如真实模型精确、不该用。 现象/后果:在有现成快模型的任务上费力学一个 latent 模型(多此一举、还引入误差),或在没有快模型/像素观测的任务上死守真实模型(根本行不通)而放弃采样 MPC。 根本原因:脱离"模型保真度 vs 速度/可学习性"这个权衡看问题。学习模型快、能吃像素、任务导向,但有误差、要数据、要训练;真实模型精确、不用训练,但可能慢、贵、或不存在。没有绝对的优劣。 正确做法:按任务选——有现成快模型且精度要紧 → 用真实模型(第 5 章那条线);模型贵/是像素/没方程、且有数据可学 → 学一个 latent 世界模型(本章)。这个权衡会贯穿全章(§6.8 还会回到它)。
练习¶
-
(辨析两个限制,⭐⭐) 用自己的话写出 vanilla 采样式 MPC 的两个限制,并各举一个会触发它的具体机器人任务。然后说明:TD-MPC 的"学习的 latent 动力学"和"学习的终端价值"分别补的是哪个限制?为什么 horizon 不能简单地靠"加长"来解决限制二?(提示:计算成本 + §6.8 会讲的累积误差。)
-
(光谱定位,⭐⭐,思考题) 在第 5 章的"模型 ↔ 数据"光谱上,给下列方法各标一个位置并说理由:(a) 第 5 章的 MBD(免训练扩散);(b) 本章的 TD-MPC;(c) 纯 model-free 的 SAC;(d) 行为克隆。然后回答:决定一个方法落在光谱哪个位置的根本问题是什么?
-
(设计判断,⭐⭐⭐,开放题) 给定三个任务,分别判断你会用"真实模型 + 采样 MPC"(第 5 章那条线)还是"学习世界模型 + 采样规划"(本章),并说清理由:(a) 一台动力学方程已知、要做精确轨迹跟踪的机械臂;(b) 一个只有摄像头像素输入、要学会操作的桌面机器人;(c) 一个有快速仿真器、但每个新任务 reward 都不同、想要一套通用控制器的场景。把你的判断和本节"模型保真度 vs 速度/可学习性"的权衡对照。
§6.2 TD-MPC 三组件架构:编码器、latent 动力学、价值 ⭐⭐⭐¶
动机:要"学一个世界模型",到底要学哪几样东西¶
§6.1 说 TD-MPC 给采样规划换了两个零件——学习的动力学和学习的价值。但要真正实现它,得把"学一个世界模型"拆成具体的几个网络:到底要学哪几样、各自负责什么?这一节就把这个架构拆开讲透。它是全章的地基——后面所有的规划(§6.3–§6.4)和训练(§6.5)都建立在这套架构上。
先从一个最朴素的需求倒推。采样规划要在 latent 空间 rollout 一条动作序列、算回报、末端加价值。为此它需要:(1) 把当前观测变成一个 latent 状态(编码器);(2) 在 latent 空间里,给定当前 latent 和一个动作,预测下一个 latent(latent 动力学);(3) 给定 latent 和动作,预测这一步的 reward(reward 预测);(4) 给定 latent(和动作),估计"从这里出发的长期价值"(价值函数)。这四样,就是 TD-MPC 世界模型的全部组件。
TD-MPC 把前三样(编码 + 动力学 + reward)合称为 TOLD(Task-Oriented Latent Dynamics,任务导向的 latent 动力学)模型,加上第四样价值函数,构成完整的世界模型。下面逐一拆解,重点回答两个"为什么":为什么在 latent 空间而非原始观测空间?为什么"任务导向"是关键?
组件一:编码器 \(h_\theta\)——把观测压成任务导向的 latent¶
编码器 \(h_\theta\) 做的事很直接:把原始观测 \(o\)(可能是低维状态向量,也可能是高维像素图像)映射成一个紧凑的 latent 向量 \(z = h_\theta(o)\)。
为什么要编码到 latent,而不直接在原始观测空间规划?这是 TD-MPC(以及一切 latent world model)最核心的设计决策,值得讲透,因为它直接回应了 §6.1 历史小节里"model-based 跑不赢 model-free"的第一个困境。
第一个理由:原始观测可能高维、含大量与决策无关的信息。 想象观测是一张摄像头图像(几万到几十万维像素)。在像素空间 rollout、规划,既维度爆炸、又荒谬——你不需要预测每个像素的未来值(背景的纹理、光照怎么变),你只需要预测"与完成任务相关的那些动态"。编码器把高维观测压成一个低维 latent(典型几十到几百维),过滤掉无关细节,只保留决策需要的信息。
第二个理由,也是 TD-MPC 的精髓——"任务导向"。 这里有一个微妙但关键的区别。早期 latent world model(如 PlaNet、Dreamer)的 latent 是"为了重建观测"而学的——latent 要能解码回原始图像,所以它必须编码图像里的一切(包括无关细节)。TD-MPC 反其道而行:它的 latent 不为重建观测服务,只为预测 reward 和价值服务。换句话说,latent 只需要编码"与任务回报相关"的信息,与回报无关的(背景、光照)可以完全丢弃。
读到这里你可能会问:不要求重建观测,那编码器靠什么学出有意义的 latent?万一它把所有观测都压成同一个点(平凡解)怎么办? 这是个很好的问题,答案藏在训练信号里:编码器是和动力学、reward、价值**联合训练**的,它的 latent 必须能让"动力学预测的下一 latent 准、reward 预测准、价值预测准"。这些任务相关的预测目标,逼着编码器学出"任务导向"的、有判别力的 latent,而不会塌成平凡解(§6.5 讲训练时会展开 latent 一致性损失如何防止塌缩)。
本质洞察:TOLD 模型"任务导向"四个字,是 TD-MPC 区别于早期 latent world model 的命门。早期方法学一个"通用"的世界模型——要能重建观测、什么都预测,结果容量被大量与决策无关的细节占用,反而学不好决策相关的动态。TD-MPC 认识到:做控制,根本不需要一个能重建世界的模型,只需要一个能预测"与回报相关的未来"的模型。 这是一种深刻的"少即是多"——主动放弃重建能力,把全部模型容量集中在"对决策有用"的信息上。这也解释了为什么 TD-MPC 能用相对小的模型达到好性能:它不浪费一丝容量在无关的重建上。这个"任务导向、只学有用的"的思想,远不止用于世界模型——它是一切表示学习里"为下游任务定制表示,而非追求通用重建"的智慧的体现。理解了它,你就理解了现代 model-based RL 从"重建式"到"任务导向式"这次关键转变的本质。
为了让"任务导向"从抽象变具象,举一个开车的例子。设想观测是车载摄像头的图像,任务是"沿车道行驶、不撞车"。这张图像里有海量信息:车道线、前方车辆、天空的云、路边的树、广告牌的文字、对向车道的细节……一个**重建式** latent(Dreamer 式)必须编码这一切——因为它要能重建出整张图像,包括云的形状和广告牌的字。但这些信息里,只有一小部分和"沿车道开、不撞车"相关:车道线的位置、前车的距离和速度、可行驶区域。云、树、广告牌的文字,对这个任务的决策毫无影响。
TD-MPC 的**任务导向** latent 只编码后者——它问的不是"怎么重建这张图",而是"这张图里,哪些信息影响我的 reward(开得好不好、有没有撞)和长期价值"。于是它把容量集中在车道线、障碍物、可行驶区域上,把云和广告牌彻底丢弃。同样一个 latent 维度预算,重建式要分给云和广告牌,任务导向式全给了决策相关的信息——后者自然学得更好、用得更省。
再举个抓取的例子。任务是"抓起桌上的杯子"。重建式 latent 要编码桌面的木纹、杯子上的图案、背景墙的颜色;任务导向 latent 只编码杯子的位置、朝向、抓取点、夹爪与杯子的相对关系。木纹和图案再复杂,对"怎么抓"没有影响,任务导向 latent 一概不管。这就是"少即是多"——主动丢弃无关信息,把模型容量花在刀刃上。
读到这里你可能会问:编码器对低维状态向量和高维像素图像,是同一个网络吗? 不完全是——编码器的**结构**会随观测类型变,但它的**角色和输出**一致。对低维状态观测(如关节角度、速度这样的向量),编码器就是一个 MLP,把状态向量映射到 latent。对高维像素观测(图像),编码器前面会接一个卷积网络(CNN)先提取视觉特征,再映射到 latent——因为 MLP 不适合直接处理图像的空间结构,CNN 才是。
但无论结构怎么变,编码器的角色不变:把观测(无论什么形式)压成一个统一的、任务导向的 latent。这正是 latent 空间的威力——它是一个"模态无关"的中间表示。状态观测进来、像素观测进来,编码器(用不同的前端结构)都把它们映射到同一个 latent 空间;之后的动力学、reward、价值都在这个统一的 latent 空间工作,完全不关心原始观测是状态还是像素。这也是为什么 TD-MPC 能用同一套框架处理状态任务和像素任务(TD-MPC 论文在 DMControl 和 Meta-World 的 state 和 image 两种观测上都验证了)——只需换一下编码器的前端(MLP 还是 CNN),后面全部复用。这个"编码器吸收模态差异、latent 之后统一"的设计,是 latent world model 通用性的又一个体现,也呼应了 §6.6 多任务里"统一接口吸收异构性"的思路。
组件二:latent 动力学 \(d_\theta\)——在 latent 空间预测未来¶
有了 latent,动力学 \(d_\theta\) 负责在 latent 空间里"往前推":给定当前 latent \(z\) 和一个动作 \(a\),预测下一个 latent \(z'\)。
注意这个预测**完全发生在 latent 空间**——输入是 latent,输出还是 latent,从头到尾不碰原始观测。这正是 §6.1 限制一的解药:rollout 时不需要真实仿真器、不需要解码回观测,只需要反复调用这个轻量的 latent 动力学网络。
为什么这样能快?因为 \(d_\theta\) 通常就是一个**小的多层感知机(MLP)**——输入是 latent 拼上动作,过两三层全连接,输出下一 latent。它规整(纯矩阵乘 + 激活)、可大批量并行(GPU 上一次推几千条 rollout)、维度可控(latent 维度你说了算)。对比一个真实物理仿真器:要做接触检测、碰撞求解、约束投影、隐式积分迭代,计算不规则、难以批量。所以 latent 动力学的单步 rollout 可以快到微秒级,且能在 GPU 上把成千上万条轨迹一起推——这是采样规划最需要的。
读到这里你可能会问:为什么动力学用简单的 MLP,而不用更"强大"的 RNN 或 Transformer? 这是个值得想的设计选择,背后有几层考量。
其一,规划要求极快、极规整。 规划时要批量 rollout 成千上万条轨迹、每条几步,对单步前向的速度极敏感。MLP 是最规整、最快、最易批量并行的网络——纯矩阵乘 + 激活,GPU 一次推完所有轨迹。RNN 有时序依赖(要按步展开、难以充分并行)、Transformer 有注意力(计算更重),都会拖慢规划。对"每步要推几千条"的采样规划,MLP 的简单和快是巨大优势。
其二,latent 已经吸收了"状态"信息,不需要 RNN 的记忆。 RNN 的价值在于维护一个隐状态、记住历史。但 TD-MPC 的 latent \(z\) 本身就是"当前状态的紧凑表示"——它已经编码了决策需要的信息,动力学只需"从当前 latent + 动作预测下一 latent",是一个**马尔可夫式的单步映射**,不需要额外的时序记忆。所以 MLP 够用,RNN 的记忆能力在这里是多余的。
其三,简单模型更好训、更稳、更省样本。 复杂网络(RNN/Transformer)参数多、更难训练、更吃数据、更易过拟合。TD-MPC 追求样本效率(§6.1),用简单的 MLP 更容易在有限数据上学好、训练也更稳定。这也呼应"任务导向、够用就好"的精神——不为复杂而复杂。
所以 MLP 不是"将就",而是匹配 TD-MPC 需求的恰当选择:规划要快(MLP 规整快)、latent 已马尔可夫(不需记忆)、要样本高效(简单模型好训)。当然,这不绝对——某些需要长时序记忆或复杂结构的任务,可能确实需要更复杂的动力学网络,这也是研究在探索的方向。但对 TD-MPC 覆盖的大多数连续控制任务,MLP 是恰到好处的选择。
在 TD-MPC2 里,这个动力学网络的输出还经过一个特殊的归一化激活 SimNorm(把 latent 分块、每块做 softmax 归一化),它能稳定 latent 的尺度、防止训练发散。这是个工程细节,§6.6 会讲,这里先知道"latent 动力学是个带特殊归一化的小 MLP"即可。
读到这里你可能会问:latent 动力学预测的 \(z'\),和"真实的下一观测编码出的 latent"一致吗?会不会预测得离谱? 这正是训练要保证的——TD-MPC 用一个 latent 一致性损失,逼 \(d_\theta(z,a)\) 预测的 latent 接近"真实下一观测 \(o'\) 编码出的 latent \(h_\theta(o')\)"(§6.5 详述)。但也要诚实:它只是"接近",每步仍有小误差,多步 rollout 会累积——这就是 §6.8 要讲的 compounding error,也是 TD-MPC 必须用短 horizon 的根本原因之一。
读到这里你可能会有个实践问题:latent 维度到底该设多大? 这是初学者上手时最常纠结的超参之一,给一个务实的回答。
原则是"任务导向地够用就好",而非越大越好(§6.2 末尾的陷阱会展开为什么不是越大越好)。具体地:latent 维度要**大到能编码所有与回报相关的信息,又不必大到去容纳无关细节**。一个直觉的参照——latent 维度通常和"任务的内在自由度"一个量级,而非和"观测维度"一个量级。比如一个像素观测(几万维)的抓取任务,其内在自由度(物体位姿、夹爪状态等)可能只有几十个,latent 设几十到一两百维往往就够,远小于观测维度。
实践上,TD-MPC2 单任务默认模型才 5M 参数、latent 维度也不大,照样在复杂任务上work。所以**从小默认值起步**(几十维),训练时监控 latent 一致性损失和任务性能——如果损失降不下去、性能上不来,可能是 latent 太小(编码不下必要信息),适当加大;如果训练慢、过拟合,可能太大,减小。多任务/更复杂的任务才需要更大的 latent 和模型(§6.6 的规模化)。记住:latent 维度服务于"任务导向的压缩",不是越大越好。
组件三:reward 预测 \(r_\theta\)——在 latent 空间估计每步回报¶
rollout 一条轨迹,光有状态序列不够,还要知道每步的 reward 才能算回报。reward 预测 \(r_\theta\) 就负责这个:给定 latent \(z\) 和动作 \(a\),预测这一步的 reward。
为什么 reward 也要"学",而不直接用真实 reward 函数?因为在 latent 空间 rollout 时,你手上只有预测出来的 latent \(z\),没有对应的真实观测——真实 reward 函数往往定义在真实状态/观测上,你无法对一个"想象出来的 latent"调用真实 reward 函数。所以必须学一个"latent 上的 reward 预测器",让 rollout 全程在 latent 空间自洽地进行。
在 TD-MPC2 里,reward 预测不是直接回归一个标量,而是用**离散回归**(把 reward 范围分成若干 bin,预测一个分布,再解码回标量)——这对不同任务差异巨大的 reward 量级更鲁棒。同样是 §6.6 的工程细节,这里知道"reward 也是 latent 上学出来的预测"即可。
组件四:价值函数 \(Q_\theta\)——把"horizon 之外的长期回报"压成一个数¶
前三个组件(编码 + 动力学 + reward)让你能在 latent 空间 rollout 一条 H 步轨迹、算出这 H 步的回报。但 §6.1 的限制二说了:H 步之后的长期回报,规划器看不到。第四个组件——价值函数 \(Q_\theta\)——就是来补这个的。
\(Q_\theta(z, a)\) 估计"在 latent 状态 \(z\) 下做动作 \(a\)、之后一直按某个策略走下去能拿到的期望折扣回报"。它把"从某个 latent 出发的、一直到无穷远未来的长期回报"压缩成一个数。于是规划器在 rollout 到 H 步末端的 latent \(z_H\) 时,不再直接截断(丢掉 H 之后的一切),而是加上 \(Q_\theta(z_H, a_H)\)——把"H 之后的长期回报"用这个学习的价值估进来。
这就是本章核心洞察的机制基础,§6.4 会专门展开。这里先建立架构上的认识:价值函数是世界模型的第四个组件,它的角色是"长期回报的代理",专门补短 horizon 看不到的那部分。
在实现上,TD-MPC 学的是**动作价值 \(Q_\theta(z,a)\)(而非状态价值 \(V\)),且仿照 SAC 用**多个 Q 网络的集成(TD-MPC2 用 num_q 个,带 dropout)来抑制价值过估计——从集成里取(随机两个的)较小/平均值。这些 RL 直觉(双 Q、集成防过估计)直接迁移,§6.5 训练时会讲。
读到这里你可能会问:为什么学动作价值 \(Q(z,a)\),而非状态价值 \(V(z)\)? 因为规划时要评估"在末端 latent 做某个具体动作"的价值——\(Q(z_H, a_H)\) 直接给出"在 \(z_H\) 做 \(a_H\) 之后的长期回报",正好是终端价值需要的形式。\(V(z)\) 只给"状态的价值"、不含动作信息,用它当终端价值还得额外处理"末端该选什么动作"。用 \(Q\) 更直接:末端选个动作(由 policy prior 给,§6.3)、查它的 \(Q\) 即可。这也和 SAC 等用 \(Q\) 的 actor-critic 方法一致,双 Q、集成等技巧都是为 \(Q\) 设计的,直接迁移。
小结一下价值这个组件的定位:它是世界模型四个组件里**唯一面向"长期"的**——编码器、动力学、reward 都是"局部/单步"的(编码当前、预测下一步、算这一步 reward),只有价值 \(Q_\theta\) 概括"从某状态出发的整个未来"。正是这个"唯一管长期"的组件,在规划时充当终端价值,补足了短 horizon 看不到的远期(§6.4)。记住这个分工——三个局部组件 + 一个长期组件——你就清楚了为什么规划时前 H 步用前三个组件 rollout、末端用价值收尾。
把四个组件拼起来:完整的世界模型¶
现在把四个组件拼成完整的 TD-MPC 世界模型,看数据怎么在它们之间流动:
观测 o ──[编码器 h_θ]──> latent z₀
│
┌─────────────────────┼─────────── 规划时反复用 ───────────┐
│ ▼ │
│ 给定动作 a: ┌──[reward r_θ]──> r̂ (这一步回报) │
│ 当前 latent z├──[动力学 d_θ]──> z' (下一 latent) │
│ └──[价值 Q_θ]────> Q (从这出发的长期价值) │
└──────────────────────────────────────────────────────────┘
四组件 = TOLD(编码 h_θ + 动力学 d_θ + reward r_θ) + 价值 Q_θ
读这张图,把它和 §6.1 那张"换两个零件"的表对上:编码器把观测领进 latent 空间,动力学 + reward 让你能在 latent 空间 rollout 算 H 步回报(替换了真实动力学和真实代价),价值在末端补长期(替换了直接截断)。四个组件各司其职,合起来就是一个"能在 latent 空间 rollout、算回报、估长期价值"的完整规划模型。
下面给出这套世界模型的最小结构代码(PyTorch 风格,对照 TD-MPC2 官方实现的核心结构),让架构落到具体:
import torch, torch.nn as nn
def mlp(in_dim, hidden, out_dim, act=None): # 一个通用小 MLP 工厂
layers = [nn.Linear(in_dim, hidden), nn.LayerNorm(hidden), nn.Mish(),
nn.Linear(hidden, hidden), nn.LayerNorm(hidden), nn.Mish(),
nn.Linear(hidden, out_dim)]
if act is not None: layers.append(act)
return nn.Sequential(*layers)
class WorldModel(nn.Module):
"""TD-MPC 世界模型: 编码器 + latent动力学 + reward + 价值(+策略prior)。"""
def __init__(self, obs_dim, act_dim, latent_dim=50, hidden=256, num_q=5):
super().__init__()
self.encoder = mlp(obs_dim, hidden, latent_dim) # h_θ: o -> z
self.dynamics = mlp(latent_dim + act_dim, hidden, latent_dim) # d_θ: (z,a) -> z'
self.reward = mlp(latent_dim + act_dim, hidden, 1) # r_θ: (z,a) -> r̂
self.pi = mlp(latent_dim, hidden, 2 * act_dim) # 策略prior(均值+logσ)
self.Qs = nn.ModuleList([mlp(latent_dim + act_dim, hidden, 1) # Q 集成(抑制过估计)
for _ in range(num_q)])
def encode(self, o): return self.encoder(o) # 观测 -> latent
def next(self, z, a): return self.dynamics(torch.cat([z, a], -1)) # latent rollout 一步
def reward_(self, z, a): return self.reward(torch.cat([z, a], -1)) # 预测这一步 reward
def Q(self, z, a): # 从 Q 集成取价值
qs = torch.stack([q(torch.cat([z, a], -1)) for q in self.Qs], 0)
idx = torch.randperm(len(self.Qs))[:2] # 随机取两个(双Q思想)
return qs[idx].min(0).values # 取较小值, 抑制过估计
这段代码刻意精简,但骨架和 TD-MPC2 官方实现一致:四个组件都是小 MLP(编码器、动力学、reward、价值),价值用集成 + 取较小值。next 就是 latent rollout 的一步、Q 就是终端价值的来源——下一节 §6.3 的规划循环会反复调用这两个方法。
为了让这套架构彻底落地,用一个具体的抓取场景走一遍数据流,看四个组件在规划时如何协作。设想机器人要抓桌上的杯子,当前摄像头拍到一张图像,规划器想评估"夹爪向左移动一点"这个动作好不好:
- 编码:图像 \(o\) 进编码器 \(h_\theta\),输出一个比如 64 维的 latent \(z_0\)——它编码了杯子位置、夹爪状态等任务相关信息(不含背景木纹)。
- rollout 第一步:把 \(z_0\) 和动作"左移"\(a_0\) 喂给动力学 \(d_\theta\),得到下一 latent \(z_1\)(预测"左移后的状态表示");同时喂给 reward 预测 \(r_\theta\),得到这一步 reward \(\hat r_0\)(比如"离杯子更近了,+0.1")。
- 继续 rollout:把 \(z_1\) 和下一个动作 \(a_1\) 再喂给 \(d_\theta\)、\(r_\theta\),得到 \(z_2\)、\(\hat r_1\)……重复 \(H\) 步(比如 H=3),得到 \(z_3\) 和三步的 reward。
- 终端价值:到末端 latent \(z_3\),调价值 \(Q_\theta(z_3, a_3)\),估计"从 \(z_3\) 出发的长期价值"(比如"再走几步就能抓到,长期价值 +3.0")。
- 算总回报:\(G = \hat r_0 + \gamma \hat r_1 + \gamma^2 \hat r_2 + \gamma^3 Q_\theta(z_3,a_3)\),这就是"左移"这条动作序列的评分。
规划器对成百上千条候选动作序列都这样算一遍(全部在 latent 空间、批量并行),选出评分高的、精炼、执行第一个动作。全程图像只在第 1 步出现一次,之后都在 latent 空间。这一遍走下来,四个组件的协作就具体了:编码器开门(进 latent),动力学和 reward 负责 rollout(推演眼前),价值负责收尾(估长期)。
本质洞察:TD-MPC 的世界模型,本质是把"环境"这个黑箱拆成了四个可学习、可微、可快速前向的小网络。这个拆解的精妙之处在于**职责的清晰分离**:编码器管"什么信息相关",动力学管"状态怎么演化",reward 管"每步多好",价值管"长期多好"。每个组件都小、都快、都只干一件事,合起来却覆盖了规划所需的全部信息。这种"把复杂系统拆成职责单一的小模块"的设计,和软件工程里的单一职责原则、和你在前几章见过的"统一框架 + 正交维度"是同一种智慧。更深一层:这四个组件不是孤立训练的,而是**联合训练、互相约束**(§6.5)——编码器学出的 latent 要同时让动力学、reward、价值都好预测,这种联合约束正是它们能协同工作的保证。理解"拆成四个小网络 + 联合训练"这个架构,你就握住了 TD-MPC 的骨架,剩下的规划和训练都是在这副骨架上做文章。
⚠️ 常见陷阱¶
概念误区:以为 TD-MPC 的 latent 模型像 Dreamer/PlaNet 那样要能重建观测。 错误认识:既然是"世界模型",就以为它要能从 latent 解码回原始观测(图像/状态),像自编码器那样。 现象/后果:误以为 TD-MPC 要训一个重型的解码器、要做像素重建,从而高估它的复杂度和训练难度;也抓不住它"任务导向"的精髓。 根本原因:混淆了"重建式世界模型"(PlaNet/Dreamer,latent 要能重建观测)和"任务导向世界模型"(TD-MPC,latent 只为预测 reward/价值服务,不重建观测)。TD-MPC(尤其 TD-MPC2 的 implicit world model)没有解码器,latent 不重建任何东西。 正确做法:把 TD-MPC 的 latent 理解为"为决策定制的紧凑表示"——它只编码与回报相关的信息,靠联合训练(动力学/reward/价值预测 + latent 一致性)学出,不靠重建。这是它比重建式模型更高效的原因。
编程陷阱:在 latent 空间 rollout 时,错误地每步都解码回观测、或调用真实 reward 函数。
错误做法:实现 rollout 时,每步把预测的 latent 解码回观测,再用真实 reward 函数算 reward;或试图把 latent 转回真实状态去调真实动力学。
现象/后果:彻底丢掉了 latent rollout"快、自洽"的全部优势,退化成"在观测空间 rollout"(慢、且需要真实模型),TD-MPC 的意义荡然无存;若没有解码器/真实模型,代码直接报错或无法运行。
根本原因:没理解 latent rollout 的核心是"全程在 latent 空间自洽进行"——用学习的动力学 \(d_\theta\) 推 latent、用学习的 reward \(r_\theta\) 在 latent 上算 reward,从不回到观测空间。
正确做法:rollout 循环里只调用 next(z,a)(latent 推进)和 reward_(z,a)(latent 上的 reward 预测),末端调 Q(z,a)(latent 上的价值),全程不解码、不碰真实模型。这正是 §6.3 plan 算法的写法。
思维陷阱:以为 latent 维度越大、模型越大,世界模型就越准越好。 错误认识:既然 latent 要编码信息,那维度越大能编码越多、模型越大越准,应该尽量大。 现象/后果:用过大的 latent 维度和模型,训练慢、易过拟合、规划时 rollout 也变慢,未必更好;也违背了"任务导向、只学有用信息"的精神。 根本原因:latent 的价值在于"任务导向地压缩"——它要的是"恰好够编码决策相关信息"的维度,不是越大越好。过大的 latent 会重新引入"编码无关信息"的浪费,且增加训练和规划成本。TD-MPC2 单任务默认模型才 5M 参数、latent 维度也不大,照样работает。 正确做法:latent 维度和模型大小按任务复杂度选,从小默认值起步(TD-MPC2 单任务默认 5M 参数),不够再加。记住"任务导向"意味着"够用就好",而非"越大越好"——多任务/复杂任务才需要更大模型(§6.6 的规模化)。
练习¶
-
(架构梳理,⭐⭐) 不看正文,画出 TD-MPC 世界模型的四个组件及数据流:观测如何变成 latent、规划时如何在 latent 空间 rollout(用到哪几个组件)、末端如何估长期价值。然后标注:哪些组件在规划的每一步都被调用、哪个只在末端调用?
-
(为什么任务导向,⭐⭐⭐,思考题) TD-MPC 的 latent "不重建观测、只为预测 reward/价值服务"。请论证:(a) 对一个以像素为观测的任务,"重建式 latent"(要能重建图像)和"任务导向 latent"(只编码回报相关信息)会把模型容量花在哪些不同的地方?(b) 为什么"任务导向"对样本效率和性能更友好?(c) 这种"为下游任务定制表示、放弃通用重建"的思想,你在别的机器学习场景见过吗(举一个例子)?
-
(最小实现,⭐⭐⭐) 基于本节的
WorldModel骨架代码,补全一个rollout(z0, actions)方法:给定初始 latentz0和一个动作序列actions(形状(H, act_dim)),在 latent 空间 rollout,返回每步的预测 reward 和末端 latent。确认你的实现全程不解码回观测、不调用任何真实模型。然后思考:如果把actions扩成(K, H, act_dim)(K 条序列并行),你的代码要怎么改才能批量 rollout?(这正是 §6.3 采样规划要做的。)
§6.3 在 latent 空间做采样规划:把熟悉的 MPPI/CEM 搬进来 ⭐⭐⭐¶
动机:有了世界模型,怎么用它做决策¶
§6.2 我们有了一个学好的世界模型(编码 + 动力学 + reward + 价值)。但模型本身不会做决策——它只是个"能预测未来"的工具。怎么用它选出当前该执行的动作?答案是你已经非常熟悉的:采样规划。这一节把第 2–4 章的 MPPI/CEM 搬进 latent 空间,你会发现规划循环几乎一字不变,只是 rollout 的地方换成了 latent 动力学、末端加了价值。
先把目标说清楚:给定当前观测 \(o\),规划器要输出"当前该执行的动作 \(a_0\)"。它的做法和 vanilla 采样 MPC 完全一致——在动作序列空间里采样、用模型 rollout 评估、迭代精炼出一个好的动作序列、执行它的第一个动作、下个周期重来(滚动时域)。唯一的不同是:rollout 在 latent 空间用学习的动力学进行,末端加学习的价值。
为什么"在 latent 空间规划"是值得的:快、可批量、自洽¶
在展开算法前,先把"为什么值得搬进 latent 空间"这件事讲透——这是 §6.1 限制一的正面回答。
第一,latent 动力学 rollout 极快。 如 §6.2 所说,latent 动力学 \(d_\theta\) 是个小 MLP,单步前向只是几次矩阵乘 + 激活。对比真实物理 rollout 要做的接触检测、碰撞求解、隐式积分迭代,latent 一步可以快几个数量级。采样规划每周期要 rollout 成千上万条 × 几十步,这个速度差异直接决定了"能不能实时"。
第二,latent rollout 天然可大批量并行。 latent 动力学是规整的矩阵运算,把 \(K\) 条 rollout 的 latent 堆成一个 \((K, \text{latent dim})\) 的张量,一次矩阵乘就推进所有 \(K\) 条——这正是 GPU 最擅长的。对比真实仿真器:很多仿真器难以高效批量(每个样本要单独跑物理引擎),并行度受限。latent 模型让"采几千条 rollout"这件事在 GPU 上几乎免费。
第三,latent rollout 自洽、不依赖外部模型。 整个 rollout 全程在 latent 空间用学习的网络进行——编码一次得到初始 latent,之后反复调 \(d_\theta\) 推进、调 \(r_\theta\) 算 reward、末端调 \(Q_\theta\) 估价值,从头到尾不需要真实仿真器、不需要解码回观测。这意味着即便你**没有真实动力学**(像素观测、无方程),只要学好了世界模型,照样能规划——这是 vanilla 采样 MPC 做不到的。
这第三点里"能吃像素"的能力,值得单独说透,因为它是 latent 规划最独特、也最容易被低估的优势。设想观测是摄像头图像。vanilla 采样 MPC 要在"图像空间"rollout——可你没有"图像的动力学方程"(给定当前图像和一个动作,下一帧图像是什么?没有解析模型能算)。即便有个能渲染图像的仿真器,在几万维的像素空间里采样、rollout、算回报也荒谬地昂贵。所以 vanilla 采样 MPC 根本无法直接处理像素观测——这是它一个硬性的能力边界。
latent 规划优雅地绕过了这堵墙:编码器先把图像压成低维 latent(一次前向),之后所有 rollout、规划全在 latent 空间进行——而 latent 空间有学好的动力学(\(d_\theta\)),可以快速 rollout。像素只在"编码进 latent"那一步出现一次,之后再不碰像素。 于是"在像素上规划"这个不可能的任务,被转化成了"在 latent 上规划"这个可行的任务。这就是为什么 TD-MPC 能直接从摄像头学控制,而经典采样 MPC 不能——它把规划从"无法建模的像素空间"搬到了"学出来的、可建模的 latent 空间"。这一能力,是学习世界模型给采样式 MPC 带来的最大疆域扩展。
读到这里你可能会问:latent 快、可批量我懂,但 latent rollout 准吗?用一个有误差的学习模型 rollout,规划会不会被带偏? 会有这个风险,而这正是 TD-MPC 用**短 horizon**(典型 H=3~5)的根本原因之一——短 rollout 让 latent 动力学的累积误差还没长大就停下,再用学习的价值补长期(§6.4)。所以"latent 规划"和"短 horizon + 价值"是配套的设计:latent 让 rollout 快、短 horizon 让 rollout 准、价值补长期信息——三者环环相扣,这也是为什么本章把它们放在相邻的小节里讲(§6.4 末尾会专门剖析这个协同)。
还有一个值得点明的反直觉点:用一个有误差的学习模型规划,为什么实践中不会被模型误差彻底带偏? TD-MPC 其实有三重保险护着它,理解这三重能让你更放心地用学习模型规划。
第一重,短 horizon 限制误差。 rollout 只 3~5 步,模型误差还没累积大就停下(§6.4、§6.8)——误差被限制在可控范围。
第二重,滚动时域不断纠错。 TD-MPC 是滚动时域的——每个控制周期都用**真实的新观测**重新编码、重新规划。即便上一周期因模型误差选了略偏的动作,执行后得到真实的新观测,下一周期从这个真实观测重新出发规划,误差不会无限累积。真实观测像一个"锚",每一步把规划拉回现实,防止它在想象里越飘越远。这是 MPC 滚动时域的精髓在 TD-MPC 里的体现——它天然对模型误差有纠错能力。
第三重,价值提供全局兜底。 即便短 rollout 有点偏,学习的价值(从大量真实数据学来)提供了一个相对稳定的长期判断,不会因几步 rollout 的小误差而剧变。
三重合起来,让"用有误差的模型规划"在实践中相当鲁棒——短 horizon 限制误差、滚动重规划不断纠错、价值全局兜底。这也解释了为什么 TD-MPC 虽然用学习模型(有 compounding error 的原罪,§6.8),实际却能稳定 work:它的设计处处在"与模型误差共处",而非奢望一个完美模型。当然,三重保险不是万能的(OOD 等情况仍会出问题,§6.8),但它们让 TD-MPC 在大多数任务上对模型误差有足够的容忍度。
理论:TD-MPC 的 plan 算法逐行解¶
现在给出 TD-MPC 的完整规划算法。它本质是一个 CEM/MPPI 式的采样优化器(TD-MPC 实际用接近 CEM 的精英更新,TD-MPC2 用的 MPPI 式加权出自 Williams 等 2015 的路径积分控制——正是你第 2 章学过的那个 MPPI,两者都属采样优化),在 latent 空间迭代精炼一个动作序列上的高斯分布:
def plan(obs, prev_mean, model, H=5, K=512, iters=6, num_elites=64,
num_pi_trajs=24, gamma=0.99, temperature=0.5):
"""TD-MPC 在 latent 空间的采样规划。返回当前要执行的动作。"""
z = model.encode(obs) # 1. 编码: 观测 -> 初始 latent
mean = shift(prev_mean) # 2. warm-start: 上周期解平移一格
std = torch.ones(H, action_dim) * 0.5 # 初始标准差
for i in range(iters): # 3. 采样优化迭代(CEM/MPPI 式)
# 3a. 采 K 条动作序列: 一部分来自高斯, 一部分来自 policy prior
noise = torch.randn(K - num_pi_trajs, H, action_dim) * std
sampled = (mean.unsqueeze(0) + noise).clamp(-1, 1)
pi_actions = rollout_policy_prior(model, z, H) # 从学习的策略采 num_pi_trajs 条
actions = torch.cat([sampled, pi_actions], dim=0) # (K, H, action_dim)
# 3b. 在 latent 空间并行 rollout K 条, 累积折扣 reward
z_k = z.unsqueeze(0).expand(K, -1) # (K, latent_dim) 初始 latent 复制 K 份
G = torch.zeros(K) # 每条的累积回报
discount = 1.0
for t in range(H):
G += discount * model.reward_(z_k, actions[:, t]).squeeze(-1) # 这一步 reward
z_k = model.next(z_k, actions[:, t]) # latent 推进一步
discount *= gamma
# 3c. 终端价值: 用学习的 Q 估计 horizon 之后的长期回报(本章核心, §6.4 展开)
a_H = model.pi_action(z_k) # 末端 latent 处策略选的动作
G += discount * model.Q(z_k, a_H).squeeze(-1) # 加终端价值
# 3d. 用回报更新分布: 取精英(CEM) 或指数加权(MPPI)
elite_idx = G.topk(num_elites).indices
elite_actions = actions[elite_idx] # (num_elites, H, action_dim)
elite_G = G[elite_idx]
w = torch.softmax(elite_G / temperature, dim=0) # MPPI 式权重(温度控制软硬)
mean = (w.view(-1,1,1) * elite_actions).sum(0) # 加权均值
std = torch.sqrt((w.view(-1,1,1) *
(elite_actions - mean.unsqueeze(0))**2).sum(0)).clamp(min=0.05)
return mean[0] # 4. 执行第一个动作(滚动时域)
逐段读这个算法,把它和你熟悉的 MPPI/CEM 对照:
第 1 步 编码:把当前观测编码成初始 latent \(z\)。这是 latent 规划独有的一步——vanilla MPPI 直接在真实状态上规划,没有这步。之后整个规划都在 latent 空间。
第 2 步 warm-start:用上一控制周期的解平移一格作为本周期的初始均值。这和第 2 章 MPC 的 warm-start 完全一致——利用相邻周期解的连续性,减少所需迭代。
第 3 步 采样优化迭代,这是核心循环,分四小步:
- 3a 采样:采 \(K\) 条动作序列。注意 TD-MPC 的一个特色——不是全从高斯采,而是**一部分(num_pi_trajs 条)从学习的 policy prior 采**。这个"策略先验"提供"好动作大概长什么样"的引导,加速收敛(下面专门讲)。
- 3b latent rollout:把初始 latent 复制 \(K\) 份,并行 rollout \(H\) 步——每步用 \(r_\theta\) 算 reward 累积、用 \(d_\theta\) 推进 latent。全程在 latent 空间,向量化批量进行。这就是 §6.2 那个"换零件"的现场:rollout 用的是学习的 latent 动力学,reward 用的是学习的 reward 预测。
- 3c 终端价值:rollout 到末端 latent \(z_H\) 后,加上 \(\gamma^H Q_\theta(z_H, a_H)\)——这就是本章核心洞察的代码落点,把 horizon 之外的长期回报用学习的价值估进来。§6.4 会专门展开它为什么是点睛之笔。
- 3d 更新分布:用回报选精英(CEM)或做指数加权(MPPI),更新高斯的均值和标准差。这和第 2–4 章一字不差——温度 temperature 控制权重软硬、std.clamp(min=0.05) 防止标准差塌到零(保持最低探索)。
第 4 步 执行:返回精炼后动作序列的第一个动作,执行它。下个周期用本周期的 mean 做 warm-start,重来——滚动时域。
把这个算法和第 2 章的 vanilla MPPI 并排,你会看到**结构完全同构**:都是"采样—rollout—算回报—更新分布—迭代—执行第一个"。差异只有三处,全是 §6.1 那张表里标的"换零件":rollout 在 latent 空间(用 \(d_\theta/r_\theta\))、末端加价值(\(Q_\theta\))、采样掺入 policy prior。内核没变,这就是为什么说"TD-MPC 的规划就是你已经会的采样 MPC"。
读到这里你可能会问:采样优化只迭代 6 次(默认值),这么少够吗?vanilla MPPI 也是这么少吗? 这个问题的答案揭示了 TD-MPC 规划为什么能实时。6 次迭代确实少,但 TD-MPC 有两个"加速器"让它够用:
加速器一:policy prior 提供好起点。 纯高斯采样要从零摸索,需要很多次迭代才能找到好区域。但 TD-MPC 每次都掺入 policy prior 采的轨迹(§6.3)——这些轨迹已经"大致合理",相当于规划从一个接近最优的起点出发,几次迭代就能精修到位,不必从零慢慢搜。
加速器二:warm-start 利用上周期的解。 滚动时域里相邻周期解高度相似,warm-start 让本周期从"上周期解的平移"出发(上面刚讲过)——又是一个好起点,进一步减少所需迭代。
两个加速器合起来,让 6 次迭代足以收敛到好解。这对实时性至关重要:每个控制周期要在几毫秒到几十毫秒内完成规划,迭代次数必须少。如果像 vanilla MPPI 那样冷启动、纯高斯采样,可能需要更多迭代才能达到同等质量。所以 TD-MPC 的"少迭代也够"不是凑合,而是 policy prior 和 warm-start 这两个好起点换来的——它们用"学习的先验"和"时序连续性"把搜索起点抬高了,于是少量迭代就够。 这再次体现了 §6.3 那个"摊销给起点、规划做精修"的思想:好起点(摊销)让在线精修(规划)的负担大大减轻。
warm-start:在 latent 规划里同样关键¶
plan 算法第 2 步的 warm-start 值得多说一句,因为它直接承接了你在第 2 章学过的 MPC 思想,且在 TD-MPC 里同样重要。
回忆 MPC 的滚动时域:每个控制周期重新规划,但只执行第一个动作,下个周期重来。相邻周期的最优动作序列通常高度相似——这周期规划出 \([a_0, a_1, \dots, a_{H-1}]\),执行 \(a_0\) 后,下周期的好起点很可能是 \([a_1, a_2, \dots, a_{H-1}, a_{\text{new}}]\)(把这周期的解平移一格,末尾补一个新动作)。warm-start 就是用上周期的解平移作为本周期的初始均值,而非每次从零(高斯零均值)开始。
在 TD-MPC 里,warm-start 的价值和 vanilla MPC 一样——甚至更重要。因为 TD-MPC 的规划迭代次数有限(默认 6 次,受实时约束),从一个好起点出发能让有限的迭代更快收敛到好解。如果每周期都冷启动(零均值),6 次迭代可能不够把分布从零优化到好区域;而 warm-start 给了一个已经接近最优的起点,6 次迭代足以精修。
读到这里你可能会问:warm-start 平移后,末尾那个新补的动作怎么初始化? 和第 2 章一样,常见做法是复制平移后的最后一个动作,或用 policy prior 在末端 latent 处给一个动作。这个细节看似小,但若处理不当(比如末尾补一个乱七八糟的动作),会在滚动中逐渐污染轨迹。TD-MPC 实现里通常把 _prev_mean 平移、末尾补合理值,确保 warm-start 平滑。这也呼应了第 2 章 warm-start 的同款提醒——平移是利用相邻周期的连续性,但新生的末尾格要妥善处理。
policy prior:为什么采样要掺入"学习的策略"¶
上面提到 TD-MPC 的采样不全从高斯来,而是掺入一部分从 policy prior(策略先验) 采的轨迹。这是个值得专门讲的设计,它也是 TD-MPC 融合 model-free 思想的一个体现。
policy prior 是一个学习的策略网络 \(\pi_\theta(z)\):给定 latent,输出一个动作分布(均值 + 标准差)。它和价值函数一起训练(§6.5),学的是"在当前 latent 下,好动作大概是什么"。
为什么规划要掺入它采的轨迹?回忆第 5 章末尾提过的"learned prior"思想——纯高斯采样是"盲目"的,它不知道什么动作合理,要靠大量采样 + 迭代才能找到好区域。而 policy prior 提供了一个**有信息的起点**:它采出的轨迹已经是"大致合理"的动作(因为策略学过),规划器在这些好轨迹附近精炼,收敛快得多。
具体地,num_pi_trajs 条来自 policy prior、其余 K - num_pi_trajs 条来自当前高斯分布。两者混在一起评估、更新。这样既有 policy prior 的"有信息引导"(快速找到好区域),又有高斯采样的"局部探索"(在好区域附近精修、且不被策略的偏差锁死)。
本质洞察:TD-MPC 的 policy prior,揭示了"规划"和"学策略"如何相辅相成,而非二选一。纯采样规划(vanilla MPPI)是"即时优化"——每次从零搜索,不积累经验;纯 model-free 策略是"摊销优化"——把"好动作"固化进一个网络,推理快但不在线优化。TD-MPC 把两者缝合:用学习的策略 prior 提供"好动作大概在哪"的摊销经验,用在线采样规划在此基础上做即时精炼。 策略负责"快速给个好的起点",规划负责"在起点附近精益求精"。这种"摊销 + 即时"的双层结构,比任何单一方式都强——它既有策略的快、又有规划的准。更深一层,这也呼应了第 5 章的 learned prior 路线(数据先验 + 在线精炼):无论是扩散 MPC 还是 TD-MPC,"用学习的先验引导采样、用在线优化保证质量"都是同一个高明的组合拳。理解了这一点,你看任何"学习 + 规划"的混合方法,都能一眼认出这个"摊销给起点、规划做精修"的骨架。
与 vanilla MPPI 的对照表¶
把 TD-MPC 的 latent 规划和第 2–4 章的 vanilla 采样 MPC 系统对照一次,巩固"换零件"的认识:
| 维度 | vanilla MPPI/CEM | TD-MPC latent 规划 |
|---|---|---|
| 规划空间 | 真实状态空间 | 学习的 latent 空间 |
| 起始 | 直接用当前真实状态 | 先编码:\(z = h_\theta(o)\) |
| rollout 动力学 | 真实仿真器/方程 | 学习的 \(d_\theta\)(快、可批量) |
| 每步 reward | 真实代价函数 | 学习的 \(r_\theta\)(latent 上) |
| 采样来源 | 纯高斯 | 高斯 + policy prior 混合 |
| 终端处理 | 直接截断 | 加学习的价值 \(Q_\theta\) |
| horizon | 较长(30~100) | 很短(3~5,靠价值补长期) |
| 更新规则 | 指数加权/精英 | 同左(不变) |
| warm-start | 有 | 有(不变) |
| 执行 | 第一个动作,滚动时域 | 同左(不变) |
盯住"更新规则、warm-start、执行"这几行的"不变"——再次确认采样规划内核原封未动。真正的差异集中在"规划空间、rollout、终端、horizon"上,而它们都服务于一个目的:用学习的 latent 模型 + 学习的价值,绕开 vanilla 采样 MPC 的两个限制。
这个"内核不变"对你有一个很实际的好处:前几章积累的所有采样规划经验,在 TD-MPC 里直接可用。 你在第 2–4 章学的温度怎么调(探索-利用权衡)、精英比例怎么选、warm-start 怎么做、ESS 怎么监控、为什么标准差要设下限——这些经验一字不改地适用于 latent 规划,因为它的更新规则、warm-start、执行逻辑和 vanilla 采样 MPC 完全一样。你唯一要新学的,是"模型和价值从数据学"这一层(§6.5)和"在 latent 空间而非真实空间"这个变化。换句话说,学 TD-MPC 的规划部分,你的边际学习成本很低——大部分是已有知识的迁移,新东西集中且明确。这正是"看穿它就是换零件的采样 MPC"带来的学习红利。
⚠️ 常见陷阱¶
编程陷阱:latent rollout 没有向量化,用 Python 循环逐条 rollout K 条轨迹。
错误做法:用一个 for k in range(K) 外层循环,逐条 rollout 每条动作序列。
现象/后果:彻底浪费了 latent 动力学"可大批量并行"的核心优势,规划慢几个数量级,实时性崩溃——latent 规划"快"的全部意义荡然无存。
根本原因:没利用 latent 动力学是规整矩阵运算这一点。\(K\) 条 rollout 的 latent 可以堆成 \((K, \text{latent dim})\) 张量,一次矩阵乘推进所有条,这正是 GPU 擅长的。
正确做法:把初始 latent 复制 \(K\) 份成 batch(z.expand(K, -1)),rollout 循环只沿 horizon 维度(\(H\) 步)走,每步对整个 batch 做一次 next/reward_。横向的 \(K\) 条永远批量、并行,只有纵向的 \(H\) 步串行——这正是本节 plan 代码的写法。
概念误区:以为 TD-MPC 的规划是纯 MPPI,或纯 CEM,必须二选一。
错误认识:纠结 TD-MPC 到底用 MPPI 还是 CEM,以为它们是互斥的两种规划器。
现象/后果:实现时困惑该用指数加权还是硬精英截断,或误以为换一种就不是 TD-MPC 了。
根本原因:MPPI 和 CEM 都属"采样优化"大家族(第 4 章统一视角讲过),区别只在"怎么用回报更新分布"——MPPI 用指数加权(软)、CEM 用精英截断(硬)。TD-MPC 原版接近 CEM、TD-MPC2 用 MPPI 式加权,但它们的框架(latent rollout + 终端价值 + 迭代)完全一样,更新规则是可换的细节。
正确做法:把更新规则当成一个可配置的"旋钮"(呼应第 4 章累积项目的 weight 维度)——用 MPPI 式加权还是 CEM 式精英,都行,框架不变。重要的是 latent rollout + 终端价值这个骨架,而非更新规则的具体选择。
思维陷阱:以为 policy prior 可有可无,纯高斯采样也一样。 错误认识:既然有采样优化迭代,纯高斯采样多迭代几轮也能找到好动作,policy prior 是多余的。 现象/后果:去掉 policy prior,规划收敛慢、需要更多采样和迭代才能达到同等质量,尤其在高维动作空间或迭代次数受限(实时约束)时性能明显下降。 根本原因:纯高斯采样是"盲目"的,不知道什么动作合理;policy prior 提供"好动作大概在哪"的有信息引导,让规划从一个好起点出发、快速收敛。在实时约束下迭代次数有限,好起点尤其关键。 正确做法:保留 policy prior(它和价值一起训练,几乎免费),用它提供一部分有信息的采样起点,再用高斯采样做局部探索。这是 TD-MPC "摊销 + 即时"双层结构的关键一半,不是可有可无的装饰。
练习¶
-
(plan 算法精读,⭐⭐) 对照本节 plan 代码与第 2 章的 vanilla MPPI,逐行标出:哪几行是 latent 规划独有的(vanilla 没有)、哪几行和 vanilla 完全一样。特别说明:编码、latent rollout、终端价值、policy prior 混合各对应哪几行,它们分别解决 §6.1 的哪个限制。
-
(批量 rollout 实现,⭐⭐⭐) 基于 §6.2 练习 3 的单条 rollout,把它改成批量版:输入
actions形状(K, H, act_dim),初始 latentz0复制成(K, latent_dim),沿 horizon 维度 rollout,返回每条的累积折扣 reward(K,)和末端 latent(K, latent_dim)。确认你的实现里 \(K\) 条永远批量、只有 \(H\) 步串行。然后加上终端价值:用model.Q给每条加 \(\gamma^H Q(z_H, a_H)\)。 -
(policy prior 的作用,⭐⭐⭐,思考题) TD-MPC 的采样掺入 policy prior。请论证:(a) policy prior 和纯高斯采样各自的优劣是什么(用"盲目探索 vs 有信息引导"的语言)?(b) 为什么"混合"比"纯用其中一种"好?(c) 这种"学习的先验 + 在线采样精炼"的组合,和第 5 章末尾的 learned prior 路线(数据先验 + 扩散精炼)在思想上有什么共通之处?(d) 如果 policy prior 学得很差(早期训练),混合它会不会害了规划?TD-MPC 靠什么避免被坏 prior 带偏?(提示:高斯采样那部分仍在做独立探索。)
§6.4 价值作终端代价:短 horizon + 学习的长期价值 ⭐⭐⭐¶
动机:这是全章最该带走的一个洞察¶
前面铺垫的一切——学习的 latent 模型、latent 空间规划——都是为了这一节。如果说本章只有一个观念值得你记住,就是这一节的核心洞察:用一个学习的价值函数作终端代价,能让"短 horizon 的采样规划"获得"长 horizon 的远见"。 这一招同时绕开了 §6.1 的限制二(短 horizon 短视)和 §6.8 将讲的累积误差(长 rollout 失真),是 TD-MPC 设计里最精妙的一步。这一节用一个亲手验证的 demo 把它演示到无可辩驳。
先把问题摆清。§6.1 说短 horizon 看不到长期、决策短视。直觉的修法是"加长 horizon"。但加长有两个代价:计算成本线性增长,以及(用学习模型时)rollout 越长累积误差越大(§6.8)。所以"加长 horizon"这条路走不通——它又慢又失真。TD-MPC 的答案完全不同:不加长 horizon,而是在短 horizon 的末端,加一个学习的价值,把"horizon 之外的长期回报"一次性估进来。
理论:终端价值如何把"无穷远未来"塞进短 horizon¶
回忆 §6.3 plan 算法里那行终端价值。规划器 rollout \(H\) 步,算出这 \(H\) 步的折扣回报,然后在末端 latent \(z_H\) 处加上:
读这个式子,它把一条轨迹的总回报拆成两段。**第一段**是 rollout 实打实算出的前 \(H\) 步折扣回报——这部分靠 latent 动力学和 reward 预测。**第二段**是关键:\(\gamma^H Q_\theta(z_H, a_H)\),它用学习的价值函数估计"从末端 latent \(z_H\) 出发、之后一直走下去能拿到的长期回报"。
为什么这一项能"补足长期信息"?回忆价值函数的定义——\(Q_\theta(z_H, a_H)\) 估计的正是"从 \(z_H\) 做 \(a_H\) 之后的期望折扣回报,一直到无穷远未来"。所以这一项把"\(H\) 步之后、一直到无穷远的所有回报"压缩成了一个数,加到回报里。于是规划器虽然只显式 rollout 了 \(H\) 步,但通过这个终端价值,它"看到"了 \(H\) 之后的长期后果。
这里要澄清一个初学者容易混淆的点:为什么前 H 步用 reward 预测 \(r_\theta\) 累积,而末端却换成价值 \(Q_\theta\),不继续用 reward? 因为 reward 和价值估的是**完全不同的两个量**。reward \(r_\theta(z_t,a_t)\) 估的是"这一步"的即时回报(一个单步的量);价值 \(Q_\theta(z_H,a_H)\) 估的是"从这里出发、之后所有步"的长期累积回报(一个无穷步的量)。
所以前 H 步,我们一步一步显式 rollout、用 reward 预测算每一步的即时回报(因为这几步我们用模型实打实推演了,能算出每步 reward);到第 H 步末端,我们**不再继续 rollout**(再 rollout 会累积误差),于是用价值函数"一口气"估计"H 之后所有步的累积回报"——价值把"无穷多步的 reward 之和"压缩成了一个数。
换句话说:reward 是"零售"——一步一步地算;价值是"批发"——把剩下的无穷多步打包估成一个数。 前 H 步我们零售(精细但只能算几步),H 之后我们批发(一次性概括长期)。两者拼起来,就是"精细的近期 + 概括的远期"。如果末端继续用 reward,就只能再算"一步"的即时回报,根本覆盖不了"H 之后的长期"——那正是价值存在的意义。理解了"reward 管单步、价值管长期"这个角色分工,你就明白为什么公式里前 H 项是 reward、最后一项是价值。
打个比方能说清这个机制。短 horizon rollout 像用望远镜看前方 \(H\) 步的清晰路况,终端价值像在望远镜视野的尽头立了一块路牌,上面写着"从这里继续走,前方总体有多好"。 你不需要把望远镜望到无穷远(加长 horizon,又慢又模糊),只需要在视野尽头有这块准确的路牌(学习的价值),就能做出有远见的决策——既看清了眼前 \(H\) 步的细节,又知道了 \(H\) 之后的大势。
这正是 §6.1 历史小节里说的"融合 model-based 和 model-free"的落点:短 horizon rollout 是 model-based 的(用模型推演眼前),终端价值是 model-free 的(用学习的价值概括长期)。 前者提供局部的精确,后者提供全局的远见,合起来兼得两者之长。换句话说,终端价值这一行代码,正是 TD-MPC 把两个传统上对立的 RL 阵营缝合在一起的那一针——它让"用模型规划"(model-based 的看家本领)和"学价值"(model-free 的看家本领)不再是二选一,而是在同一个回报公式里各司其职、协同发力。这也是为什么 §6.1 反复说 TD-MPC 是两者的"深度融合"——融合的技术落点,就在这个把 model-based 的 rollout 和 model-free 的价值拼成一个回报的公式里。
读到这里你可能会问:既然价值函数能估计长期回报,那为什么还要 rollout 那 \(H\) 步?直接用 \(Q_\theta(z_0, a_0)\) 选动作(像纯 model-free 的 SAC 那样)不就行了? 这是个极好的问题,触及了"规划 vs 纯价值"的核心区别。答案是:价值函数是学出来的、有近似误差,而 rollout 那 \(H\) 步是用模型实打实推演的、相对可靠。 纯靠 \(Q_\theta(z_0, a_0)\) 选动作(model-free)把全部信任押在价值函数上——价值不准就全错。TD-MPC 的做法是:用相对可靠的短 rollout 推演眼前 \(H\) 步(减少对价值的依赖),只把"\(H\) 之后"这部分难以推演的长期交给价值。rollout 的步数 \(H\) 越多,对价值的依赖越少、但累积误差越大;\(H\) 越少,越依赖价值、但 rollout 越准。 TD-MPC 选一个小的 \(H\)(3~5),在"用模型推演"和"信任价值"之间取了一个甜点——这也是为什么它既不是纯规划、也不是纯价值,而是两者的精妙平衡。
本质洞察:终端价值是 TD-MPC 把"有限 horizon 规划"和"无限 horizon 最优"缝合起来的针脚。纯短 horizon 规划求的是"未来 \(H\) 步内的局部最优",它在数学上**不等于、也不可能等于**真正的"无限 horizon 全局最优"——除非你能把 \(H\) 之后的所有回报也算进来。而把无穷多步的回报算进来,正是价值函数的定义。所以加上终端价值后,规划的目标从"\(H\) 步局部最优"变成了"\(H\) 步 rollout + \(H\) 之后价值估计"——后者是对"无限 horizon 最优"的一个**有原则的近似**。这个缝合的深刻之处在于:它让你用"短 horizon 的计算成本"逼近"无限 horizon 的决策质量",前提是你有一个够准的价值函数。这也解释了为什么 TD-MPC 必须**同时**学好动力学和价值——动力学保证短 rollout 准,价值保证长期估计准,两者任一垮掉,这个缝合就失效。理解了"终端价值 = 有限与无限的针脚",你就理解了为什么这一招是 TD-MPC(乃至一切结合规划与价值的方法,如 AlphaZero 的 MCTS + value network)的命脉。
动手验证:加 horizon 救不了短视,加价值可以¶
光说不够,用一个亲手验证的 demo 把这个洞察钉死。我们刻意构造一个"短视会失败、必须看长期"的任务,然后对比"加 horizon"和"加价值"两条路谁有效。
任务设计:一个一维的点,可以左右移动(动作 \(a\in[-1,1]\),\(x' = x + a\))。reward 地形上有**两个峰**:近处 \(x=2\) 有一个**小峰**(高 1.0),远处 \(x=10\) 有一个**大峰**(高 4.0),两峰之间是 reward 接近 0 的低谷。点从 \(x=0\) 出发。真实最优是穿过低谷、到达远处的大峰。但短视的规划器会被近处的小峰吸住——因为在短 horizon 内,"走向小峰"立刻有回报,而"走向大峰"要先穿过一段 reward 为 0 的低谷、回报来得晚。
import numpy as np
gamma = 0.97
def reward(x):
small = 1.0 * np.exp(-((x-2.0)**2)/(2*0.6**2)) # 近处小峰(高1.0)
big = 4.0 * np.exp(-((x-10.0)**2)/(2*0.8**2)) # 远处大峰(高4.0)
return small + big
# "学好的价值函数" V*(x): 用密集 value iteration 预计算(模拟一个训练好的 Q)
xs = np.linspace(-2, 14, 1601)
def idx(x): return np.clip(((np.asarray(x)+2)/16*1600).astype(int), 0, 1600)
V = np.zeros(1601)
for _ in range(400): # value iteration 收敛出 V*
Vnew = V.copy()
for ai in [-1.,-.5,0,.5,1.]:
xn = np.clip(xs+ai, -2, 14); Vnew = np.maximum(Vnew, reward(xn)+gamma*V[idx(xn)])
V = Vnew
def plan(x0, H, use_value, K=150, iters=4, seed=0):
rng = np.random.default_rng(seed)
mean = np.zeros(H); std = np.ones(H)*0.6
for _ in range(iters):
actions = np.clip(mean[None] + rng.standard_normal((K,H))*std, -1, 1)
x = np.full(K, x0); G = np.zeros(K); g = 1.0
for t in range(H): # rollout H 步, 累积折扣 reward
x = np.clip(x + actions[:,t], -2, 14); G += g*reward(x); g *= gamma
if use_value:
G += g * V[idx(x)] # 终端价值: 估计 H 之后的长期回报
elite = G.argsort()[-25:] # 取精英更新分布(CEM 式)
mean = actions[elite].mean(0); std = actions[elite].std(0).clip(0.05,None)
return mean[0]
def run(H, use_value, steps=40, seed=0): # 闭环: 每步规划, 执行第一个动作
x = 0.0
for t in range(steps): x = np.clip(x + plan(x,H,use_value,seed=seed+t), -2, 14)
return x
跑 5 个随机种子,对比不同 horizon、有无终端价值时点最终停在哪:
=== 近处小峰(x=2,高1.0) vs 远处大峰(x=10,高4.0): 真实最优应到大峰 ===
配置 平均最终位置 结果
H=3, 无价值 2.00 ✗ 困在小峰
H=3, +学习的价值 10.00 ✓ 到达大峰
H=5, 无价值 2.00 ✗ 困在小峰
H=5, +学习的价值 10.01 ✓ 到达大峰
H=15, 无价值 2.04 ✗ 困在小峰
H=30, 无价值 2.02 ✗ 困在小峰
这组数字把本节的洞察演示得淋漓尽致,逐行读:
无价值时,加 horizon 救不了短视。 H=3、5、15、30 一路加上去,点**全部**困在近处小峰(x≈2)。即使 horizon 加到 30,依然短视!为什么加 horizon 没用?因为大峰在 x=10、距起点 10 步,中间隔着一段 reward≈0 的低谷——纯 rollout 即便 horizon 够长,也要采样到"连续向右、穿过低谷、最后到大峰"这样一条特定轨迹才能发现大峰的好,而在高维动作序列里随机采样极难采到这样的轨迹,加上折扣让远期回报衰减,规划器算来算去还是觉得"待在近处小峰"回报更稳。加 horizon 既增加了计算、又因采样难度和折扣而收效甚微。
加价值,H=3 就够。 一旦在末端加上学习的价值,H=3 就让点穿过低谷、到达远处大峰(x≈10)!因为价值函数 \(V^*(x)\) 已经"知道"——即便你现在在低谷里(reward≈0),你的长期价值依然很高(因为前方有大峰)。于是规划器在 rollout 末端看到"虽然这 3 步 reward 不高,但末端位置的长期价值很高",就敢于穿过低谷向大峰前进。短 horizon + 价值,3 步就有了 30 步都没有的远见。
这就是本节洞察的铁证:长期信息不该靠"加长 horizon"硬抠(又慢又抠不出来),而该用"学习的价值"在末端一次性补足(又快又准)。 TD-MPC 用 H=3~5 就能做出有远见的决策,秘密全在这个终端价值上。
读到这里你可能会问:这个 demo 里的价值函数 \(V^*\) 是用 value iteration 算出来的"完美价值",真实 TD-MPC 的价值是学出来的、有误差,那洞察还成立吗? 成立,但要加一句诚实的限定。洞察的机制——"价值补长期、让短 horizon 有远见"——不依赖价值完美,只要价值**够准**就成立。真实 TD-MPC 的价值确实有误差,所以它的远见也不完美;但即便是有误差的价值,也远胜"直接截断(等于假设 H 之后回报为 0)"。换句话说,终端价值是"用一个有误差的长期估计"替换"一个肯定错误的零假设"——前者再不准,也比后者强。这也再次说明为什么 TD-MPC 要花大力气把价值学准(§6.5):价值越准,短 horizon 的远见越可靠。
三种决策方式:纯规划、纯价值、规划 + 价值¶
把 TD-MPC 的"规划 + 价值"放到一个更大的对比里,你会更清楚它的位置。决策连续控制问题,大致有三种思路,它们的区别恰好落在"如何处理未来"上:
| 决策方式 | 怎么看未来 | 代表 | 优点 | 缺点 |
|---|---|---|---|---|
| 纯规划(无价值) | 用模型 rollout 显式推演未来 H 步,截断 | vanilla MPPI/CEM(第 2–4 章) | rollout 可靠(用模型实推) | 短视(H 之外看不到)、长 H 又慢又累积误差 |
| 纯价值(model-free) | 用学习的价值/策略一步选动作,不 rollout | SAC、PPO | 推理快、无模型误差 | 全押在价值上,价值不准就全错;不在线优化 |
| 规划 + 价值 | 短 rollout 推演眼前 + 价值估长期 | TD-MPC(本章)、AlphaZero | 兼得:眼前可靠 + 长期有远见 | 要同时学好模型和价值 |
读这张表,三种方式像一个光谱:纯规划完全信任模型推演(但只能短期)、纯价值完全信任学习的价值(但有近似误差)、TD-MPC 在中间——用短 rollout 推演相对可靠的眼前、用价值概括难推演的长期。 它取两者之长:比纯规划有远见(价值补长期)、比纯价值鲁棒(短 rollout 减少对价值的依赖)。
这也再次印证 §6.4 开头那个问题的答案——为什么不纯靠价值(像 SAC)。纯价值把全部信任押在一个有误差的函数上;TD-MPC 用"短 rollout 推演 + 价值补长期"分散了风险:眼前 H 步用相对可靠的模型推演(不依赖价值),只有"H 之后"才依赖价值。rollout 步数 \(H\) 就是这个"信任模型 vs 信任价值"的旋钮,TD-MPC 选一个小的 \(H\) 取甜点。
把这张三方对比记牢,它其实是理解整个 model-based RL 版图的一把尺子:你以后看到任何决策方法,都可以问"它怎么处理未来——纯前瞻、纯价值、还是前瞻 + 价值",立刻就能在这个版图上给它定位。而 TD-MPC(以及 AlphaZero 等)选的"前瞻 + 价值"这一档,正是兼顾可靠与远见的那个甜点档位——这也是为什么它成了 model-based RL 里最有影响力的范式之一。本节的核心洞察,本质上就是在讲"为什么这个甜点档位如此关键"。
为什么这一招同时绕开了"两个限制"¶
回到 §6.1 的两个限制,看终端价值这一招如何一箭双雕(其实是和 latent 模型配合,三个设计协同):
绕开限制二(短视):终端价值直接补足了 horizon 之外的长期信息——这是它的本职,上面已充分演示。
配合绕开"长 rollout 失真":因为有终端价值补长期,规划器**不需要长 horizon** 了,可以用很短的 H(3~5)。而短 H 恰恰避开了 §6.8 要讲的累积误差——学习的 latent 动力学只 rollout 3~5 步,误差还没长大就停下,再交给价值。所以终端价值不仅补了短视,还**让"用短 horizon"成为可能**,从而间接绕开了学习模型的累积误差问题。
本质洞察:把 §6.2 的 latent 模型、§6.3 的 latent 规划、§6.4 的终端价值三者合起来看,TD-MPC 的设计是一个环环相扣的整体,缺一不可。latent 动力学让 rollout 快(绕限制一),但它有累积误差、不能 rollout 太长;短 horizon 避开累积误差,但会短视;终端价值补足短视、让短 horizon 可行。三个设计像三根互相支撑的柱子:latent 模型提供速度、短 horizon 提供准确、终端价值提供远见,任何一根抽掉,整座结构就塌——没有 latent 模型就慢、没有短 horizon 就被累积误差毁、没有终端价值就短视。这种"多个设计协同解决一组相互纠缠的限制"的整体性,是 TD-MPC 最值得品味的地方。它告诉你:一个好的系统设计,往往不是单点突破,而是几个设计彼此成全、共同绕开一组本来无解的两难。读 TD-MPC,要读的正是这种"协同"的智慧,而非孤立地记住"它用了价值函数"。
一个熟悉的类比:TD-MPC 与 AlphaZero¶
如果你听说过 AlphaZero(下围棋/国际象棋的那个),本节的核心洞察会让你会心一笑——TD-MPC 和 AlphaZero 用的是同一个深层范式:有限的前瞻搜索 + 学习的价值。
AlphaZero 下棋时,不会把棋局算到终局(那是天文数字的可能性,算不完)——它用 MCTS(蒙特卡洛树搜索)只**前瞻有限的几步**,在搜索的叶子节点上用一个**学习的价值网络**估计"从这个局面出发,最终能赢的概率"。前瞻搜索负责精细推演眼前几步,价值网络负责概括"几步之后的长期胜负"。两者结合,让它用有限的搜索逼近"看到终局"的决策质量。
把这个和 TD-MPC 对照,结构惊人地一致:
| 前瞻部分(推演眼前) | 价值部分(概括长期) | |
|---|---|---|
| AlphaZero | MCTS 树搜索(前瞻几步棋) | 价值网络(估计终局胜负) |
| TD-MPC | 采样规划 latent rollout(前瞻 H 步) | 学习的 \(Q_\theta\)(估计 H 之后的长期回报) |
两者都在解同一个根本难题:怎么用有限的计算(前瞻几步),逼近无限 horizon 的最优决策(看到终局/无穷远未来)? 答案都是同一个——有限前瞻 + 学习价值:用前瞻精确推演够得着的近期,用学习的价值概括够不着的远期。
这个类比的价值在于,它告诉你本节的核心洞察不是 TD-MPC 独有的小技巧,而是一个**贯穿决策智能的普遍范式**。从下棋(AlphaZero)到连续控制(TD-MPC),凡是面对"未来太长、算不到底"的决策问题,"有限前瞻 + 学习价值"都是一把通用的钥匙。理解了 TD-MPC 的终端价值,你也就理解了 AlphaZero 的价值网络——它们是同一个思想在不同领域的化身。这也是为什么本节的核心洞察值得反复品味:它的适用范围,远超 TD-MPC 本身。
⚠️ 常见陷阱¶
概念误区:以为"加长 horizon"和"加终端价值"是等效的、可互相替代的两条路。 错误认识:既然终端价值补长期信息,加长 horizon 也能覆盖更多未来,两者效果应该差不多,用哪个都行。 现象/后果:在该用终端价值的地方死磕加长 horizon,结果又慢、又因采样难度和累积误差而救不了短视(正如 demo 里 H=30 无价值仍困在小峰);浪费大量计算却不解决问题。 根本原因:加长 horizon 是"显式 rollout 更多步"——计算线性增长、采样难度上升、学习模型累积误差增大,且折扣让远期回报衰减、未必抠得出长期信息。终端价值是"用一个学习的函数一次性概括无穷远未来"——计算几乎不增、不受 rollout 误差累积影响。两者机制完全不同,效果天差地别(demo 已铁证)。 正确做法:补长期信息一律用终端价值,而非加长 horizon。把 horizon 保持短(3~5)以避开累积误差,让价值去管长期。这是 TD-MPC 的核心设计,不是可选项。
思维陷阱:以为既然价值能估长期,就该完全靠价值(纯 model-free),不必 rollout。 错误认识:价值函数都能估计无穷远未来了,那直接用 \(Q(z_0,a_0)\) 选动作就行,rollout 那几步是多余的。 现象/后果:退化成纯 model-free(如 SAC),把全部信任押在价值函数上——价值有近似误差时决策全错,丢掉了"用模型推演眼前、减少对价值依赖"的鲁棒性。 根本原因:价值是学出来的、有近似误差;短 rollout 是用模型实打实推演的、相对可靠。纯靠价值等于无条件信任一个有误差的估计;短 rollout + 终端价值则用可靠的推演覆盖眼前、只把难推演的长期交给价值,更鲁棒。 正确做法:保留短 rollout(3~5 步),用它推演相对可靠的眼前、减少对价值的依赖,只用终端价值补"rollout 够不到的长期"。rollout 步数 \(H\) 是"信任模型推演 vs 信任价值"的平衡旋钮——TD-MPC 选小 \(H\) 取甜点,而非走"纯价值"或"长 rollout"的极端。
编程陷阱:终端价值忘记乘折扣 \(\gamma^H\),或用了错误的折扣指数。
错误做法:在末端直接加 \(Q(z_H, a_H)\) 而不乘 \(\gamma^H\),或乘了错误的指数(如 \(\gamma^{H-1}\)、\(\gamma^{H+1}\))。
现象/后果:终端价值和前 \(H\) 步回报的折扣不一致,导致"长期 vs 短期"的权衡被扭曲——不乘折扣会让终端价值被过度看重(相当于不折扣未来),规划行为异常。
根本原因:终端价值估计的是"从第 \(H\) 步末端状态出发的回报",而前面 rollout 的第 \(t\) 步 reward 乘的是 \(\gamma^t\)(\(t=0,\dots,H-1\)),所以末端(第 \(H\) 步)的价值必须乘 \(\gamma^H\) 才能和前面的折扣一致、拼成一个自洽的折扣总回报。
正确做法:严格按 \(G=\sum_{t=0}^{H-1}\gamma^t r_t + \gamma^H Q(z_H,a_H)\) 写——前 \(H\) 步 reward 乘 \(\gamma^0\) 到 \(\gamma^{H-1}\),终端价值乘 \(\gamma^H\)。自检:rollout 循环里维护一个 discount 变量,每步乘 \(\gamma\),循环结束后 discount 恰好是 \(\gamma^H\),直接用它乘终端价值(正如 §6.3 plan 代码的写法)。
练习¶
-
(复现核心 demo,⭐⭐) 把本节的"小峰 vs 大峰"demo 敲一遍跑通,复现"H=3/5/15/30 无价值都困在小峰、H=3+价值到达大峰"的结果。然后实验:(a) 把大峰的高度从 4.0 降到 1.5(和小峰差不多),无价值的短 horizon 还会被小峰困住吗?为什么?(b) 把两峰间的距离拉近(大峰移到 x=5),无价值需要多长 horizon 才能发现大峰?这说明"加 horizon"在什么情况下勉强有效、什么情况下彻底无效。
-
(价值不准时远见如何退化,⭐⭐⭐,探索题) 真实 TD-MPC 的价值是学出来的、有误差,本节用的 \(V^*\) 是完美价值。请基于 demo 探索"价值不准"的影响:(a) 给价值函数注入**系统性偏差**——比如在低谷区域(\(x=4\sim8\))让价值估计偏低(模拟"价值没学好、低估了穿过低谷后的长期价值"),看规划是否还敢穿过低谷去大峰,还是退回小峰?(b) 偏差多大时远见开始失效?(c) 这个实验说明了什么——为什么 §6.5 要花大力气把价值学准?(d) 对比"价值有系统性偏差"和"价值有随机噪声(无偏)"两种情况,哪种更容易破坏远见?为什么?(提示:随机噪声在多次采样里可能部分抵消,系统性偏差不会。)这道题让你亲手体会"短 horizon 的远见有多依赖价值的质量"。
-
(折扣与终端价值,⭐⭐⭐) 基于 demo,把终端价值的折扣从正确的 \(\gamma^H\) 改成 \(\gamma^0\)(即不折扣终端价值),观察规划行为如何变化。然后推导:如果终端价值不乘折扣,相当于在隐式地假设什么(提示:把它写进总回报公式,看它和前 \(H\) 步回报的折扣是否自洽)?这道题让你从代码和数学两头理解"终端价值为什么必须乘 \(\gamma^H\)"。
-
(规划 vs 纯价值的平衡,⭐⭐⭐⭐,思考题) 本节论证 TD-MPC 在"用模型 rollout"和"信任价值"之间用 \(H\) 取平衡。请综合论证:(a) 把 \(H\) 推到极端:\(H=0\)(纯靠 \(Q(z_0,a_0)\) 选动作)退化成什么方法?\(H\to\infty\)(不用价值)又退化成什么?各有什么问题?(b) 为什么"中等的小 \(H\)(3~5)"是甜点——它在"模型 rollout 的累积误差"和"价值的近似误差"之间如何权衡?(c) 这个"短 rollout + 终端价值"的结构,和你听过的 AlphaZero(MCTS 树搜索 + 价值网络)有什么共通之处?两者都在用"有限的前瞻搜索 + 学习的价值"逼近"无限的最优决策"——把这个共性讲清楚。
§6.5 联合训练:四个网络如何从数据一起学出来 ⭐⭐⭐¶
动机:模型不会凭空出现,它要从数据训练出来¶
前面几节都在用一个"已经学好的"世界模型做规划。但这个模型从哪来?这一节回答 TD-MPC 的另一半——训练。它讲清编码器、动力学、reward、价值这四个网络如何用一个联合损失从交互数据里一起学出来。理解训练,你才算完整掌握 TD-MPC,也才能在 §6.7 真正把它跑起来。
先建立一个总体认识:TD-MPC 是一个**完整的强化学习算法**,不只是一个规划器。它的运行是一个标准的 RL 闭环——用当前模型规划、与环境交互、把交互数据存进 replay buffer、从 buffer 采数据训练模型、模型变好后规划更好……循环往复。规划(§6.3)是"怎么用模型决策",训练(本节)是"怎么从数据改进模型",两者构成完整的学习系统。
训练数据从哪来:规划即采集¶
TD-MPC 的训练数据来自它自己的规划。每个时刻,规划器(§6.3 的 plan)输出一个动作、执行、观测到下一状态和 reward,这条 transition \((o, a, r, o')\) 存进 replay buffer。训练时从 buffer 里采一批轨迹段,用来更新四个网络。
这里有个值得注意的点:规划器既是"决策者"又是"数据采集者"。它用当前模型规划出动作去和环境交互,这些交互数据又用来改进模型。这种"用当前策略采的数据训练当前模型"的结构,是 RL 里 off-policy 学习的典型模式(buffer 里混着不同时期模型采的数据)。记住这一点,§6.8 讲"policy mismatch / 价值过估计"时会回到它——规划器采的数据分布和价值学习假设的分布不完全一致,是个微妙的问题源。
这里顺带点明一个性质:TD-MPC 是 off-policy(离策略) 学习的。回忆你的 RL 基础——off-policy 指"用一个策略采的数据,训练另一个(或不断更新的)策略/价值",与之相对的 on-policy 要求"训练用的数据必须来自当前策略"。TD-MPC 的 replay buffer 里混着不同训练阶段的模型采的 transition(早期较差的模型采的、近期较好的模型采的都有),训练时不加区分地从里面采——这正是 off-policy 的做法。
off-policy 的好处很实际:数据可以反复利用。每条 transition 进了 buffer 就能被采样很多次、训练很多轮,不像 on-policy 那样用一次就丢。这大幅提升了样本效率(呼应 §6.1 说的 model-based 样本效率优势),对真机机器人(交互昂贵)尤其宝贵。TD-MPC 的双 Q、目标网络等设计也都是 off-policy RL(如 SAC、DQN)的标准配件,从那里直接迁移。
但 off-policy 也埋下一个隐患,正是 §6.8 要讲的 policy mismatch 的根源:buffer 里的数据来自"规划器这个行为策略",而价值学习时用 TD 目标(假设按 policy prior 走)——行为策略和价值学习假设的策略不完全一致,这种 off-policy 特有的"分布不匹配"会让价值在某些区域的误差得不到纠正。所以 off-policy 既给了 TD-MPC 样本效率,也带来了 §6.8 的微妙问题——这是一体两面。
还有一个实战细节值得知道:训练**最开始**,模型完全没学过、规划等于瞎猜,这时用它采数据没意义。所以 TD-MPC 通常先用**随机动作**采集一批初始数据(称 seed steps / 预热),填充 replay buffer,让模型先有数据可学;之后才切换到"用规划采数据"。这解释了 §6.8 故障排查里说的"训练初期规划随机是正常的"——初期本就是随机预热 + 模型刚起步的阶段,规划行为随机是预期的,不是 bug。预热步数通常按任务的 episode 长度设定(也是 TD-MPC2 单一超参的一部分,不用你逐任务调)。理解这个预热阶段,你训练时就不会因为"前面一段一直随机、不见好"而惊慌——那正是它该有的样子。
理论:联合损失的三个部分¶
TD-MPC 的核心是一个**联合损失**,同时训练四个网络(编码器、动力学、reward、价值)。从 buffer 采一段长度为 \(H\) 的轨迹 \((o_0, a_0, r_0, o_1, a_1, r_1, \dots)\),损失由三部分组成。先给全貌,再逐项拆解:
其中 \(z_t\) 是从初始 latent 用动力学**递推**出来的(\(z_{t+1} = d_\theta(z_t, a_t)\)),\(\text{sg}\) 是 stop-gradient,\(\lambda\) 是按时间步衰减的权重。逐项讲透。
① latent 一致性损失(latent consistency)——这是 TD-MPC 最有特色的一项。 它要求:用动力学**递推**出来的 latent \(z_t\)(从 \(z_0=h_\theta(o_0)\) 出发,反复用 \(d_\theta\) 推 \(t\) 步),要接近"真实第 \(t\) 步观测 \(o_t\) **直接编码**出来的 latent \(h_\theta(o_t)\)"。
读这个:左边 \(z_t\) 是"模型想象出来的第 \(t\) 步 latent"(一路 rollout 来的),右边是"真实第 \(t\) 步观测编码出的 latent"(真值)。损失逼着"想象的 latent"接近"真实的 latent"——也就是逼动力学 \(d_\theta\) 预测得准。注意右边有 stop-gradient(\(\text{sg}\)):编码目标被当成固定靶子,梯度只更新"想象"这一侧,防止编码器为了让损失变小而"作弊"地把所有 latent 都塌到一个点(平凡解)。
这里是 TD-MPC 区别于 Dreamer/PlaNet 的命门,必须讲透:为什么用 latent 一致性,而不用"重建观测"?
回忆 §6.2 的"任务导向"。Dreamer/PlaNet 用重建损失——要求 latent 能解码回原始观测 \(o_t\),逼模型学会重建图像/状态。但重建逼模型去编码观测里的一切(包括无关细节)。TD-MPC 的 latent 一致性只要求"递推的 latent 接近编码的 latent"——它**在 latent 空间内部比较,根本不碰原始观测**。这意味着:模型只需要保证"latent 层面的动态预测一致",而不需要保证"能重建观测"。latent 里编码什么、不编码什么,由下游的 reward/价值预测任务决定(任务导向),而非由"重建观测"这个与决策无关的目标绑架。
本质洞察:latent 一致性损失是"任务导向世界模型"在训练层面的实现。它的精妙在于把"模型预测得准"这件事,从"能重建观测"(绝对的、与任务无关的标准)改成了"latent 层面自洽"(相对的、由下游任务塑造的标准)。这一改,模型就被解放了——它不必浪费容量去重建无关细节,只需保证"我对 latent 演化的预测,和真实观测编码出的 latent 一致"。而 latent 里到底该编码什么,由 reward 和价值预测任务隐式决定:能帮助预测 reward/价值的信息会被编码进 latent,无关的会被丢弃。这种"用 latent 空间的自洽性替代观测空间的重建"的思想,是现代 model-based RL 从"重建式"走向"任务导向式"的技术核心。它也呼应了一个更普遍的机器学习智慧:表示学习的目标,应该由下游任务定义,而非追求对输入的完美重建。 自监督学习里的对比学习、BYOL 等方法用的也是类似的"在表示空间自洽、不重建输入"的思想——TD-MPC 的 latent 一致性是这个思想在世界模型里的体现。理解了它,你就理解了为什么 TD-MPC 不需要解码器、为什么它的模型能小而有效。
② reward 预测损失。 要求 reward 预测 \(\hat r_t = r_\theta(z_t, a_t)\) 接近真实 reward \(r_t\)。这一项保证规划时 latent 上算的 reward 准。简单直接——它是个回归损失(TD-MPC2 用离散回归,§6.6 讲)。但它的作用不止于此:因为 reward 预测依赖 latent \(z_t\),这一项也**反向塑造了编码器**——为了预测准 reward,编码器必须把"与 reward 相关的信息"编码进 latent。这正是"任务导向"的来源之一。
③ TD / 价值损失——这是把价值学出来的部分。 要求价值预测 \(\hat Q_t = Q_\theta(z_t, a_t)\) 接近一个 TD 目标 \(Q_{\text{target}}\)。这是标准的时序差分学习(你的 RL 基础):
读这个 TD 目标:当前 \(Q\) 应该等于"这一步真实 reward \(r_t\) + 折扣 × 下一状态的价值估计"。下一状态价值用一个**目标网络** \(Q_{\bar\theta}\)(参数缓慢跟随主网络,稳定训练,你的 SAC 基础里见过)估计,动作从 policy prior \(\pi\) 采。这就是把"长期回报"bootstrap 地学进 \(Q_\theta\) 的过程——TD 让 \(Q\) 不需要走到 episode 结束就能学到长期价值。
注意这一项里的下一状态 latent 是**直接编码** \(h_\theta(o_{t+1})\)(用真实下一观测),而非动力学递推——价值学习用真实状态做 TD 目标,更可靠。
读到这里你可能会问:TD 的 bootstrap——"用当前价值估计去更新当前价值"——听起来像左脚踩右脚,它真能学出正确的长期价值吗? 这是初学 TD 最常见的困惑,用一个最小 demo 把它演示清楚,你就彻底信服了。
构造一个最简单的场景:一条 11 个状态的链(状态 0 到 10),智能体每步向右走一格,只有到达终点(状态 10)那一步才获得 reward=1,其余转移 reward=0。真实的价值 \(V^*(s)\) 是"从 \(s\) 出发能拿到的折扣回报"——离终点越近价值越高。我们看 TD 能否从"只有终点有 reward"这个稀疏信号里,学出整条链的价值:
import numpy as np
N = 11; gamma = 0.9
def step(s): # 向右走一格, 到终点给 reward
s2 = min(s+1, N-1); r = 1.0 if (s2==N-1 and s!=N-1) else 0.0
return s2, r
V = np.zeros(N); alpha = 0.1 # 价值表初始化为全 0
for ep in range(500): # 反复跑这条链, 用 TD 更新
s = 0
while s < N-1:
s2, r = step(s)
V[s] += alpha * (r + gamma*V[s2] - V[s]) # TD 更新: 当前值 <- r + γ·下一值
s = s2
看 TD 学到的价值随训练的演化(每个数是对应状态的价值估计):
真实价值 V*(s):
0.387 0.430 0.478 0.531 0.590 0.656 0.729 0.810 0.900 1.000 0.000
TD 学的价值随训练演化(看价值如何从终点"传播"回起点):
ep= 1: 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.100 0.000
ep= 5: 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.007 0.073 0.410 0.000
ep= 20: 0.000 0.000 0.000 0.001 0.007 0.028 0.097 0.262 0.547 0.878 0.000
ep=100: 0.213 0.292 0.380 0.469 0.556 0.641 0.723 0.808 0.900 1.000 0.000
ep=500: 0.387 0.430 0.478 0.531 0.590 0.656 0.729 0.810 0.900 1.000 0.000
这个演化过程把 TD 的精髓演示得清清楚楚:
reward 只在终点,但价值"传播"回了整条链。 ep=1 时,只有终点前一格(状态 9)学到了一点价值(0.1)——因为只有它直接体验到了到达终点的 reward。ep=5 时,价值往回传了一格(状态 8 也有了值)。随着训练,价值像水波一样从终点逐步"传播"回起点,到 ep=500,整条链的价值都学准了(与真实价值完全吻合,平均误差 0.0000)。
这就是 bootstrap 的威力,它不是"左脚踩右脚"。 关键在于:每次更新 \(V(s) \leftarrow r + \gamma V(s')\),用的 \(V(s')\) 虽然也是估计、可能还不准,但它**多吸收了一步真实的 reward 信息**(那个 \(r\))。所以每次更新都让价值"多对一点"——离终点近的状态先学准(它们离真实 reward 信号近),然后把学准的价值传给更远的状态。一步步地,真实 reward 的信息通过 bootstrap 链式地传遍全图。bootstrap 不是凭空自我循环,而是"用一步真实反馈 + 下一步的当前最佳估计"逐步逼近真值。
回到 TD-MPC:它的 \(Q_\theta\) 正是这样从交互数据里 bootstrap 地学出来的——每条 transition 提供一步真实 reward,TD 更新把"长期回报"逐步传播进 \(Q_\theta\)。学好之后,这个 \(Q_\theta\) 就能在规划时当终端价值,告诉规划器"从某个 latent 出发,长期有多好"(§6.4)。TD 是把"长期"装进一个函数的引擎,而那个函数正是 TD-MPC 远见的来源。 这也是为什么本章反复强调价值学习是 TD-MPC 的另一半地基——没有 TD 学出的价值,§6.4 的核心洞察就成了无源之水。
读到这里你可能会问:为什么用 TD(时序差分)学价值,而不直接用蒙特卡洛——跑完整个 episode、把真实的累积回报当价值的训练目标? 这个问题触及 TD-MPC 名字里"TD"的深意,值得回答。
蒙特卡洛的做法是:跑到 episode 结束,把实际拿到的折扣累积回报作为价值目标。它的好处是**无偏**(用的是真实回报,不依赖任何估计)。但它有两个致命问题:一是**必须等 episode 结束**才能更新(对长 episode 或持续任务很慢,甚至无法进行);二是**方差极大**(一整条轨迹的回报受沿途所有随机性影响,噪声很大)。
TD 的做法(\(Q \leftarrow r + \gamma Q(s')\))只用**一步真实 reward + 下一步的当前估计**——不必等 episode 结束(每步都能更新,快),方差也小(只引入一步的随机性)。代价是**有偏**(依赖 \(Q(s')\) 这个估计,估计不准就有偏差)。但正如上面的 demo 演示的,这个偏差会随训练逐步消除(bootstrap 让价值逐渐传播准)。
所以 TD 是在"偏差"和"方差/效率"之间做了一个对 RL 极其有利的权衡:用一点偏差(依赖 bootstrap 估计),换来了巨大的效率(不必等 episode 结束)和低方差(只看一步)。 这对 TD-MPC 尤其重要——它要在线学习、持续改进,等不起 episode 结束,也受不了高方差。这就是为什么它叫 TD-MPC,而非"蒙特卡洛 MPC":TD 是让它能高效、低方差地在线学价值的引擎。这也是你 RL 基础里"TD vs 蒙特卡洛"那个经典权衡在 TD-MPC 里的具体体现。
三项损失的权重怎么配¶
联合损失里有三个权重 \(c_1\)(latent 一致性)、\(c_2\)(reward)、\(c_3\)(价值),以及一个按时间步衰减的 \(\lambda\)。它们怎么配,是实战中真实会遇到的问题,这里给一个直觉性的说明(具体数值以官方实现为准)。
一个值得注意的经验是:latent 一致性损失的权重 \(c_1\) 通常最大、价值损失权重 \(c_3\) 通常最小。为什么这样配?
latent 一致性权重大,因为它是地基。 整个 TD-MPC 的规划都建立在"latent 动力学预测准"之上——如果 latent 一致性没学好(动力学预测不准、或 latent 塌缩),那 reward 预测和价值都建立在一个错误的 latent 表示上,全盘皆错。所以要给它最大的权重,优先保证 latent 表示和动力学的质量。
价值损失权重小,因为价值是 bootstrap 学的、本身在变。 价值通过 TD bootstrap 学习,它的目标 \(Q_{\text{target}}\) 用的是当前(还不准的)价值估计——早期价值很不准,如果给它太大权重,会让训练被不准的价值目标主导、不稳定。给它较小权重,让它"慢慢学",随着 latent 和 reward 学好、价值的 bootstrap 目标也逐渐变准。
\(\lambda\) 按时间步衰减,因为越远的 rollout 步越不可靠。 损失里 \(\lambda^t\) 让靠后的时间步(rollout 更多步、累积误差更大)权重更小——这呼应 compounding error:越往后的预测越不准,训练时也相应少信任它一点。
读到这里你可能会问:这些权重需要逐任务调吗? TD-MPC2 的一个卖点正是"单一超参集"(§6.6)——这套权重跨所有任务不变、不需逐任务调。这是它鲁棒性的体现。所以实战中你通常直接用默认权重,而非自己调——理解这些权重"为什么这样配"主要是为了读懂方法,而非为了调参。
双 Q 与价值过估计:从 SAC 迁移来的稳健性¶
价值学习有一个老问题——过估计。\(Q\) 网络的近似误差会被"取最优动作"的 max 操作系统性放大,导致 \(Q\) 估计偏高、且越学越偏。这在你的 SAC 基础里见过,解法也一样迁移过来:用多个 Q 网络,取较小值(clipped double-Q)。
读到这里你可能会问:为什么"取最优动作的 max"会系统性放大误差?误差不是有正有负、应该抵消吗? 这是理解过估计的关键,值得讲透。问题恰恰出在 max 上。设想 \(Q\) 网络对每个动作的估计都带一点随机误差(有的高估、有的低估,平均为零)。如果你只是"评估某个固定动作",这些误差确实会抵消。但 TD 目标里要"取价值最高的动作"(\(\max_a Q(s',a)\))——max 操作会**专挑那个被高估得最多的动作**。因为一个动作被高估,它的 \(Q\) 值就虚高,更容易在 max 里胜出。于是 max 系统性地偏向"高估的那些",选出的最大值期望上高于真实最大值。这个偏差不会抵消,反而通过 TD 的 bootstrap(高估的值又被用来更新别的值)逐步累积、放大。
打个比方:让一群人估计同一个量,每人有随机误差。如果你取所有估计的平均,误差抵消、接近真值。但如果你**总是采信"估得最高"的那个人**,你系统性地偏向了高估——这正是 max 操作干的事。**取两个 Q 的较小值**为什么能缓解?因为它反着来——在两个独立的高估里取较小的那个,相当于"对乐观打个折",把 max 带来的系统性高估往回压。这就是 clipped double-Q 的朴素而有效的直觉。
TD-MPC2 用一个 Q 集成(num_q 个 Q 网络,每个带 dropout),计算价值时从集成里**随机取两个、取较小值**(或平均)。取较小值抑制了乐观偏差——单个网络偶尔高估,取较小值能压下去。集成 + dropout 进一步增加多样性、提升鲁棒性。
为什么过估计对 TD-MPC 尤其要紧?因为 §6.4 讲过,TD-MPC 的规划**高度依赖价值**(终端价值补长期)。如果价值系统性高估,规划器会被"虚高的长期价值"误导,做出错误决策。所以抑制过估计不是可选项,而是保证规划质量的必需——这也是 TD-MPC 一丝不苟地从 SAC 借来双 Q/集成的原因。
读到这里你可能会问:价值过估计在 §6.8 还会作为开放问题出现,这里的双 Q 不是已经解决了吗? 双 Q 缓解了"函数近似误差导致的过估计"这一类,但 §6.8 会讲一个更微妙、双 Q 解决不了的过估计来源——policy mismatch(规划器采的数据分布和价值学习假设的分布不一致)。这是 TD-MPC 后续工作(TD-M(PC)²)专门处理的开放问题。所以这里先记住"双 Q 解决了一部分过估计",§6.8 再讲"还有一部分没解决"。
一个关键细节:为什么沿多步 rollout 训练,而非单步¶
回看联合损失的公式——它对 \(t=0,\dots,H\) 沿一段多步 rollout 累积损失,而非只在单步上训练。这是 TD-MPC 一个重要但容易被忽略的设计,值得专门点出。
朴素的想法是:训练动力学 \(d_\theta\),只要保证"单步预测准"就行——给定 \((z_t, a_t)\),让 \(d_\theta(z_t,a_t)\) 接近真实下一 latent 即可。但 TD-MPC 不这么做,它从初始 latent \(z_0\) 出发,用 \(d_\theta\) 递推多步(\(z_1, z_2, \dots, z_H\),每步都喂自己上一步的输出),然后要求每一步的递推 latent 都接近对应的真实 latent。
为什么要这样?因为这直接针对 §6.8 的 compounding error。单步训练只保证"一步准",但规划时要 rollout 多步——多步 rollout 里,模型吃的是自己上一步的(有误差的)输出,误差会累积。 如果训练时只在单步上优化,模型从没"练习过"在自己的预测上继续预测,规划时一旦多步 rollout、误差累积,它就力不从心。
沿多步 rollout 训练,等于让模型在训练时就**练习"在自己的预测基础上继续预测"**——梯度通过多步 rollout 反向传播,逼模型不仅单步准,还要"多步递推也别偏太多"。这显著缓解了误差累积:模型学会了"即便我上一步的预测有点误差,下一步也要尽量拉回正轨"。这正是调研里 TD-MPC 论文强调的——动力学通过多步 rollout 反向传播梯度来缓解误差累积。
本质洞察:沿多步 rollout 训练,是 TD-MPC 在"训练目标"和"使用方式"之间保持一致的体现。一个常见的机器学习陷阱是"训练和测试不一致"——训练时优化的目标,和实际使用时的需求不匹配。单步训练就犯了这个错:训练优化"单步准",使用时却要"多步 rollout 准"。TD-MPC 的多步训练把训练目标对齐到了使用方式——既然规划要多步 rollout,训练就在多步 rollout 上优化。这种"让训练模拟测试时的真实使用"的思想,在机器学习里反复出现(如 scheduled sampling、序列模型的 teacher forcing 与 free-running 之争)。它给你的启示是:设计训练目标时,要问"我实际怎么用这个模型",让训练尽量贴近真实使用,而非优化一个方便但失配的代理目标。
把训练流程串起来¶
把训练的全貌串成一个循环,看四个网络如何协同更新:
TD-MPC 训练循环(一次迭代):
1. 从 replay buffer 采一批长度 H 的轨迹段 (o₀,a₀,r₀,o₁,...)
2. 编码初始观测: z₀ = h_θ(o₀)
3. 沿轨迹 rollout 并累积三项损失:
for t = 0..H:
① latent 一致性: ‖z_t - sg(h_θ(o_t))‖² ← 逼动力学预测准(latent 层面)
② reward 预测: (r_θ(z_t,a_t) - r_t)² ← 逼 reward 准, 塑造编码器
③ TD/价值: (Q_θ(z_t,a_t) - Q_target)² ← 用 TD 学长期价值
z_{t+1} = d_θ(z_t, a_t) ← 动力学递推到下一步
4. 联合反向传播, 更新编码器/动力学/reward/价值四个网络
5. (单独) 用最大熵目标更新 policy prior π(z)
6. 软更新目标网络 Q_θ̄ ← τ Q_θ + (1-τ) Q_θ̄
关键: 四个网络共享编码器、联合训练——编码器学出的 latent 要同时让三项损失都小
读这个循环,抓住几个要点:
四个网络联合训练、共享编码器。 这是关键——编码器 \(h_\theta\) 同时服务于三项损失(latent 一致性要它编码得能预测、reward 预测要它编码 reward 相关信息、价值要它编码价值相关信息)。三项损失一起反向传播,逼编码器学出"对决策有用的、任务导向的"latent。这种联合训练是 TD-MPC 各组件能协同工作的根本——它们不是各学各的,而是被一个联合损失绑在一起、互相塑造。
latent 一致性防塌缩、reward/价值塑造内容。 单看 latent 一致性,编码器可以作弊地把所有 latent 塌成一个点(那样递推和编码都一样、损失为零)——这就是平凡解。防止它的是 reward/价值损失:要预测准不同状态的 reward 和价值,latent 必须对不同状态有判别力,不能塌成一个点。加上 stop-gradient(只更新递推侧、不更新编码靶子),三项损失合起来逼出一个"有判别力、任务导向、动态自洽"的 latent。
policy prior 单独用最大熵目标训练。 policy prior \(\pi\)(§6.3 规划用它采样)用类 SAC 的最大熵目标训练——让它在最大化 \(Q\) 的同时保持一定的熵(探索性)。它和价值一起构成"价值 + 策略"的 model-free 内核,嵌在 TD-MPC 的 model-based 框架里。
这里有一个值得点明的"互相促进"循环。policy prior 和价值不是各学各的,而是彼此成全:价值 \(Q_\theta\) 告诉 policy prior "什么动作长期回报高"(policy 的训练目标就是最大化 \(Q\)),于是 policy 学着输出高价值的动作;反过来,更好的 policy 让规划(§6.3 掺入 policy 采样)找到更好的轨迹、采集更优的数据,又让价值学得更准。价值教策略、策略助价值——这是一个正反馈的自举循环,和 SAC 里 actor(策略)与 critic(价值)互相促进的结构一脉相承(你的 SAC 基础直接迁移)。
更巧的是,这个"价值 + 策略"的 model-free 内核,恰好嵌在 TD-MPC 的 model-based 框架里,各自发挥所长:model-free 内核(价值 + 策略)负责"摊销长期知识"(价值概括长期、策略给好动作起点),model-based 部分(latent 模型 + 规划)负责"在线精炼"(用模型 rollout 在策略起点上精修)。这正是 §6.3 那个"摊销 + 即时"双层结构的训练侧根基——策略和价值在训练时摊销地学好"长期知识",规划在推理时即时地用模型精炼。两者的咬合,让 TD-MPC 既有 model-free 的高效摊销,又有 model-based 的在线灵活。
下面给出训练一步的最小代码骨架,对照上面的流程:
def train_step(model, target_model, batch, H=5, gamma=0.99,
c1=1.0, c2=0.5, c3=0.1, rho=0.5):
obs, actions, rewards = batch # obs:(H+1,B,obs_dim), actions/rewards:(H,B,...)
z = model.encode(obs[0]) # 初始 latent z₀
loss, discount = 0.0, 1.0
for t in range(H):
# ② reward 预测损失
r_hat = model.reward_(z, actions[t])
L_reward = ((r_hat - rewards[t])**2).mean()
# ③ TD/价值损失: 用真实下一观测编码 + 目标网络算 TD 目标
with torch.no_grad():
z_next_true = model.encode(obs[t+1]) # 真实下一 latent
a_next = model.pi_action(z_next_true) # policy prior 选动作
Q_target = rewards[t] + gamma * target_model.Q(z_next_true, a_next)
Q_hat = model.Q_train(z, actions[t]) # 主网络 Q(训练时用全部集成)
L_value = ((Q_hat - Q_target)**2).mean()
# 动力学递推到下一 latent, 算 ① latent 一致性
z = model.next(z, actions[t]) # 想象的下一 latent
with torch.no_grad():
z_target = model.encode(obs[t+1]) # 真实下一 latent(stop-grad)
L_consistency = ((z - z_target)**2).mean()
# 三项加权累积(按时间步衰减 rho^t)
loss += (discount) * (c1*L_consistency + c2*L_reward + c3*L_value)
discount *= rho
loss.backward() # 联合反向传播, 更新四个网络
# (另: 更新 policy prior 的最大熵目标, 软更新目标网络——略)
return loss.item()
这段代码把三项损失的计算和动力学递推串在一个循环里,和上面的流程图一一对应。它刻意简化(省了 policy 更新、目标网络软更新、离散回归等细节),但骨架和官方实现一致:一个循环里同时算 latent 一致性、reward、TD 三项损失,联合反传更新所有网络。
TD-MPC 的完整生命周期:训练与规划如何咬合¶
到这里,TD-MPC 的两大半——规划(§6.3–§6.4)和训练(本节)——都讲完了。最后把它们咬合成一个完整的 RL 智能体的运行周期,你才能看清这是一个自我改进的闭环,而非孤立的规划器或训练器。
TD-MPC 完整生命周期(一个自我改进的闭环):
┌─────────────────────────────────────────────────────────────┐
│ │
▼ │
[规划决策] 用当前世界模型 plan(§6.3-6.4): 编码→latent rollout │
│ →终端价值→采样更新→输出动作 │
▼ │
[环境交互] 执行动作, 观测下一状态和 reward │
│ │
▼ │
[存入buffer] 把 transition (o,a,r,o') 存进 replay buffer │
│ │
▼ │
[训练更新] 从 buffer 采轨迹段, 用三项损失(§6.5)更新世界模型: │
│ latent一致性 + reward + TD价值 → 模型变好 │
│ │
└──────────────────────────────────────────────────────────────┘
模型变好 → 规划更好 → 采集更优数据 → 模型更好...
读这个闭环,抓住"规划"和"训练"如何互相喂养:
规划用模型、训练改模型,两者互为因果。 规划用当前世界模型做决策(用得好不好取决于模型质量);决策产生的交互数据又用来训练、改进模型;改进后的模型让下一轮规划更好……这是一个正反馈的自我改进循环。这也是为什么 TD-MPC 是一个**完整的强化学习算法**,而不只是一个规划器——它包含了"用模型决策"和"从经验改进模型"的完整闭环。
规划器的双重身份再次显现。 §6.5 开头说过规划器既是决策者又是数据采集者,这个闭环把它具象化了:同一个 plan,既为"当前要执行什么"服务(决策),又为"采集什么数据来训练"服务(探索)。这个双重身份是力量来源(规划采的数据通常质量高,因为规划本身在优化),但也是 §6.8 那个 policy mismatch 问题的温床(规划采的数据分布和价值学习的假设不完全一致)。
读到这里你可能会问:这个闭环和纯 model-free(如 SAC)的 RL 闭环有什么区别? 区别在中间的"规划"和"训练"两环。SAC 的闭环是"用策略决策→交互→存 buffer→训练策略和价值",它的决策是一次策略网络前向(无规划)、训练只更新策略和价值(无世界模型)。TD-MPC 的闭环是"用世界模型规划决策→交互→存 buffer→训练世界模型(含动力学)",它的决策是在线规划(用模型 rollout)、训练要学一个完整的世界模型(多了动力学和 latent)。所以 TD-MPC 比 SAC "重"(要学模型、要在线规划),但换来了 model-based 的样本效率和规划的灵活——这又回到了 §6.1 的"融合 model-based 和 model-free"。
⚠️ 常见陷阱¶
概念误区:以为 TD-MPC 的世界模型要靠"重建观测"来训练。 错误认识:既然是世界模型,就以为训练时要让它重建观测(像自编码器/Dreamer),用重建损失。 现象/后果:误以为要训一个解码器、做像素重建,高估复杂度;也不理解 latent 一致性损失的作用,抓不住"任务导向"的精髓。 根本原因:混淆了重建式训练(Dreamer/PlaNet,用重建损失)和 TD-MPC 的 latent 一致性训练(在 latent 空间内部比较递推 latent 和编码 latent,不碰观测)。TD-MPC 没有重建损失、没有解码器。 正确做法:把 TD-MPC 的训练理解为"latent 一致性(动态自洽)+ reward 预测 + TD 价值"三项联合损失,全程不重建观测。latent 里编码什么由 reward/价值任务隐式决定,这是它高效的根源。
编程陷阱:latent 一致性损失忘记对编码目标 stop-gradient,导致 latent 塌缩。
错误做法:算 latent 一致性 \(\|z_t - h_\theta(o_t)\|^2\) 时,对两侧都回传梯度(不 stop-gradient 编码目标那一侧)。
现象/后果:编码器找到平凡解——把所有观测都编码成同一个点(或一个很小的区域),这样递推 latent 和编码 latent 自然一致、损失趋零,但 latent 失去判别力,整个模型废掉。
根本原因:如果编码目标也回传梯度,损失可以通过"让所有 latent 变得一样"来降低(塌缩捷径),而非通过"让动力学预测准"。stop-gradient 把编码目标固定成靶子,堵死这条捷径,逼损失只能靠"预测准"来降低。
正确做法:latent 一致性损失里,编码目标 \(h_\theta(o_t)\) 必须 stop-gradient(detach() / torch.no_grad()),只让递推侧 \(z_t\) 回传梯度。同时靠 reward/价值损失提供判别力信号——三者合起来才能学出有意义的 latent。这是自监督/世界模型里防塌缩的标准手法。
思维陷阱:以为四个网络可以分开、独立训练。 错误认识:编码器、动力学、reward、价值是四个网络,那分别训练(先训编码器,再训动力学……)应该也行、还更简单。 现象/后果:分开训练得到的 latent 不是"任务导向"的——比如先单独训一个重建式编码器,latent 会编码无关细节;之后再训动力学/价值,它们被迫在一个不适合决策的 latent 上工作,性能差。 根本原因:TD-MPC 的威力来自"联合训练、共享编码器"——编码器学出的 latent 要同时让动力学、reward、价值都好预测,这种联合约束才逼出"任务导向"的 latent。分开训练割裂了这种约束,latent 不再为下游决策定制。 正确做法:四个网络(共享编码器)用一个联合损失同时训练,让三项损失一起塑造编码器。这是 TD-MPC 各组件协同的根本,不能为了"简单"而拆开。policy prior 可以用单独的最大熵目标更新,但它依赖的价值仍来自联合训练的世界模型。
练习¶
-
(损失梳理,⭐⭐) 不看正文,写出 TD-MPC 联合损失的三个部分,各自逼哪个(些)网络学什么。然后回答:(a) 哪一项防止 latent 塌缩需要 stop-gradient?(b) 哪一项让编码器变得"任务导向"?(c) 哪一项是把长期价值学进来的?
-
(latent 一致性 vs 重建,⭐⭐⭐,思考题) TD-MPC 用 latent 一致性而非重建观测。请论证:(a) 对一个像素观测任务,"重建损失"和"latent 一致性损失"分别逼编码器编码哪些信息?(b) 为什么 latent 一致性能让模型"任务导向、容量不浪费"?(c) latent 一致性有塌缩风险(平凡解),它靠什么(stop-gradient + 哪些损失)避免塌缩?(d) 这种"在表示空间自洽、不重建输入"的思想,你在自监督学习里见过吗(如对比学习、BYOL)?把共性讲清楚。
-
(训练一步实现,⭐⭐⭐) 基于本节
train_step骨架,补全并跑通一个最小训练循环(可以用一个简单环境如 Pendulum,或干脆用随机生成的 transition 验证损失能下降)。重点确认:(a) 三项损失都在一个循环里计算、联合反传;(b) latent 一致性的编码目标做了 stop-gradient;(c) TD 目标用了目标网络和真实下一观测。然后实验:去掉 latent 一致性损失(只留 reward + 价值),观察 latent 是否塌缩、规划性能是否下降——亲手验证 latent 一致性的必要性。
§6.6 TD-MPC2 规模化:一套超参通吃 100+ 任务 ⭐⭐¶
动机:从"每任务精调的原型"到"一套方法通吃"¶
§6.2–§6.5 讲的是 TD-MPC(2022)的核心思想。但 TD-MPC 有个现实痛点:它是**单任务**的,且每个任务往往要调超参才能работать好。这在研究里可以接受,但离"一套通用控制器"还很远。2024 年的 TD-MPC2 就是来跨越这道坎的——它的目标是**鲁棒性和规模化**:用单一超参集覆盖所有任务、并随模型和数据规模持续提升。这一节讲 TD-MPC2 在 TD-MPC 基础上做了哪些关键改进、为什么这些改进能带来规模化。
先把成就摆出来,你才知道这些改进通向何方:TD-MPC2 在 104 个在线 RL 任务、4 个任务域上用单一超参集显著超越基线;并训练了单个 317M 参数的 agent 执行 80 个跨域、跨实体、跨动作空间的任务。104 任务覆盖 DMControl(39)、Meta-World(50)、ManiSkill2(5)、MyoSuite(10),超越 SAC、DreamerV3 和 TD-MPC。这是从"单任务原型"到"通用世界模型"的跨越。
读到这里你可能会问:"单一超参覆盖 104 任务"听起来不错,但它真有那么难、那么重要吗? 值得专门体会一下这件事的分量,因为它是 TD-MPC2 最核心的贡献,也是 RL 长期的痛点。
它很难。 RL 算法出了名地对超参敏感——同一个算法,换个任务往往要重调学习率、折扣、网络大小、探索强度等一大堆超参才能work好。一个在 Walker 上调好的 RL 智能体,搬到 Humanoid 或机械臂上,很可能直接崩,要重新调参。这种"逐任务调参"既耗费大量人力(调参是 RL 研究里最痛苦的部分之一),又让方法难以规模化(你不可能为 100 个任务各调一套超参)。所以"一套超参在所有任务上都work好"是一个长期可望不可即的目标。
它很重要。 想想深度学习里的转变——从"每个任务设计专门的网络、调专门的超参",到"一套 Transformer 架构 + 大数据通吃语言/视觉"。这个"通用化"是深度学习能规模化、能造大模型的前提。RL 要走向"通用智能体""具身大模型",同样需要先迈过"一套方法通吃多任务"这道坎。TD-MPC2 的"单一超参覆盖 104 任务"正是在这个方向上的关键一步——它证明了"学习世界模型 + 规划"这套方法可以做到通用化、可以随规模提升,而非停留在"每任务精调的研究原型"。
所以当你看到"104 任务、单一超参、317M 模型做 80 任务"这些数字时,要意识到它们背后是 RL 一个长期目标的兑现:让一套方法、一套超参,像深度学习的通用架构那样,覆盖大量不同任务、并随规模变强。 这才是 TD-MPC2 真正的分量所在——不只是"又一个 SOTA",而是"让 model-based RL 走向通用"的一次实质推进。
改进一:implicit(decoder-free)world model——连 latent 重建都不要了¶
§6.2 讲过 TD-MPC 不重建观测、用 latent 一致性。TD-MPC2 把这个思想推到极致:它是一个 implicit(decoder-free,无解码器)world model——彻底没有任何解码器,连"从 latent 重建出什么"都不做。
这听起来和 TD-MPC 的 latent 一致性差不多,但有微妙区别。TD-MPC 的 latent 一致性是"递推 latent 接近编码 latent"(在 latent 空间比较)。TD-MPC2 进一步明确:整个模型就是一组"latent 进、latent/标量出"的网络,从设计上就不存在"解码回观测"的通路。这种彻底的 decoder-free 设计,把"任务导向"贯彻到底——模型的每一个参数都只服务于"预测 reward/价值/下一 latent",没有一个参数浪费在重建上。
为什么这对规模化重要?因为当你要用**一个模型覆盖很多任务**(不同观测、不同动作空间)时,"重建观测"会变成灾难——不同任务的观测千差万别(有的是状态向量、有的是像素、维度各异),逼一个模型重建所有这些观测几乎不可能。而 decoder-free 模型只在 latent 空间工作,不管原始观测长什么样,都先编码进统一的 latent 空间——这让"一个模型吃多种观测"成为可能。
改进二:稳定训练的架构细节——让模型能"长大"¶
要规模化(模型变大、任务变多),训练稳定性是关键。模型一大、任务一杂,梯度容易爆炸、不同任务的 reward 量级差异会搞乱训练。TD-MPC2 引入了一系列架构改进来稳住训练,逐一简述:
SimNorm(simplicial normalization,单纯形归一化)——稳定 latent 尺度。 latent 动力学的输出经过 SimNorm:把 latent 向量分成若干小组,每组做 softmax 归一化。这让每组 latent 变成一个"概率单纯形上的点"(各维非负、和为 1),从而 latent 的尺度被严格约束、不会在多步 rollout 里发散。这是 TD-MPC2 能稳定 rollout 的关键之一——回忆 §6.2 提过动力学输出过 SimNorm,这里讲清了它的作用:约束 latent 尺度、防止训练和 rollout 发散。
为什么 latent 尺度会发散、SimNorm 又怎么防住,值得多说一句。回忆 §6.5——训练时动力学要沿多步 rollout 递推(\(z_{t+1}=d_\theta(z_t,a_t)\),每步喂自己上一步的输出)。如果不加约束,latent 的数值可能在递推中越来越大(或越来越小)——比如动力学网络若整体倾向于"放大"输入,多步递推后 latent 范数就指数级膨胀,最终数值爆炸、训练发散(这正是 §6.8 故障场景六里"latent 多步 rollout 数值发散"的来由)。
SimNorm 用一个巧妙的方式根除这个隐患:它把 latent 切成若干小组,每组过 softmax。softmax 的输出天然满足"各维非负、和为 1"——也就是说,每组 latent 被强制变成一个"概率分布",它的范数被严格限制在一个固定范围内,无论动力学网络怎么放大输入,输出过了 SimNorm 都会被拉回到这个有界范围。于是多步递推时,latent 尺度永远稳定、不会发散。这是个比单纯加 LayerNorm 更强的约束——它不只是归一化,而是把 latent 限制在一个几何结构(概率单纯形)上,从根本上杜绝了尺度发散。这也是为什么 SimNorm 被认为是 TD-MPC2 能稳定训练大模型、稳定多步 rollout 的关键设计之一。
LayerNorm + Mish 激活——稳定深层网络。 各 MLP 用 LayerNorm(层归一化)和 Mish(一种平滑激活函数)替代朴素的全连接 + ReLU。这些是深度学习里稳定训练、防止梯度问题的标准手段,让网络能堆得更深、训得更稳。
reward 和价值用离散回归(discrete regression)——对 reward 量级鲁棒。 这是个对规模化特别重要的改进。不同任务的 reward 量级可能差几个数量级(有的任务 reward 在 0~1,有的在 0~1000)。如果直接回归标量 reward/价值,这种量级差异会让训练在不同任务间失衡。TD-MPC2 把 reward 和价值预测改成**在对数变换空间里的离散回归**——把 reward 范围分成若干 bin,预测一个分布(用 two-hot 编码),再解码回标量。这种"分类式回归"对 reward 量级的剧烈变化鲁棒得多,是"单一超参覆盖不同 reward 量级任务"的技术基础。
读到这里你可能会问:"把标量变成分布再解码回标量"具体怎么做?为什么这样就对量级鲁棒了? 用一个小例子说清 two-hot 编码。设想把价值范围 \([0, 10]\) 分成 11 个 bin(\(0, 1, 2, \dots, 10\))。要表示一个标量值比如 3.7,two-hot 不是只在某个 bin 上标 1,而是在它**相邻两个 bin** 上按距离分配概率——3.7 落在 bin=3 和 bin=4 之间,于是给 bin=3 分配 0.3 的概率、给 bin=4 分配 0.7 的概率(越近的 bin 概率越大)。这就把"3.7"这个标量编码成了一个分布(两个相邻 bin 上的概率,故称 two-hot)。解码(two_hot_inv)时反过来——对所有 bin 的值按概率加权求和:\(3 \times 0.3 + 4 \times 0.7 = 3.7\),还原回标量。
为什么这样对量级鲁棒?因为网络现在输出的是"在各 bin 上的概率分布"(一个分类问题),用交叉熵损失训练,而非直接回归一个可能很大的标量。分类损失对目标值的绝对大小不敏感——无论真值是 3.7 还是 370,网络都只是在学"概率该集中在哪几个 bin",损失的尺度不会随真值量级暴涨。而直接回归标量时,大量级任务的平方误差会远大于小量级任务,主导训练。配合对数变换(先把 reward 取对数再分 bin,进一步压缩量级差异),离散回归就能让一套超参在 reward 量级差几个数量级的任务间都稳定训练。这就是它支撑"单一超参覆盖不同 reward 量级任务"的原理。
Q 函数集成——抑制过估计(§6.5 讲过)。 TD-MPC2 用 num_q 个 Q 网络的集成(带 dropout),计算价值时随机取两个、取较小值/平均。这抑制了价值过估计(§6.5),对规模化重要——任务一多,过估计的风险更大。
读到这里你可能会问:这么多改进(SimNorm、LayerNorm、Mish、离散回归、Q 集成),哪个最关键? 没有单一的"最关键",它们是一个**协同的稳定化套件**——共同目标是"让模型能在多任务、大规模下稳定训练"。但若一定要点出灵魂,是 SimNorm(稳 latent 尺度)和离散回归(稳不同 reward 量级)这两个,因为它们直接针对"规模化时最容易崩的两件事":latent 发散和 reward 量级失衡。其余是深度学习通用的稳定化手段。
改进三:多任务支持——可学习任务嵌入 + 动作 masking¶
要让一个模型做多个任务,得解决"不同任务的观测和动作空间不同"的问题。TD-MPC2 的做法:
可学习的任务嵌入(learnable task embedding)。 每个任务有一个可学习的嵌入向量,拼到 latent 上,告诉模型"现在在做哪个任务"。这让一个模型能根据任务嵌入调整自己的行为,而不需要为每个任务单独一个模型。
动作 masking。 不同任务的动作维度不同(有的 6 维、有的 39 维)。TD-MPC2 用统一的最大动作维度,对每个任务把无效的动作维度 mask 掉(置零、不参与)。这让一个统一的网络能处理不同动作维度的任务。
这两个设计合起来,让单个 317M 模型能做 80 个跨域、跨实体、跨动作空间的任务——观测和动作空间的差异被任务嵌入和 masking 吸收,模型内部在统一的 latent 空间工作。
读到这里你可能会问:不同任务动作维度不同(有的 6 维、有的 39 维),一个固定结构的网络怎么可能同时处理? 这个困惑值得讲清,因为它是多任务规模化最实际的障碍。
动作 masking 的思路其实朴素:用一个统一的"最大动作维度",对每个任务把多余的维度屏蔽掉。 比如所有任务里最大动作是 39 维,那网络的动作接口就固定 39 维。一个 6 维动作的任务,就用前 6 维、把后 33 维 mask 掉(置零、不参与计算、不算损失)。这样,一个固定 39 维接口的网络,就能"装下"所有维度不超过 39 的任务——小维度任务只是没用满接口而已。
观测维度的差异也类似处理(统一接口 + 任务嵌入告诉模型"现在是哪个任务、该怎么解读这些维度")。任务嵌入则像一个"任务身份证"——拼到 latent 上,让模型知道当前在做哪个任务,从而对同样的 latent 做出任务相关的不同反应。
把这两个机制合起来看,它们解决的是"异构任务的统一表示"问题:不同任务的观测/动作空间千差万别,但通过"统一最大接口 + masking + 任务嵌入",它们被塞进了一个统一的网络结构。 模型内部仍在一个共享的 latent 空间工作,跨任务的共性(如"如何控制一个动态系统")可以共享、被复用,而任务的特异性由任务嵌入和 masking 区分。这正是单个 317M 模型能做 80 个跨域、跨实体、跨动作空间任务的技术基础——共性共享、特异性区分。
改进四:规划与 policy prior 的简化¶
TD-MPC2 也调整了规划和策略:
规划时移除 MPPI 迭代间的动量。 TD-MPC 原版在 MPPI 迭代间保留动量(用上一轮的分布影响这一轮),TD-MPC2 移除了它、简化了规划。这个简化在配合 policy prior 后不损失性能、反而更稳。
最大熵 policy prior(类 SAC)。 §6.5 提过——TD-MPC 原版用确定性 prior + 高斯噪声,TD-MPC2 改用类 SAC 的最大熵随机 policy prior。这提供更好的探索和规划初始化,且在多任务下更一致。集成 policy prior 也加速了规划收敛。
如果不做这些工程改进会怎样¶
为了让"这些工程改进为什么必需"更清楚,反过来想一想:如果直接拿 TD-MPC(2022)去做 TD-MPC2 想做的事(单一超参覆盖 100+ 任务、训 317M 大模型),会撞上什么墙?
没有 SimNorm:latent 在多步 rollout 中尺度失控、可能发散,训练不稳定——任务一多、模型一大,这个问题更突出,训练容易崩。
没有离散回归:不同任务 reward 量级差几个数量级,直接回归标量会让训练被大量级任务主导、小量级任务学不好——"单一超参覆盖不同 reward 量级任务"根本无从谈起。
没有 Q 集成(只用双 Q):任务一多、维度一高,价值过估计的风险更大,双 Q 可能不够压,规划被虚高价值误导。
没有任务嵌入 + 动作 masking:根本无法用一个模型处理不同观测/动作空间的任务——多任务直接做不了。
没有这些,TD-MPC 就停留在"单任务、需逐任务调参、规模上不去"的状态——这正是 TD-MPC(2022)的局限。TD-MPC2 的每个改进,都是在拆掉规模化路上的一堵墙。把它们合起来,才让"一套超参通吃、随规模提升"成为可能。
这个反事实印证了 §6.6 的本质洞察:核心思想(latent 模型 + 终端价值 + TD)是地基,但要把地基上的房子盖大盖稳,需要一整套工程改进。好想法 + 好工程,缺一不可——TD-MPC 提供了前者,TD-MPC2 补齐了后者。
TD-MPC2 默认超参一览¶
把 TD-MPC2 的关键默认超参列出来,让"单一超参集"具体化(注意这些值跨所有任务不变,正是"单一超参"的含义):
| 参数 | 默认值 | 含义 |
|---|---|---|
| 规划 horizon | 3 | 短 horizon(靠价值补长期)。注:TD-MPC 原版用 5,TD-MPC2 默认 3 |
| 采样数 num_samples | 512 | 每次规划采的动作序列数 |
| 精英数 num_elites | 64 | 用于更新分布的精英序列数 |
| 迭代次数 iterations | 6 | 采样优化迭代轮数(动作维度≥20 时 +2) |
| policy 轨迹数 num_pi_trajs | 24 | 从 policy prior 采的轨迹数(混入采样) |
| 单任务模型大小 | 5M 参数 | 单任务在线 RL 的默认模型 |
| 多任务模型大小 | 1/5/19/48/317M | 多任务可选规模(越大越强) |
| 折扣 gamma | 启发式 | 按 episode 长度自适应:\(\min(\max(\frac{\text{ep}/5-1}{\text{ep}/5}, 0.95), 0.995)\) |
注意几个数:horizon 只有 3(再次印证 §6.4 的核心洞察——短 horizon 靠价值补长期),单任务模型才 5M 参数(任务导向、不浪费容量),迭代对大动作空间自适应 +2(动作维度≥20 时多 2 轮迭代,因为高维动作空间更难优化)。这些数字让"短 horizon + 学习价值 + 任务导向小模型"这套设计落到了具体。
读到这里你可能会问:单任务才 5M 参数,对比动辄上亿参数的大模型,这么小够吗? 够,而且这恰恰印证了"任务导向"的省(§6.2)。单个连续控制任务的内在复杂度其实不高——它要学的只是"这个任务相关的动态和价值",不是"理解整个世界"。5M 参数足以编码单任务的 latent 动力学和价值。需要大模型(19/48/317M)的是**多任务**场景——一个模型要同时装下几十上百个任务的知识、跨域跨实体,这才需要更大的容量。所以"单任务小、多任务大"不矛盾:模型大小该匹配"要装多少任务知识",而非盲目追求大。这也是 §6.6 本质洞察说的"模型大小按任务复杂度选、从小起步"的具体体现——单任务用 5M、多任务按需放大。
本质洞察:TD-MPC2 的所有改进,服务于一个共同的目标——让"学习世界模型 + 规划"这套方法从'需要专家逐任务调参的脆弱原型',变成'一套超参通吃、随规模提升的鲁棒系统'。 这个转变的意义,不亚于深度学习史上从"逐任务精调的小网络"到"一套架构 + 大数据通吃"(如 Transformer)的转变。它揭示了一个深刻的工程规律:一个方法要真正可用、可规模化,光有好的核心思想不够,还需要一整套"稳定化、统一化"的工程改进——SimNorm 稳 latent、离散回归稳 reward 量级、任务嵌入 + masking 统一不同任务、Q 集成稳价值。这些改进单看都是"工程细节",合起来却是"能不能规模化"的分水岭。这也给你一个做研究/工程的启示:不要轻视"让方法稳定、统一"的工程工作——它们往往是把一个漂亮想法推向真正通用的临门一脚。TD-MPC 提出了核心思想,TD-MPC2 用工程把它变成了通用控制器,两者缺一不可。
旁车对比:TD-MPC 和 Dreamer 怎么选¶
学习世界模型这条线上,最常被拿来和 TD-MPC 比较的是 Dreamer 系列(DreamerV1/2/3,Hafner 等)。两者都是"学一个 latent 世界模型"的代表,但在两个关键设计上分道扬镳,理解这个区别能帮你在实践中选型。
区别一:重建式 vs 任务导向。 Dreamer 的 latent 是**重建式**的——它学一个能重建观测的 latent(含一个解码器,能从 latent 还原图像)。TD-MPC(尤其 TD-MPC2)是**任务导向、decoder-free** 的——latent 不重建任何东西,只为预测 reward/价值服务(§6.2、§6.6)。这是两者最根本的区别:Dreamer 要"理解整个世界"(能重建),TD-MPC 只要"理解与任务相关的世界"(能预测回报)。
区别二:想象优化 vs 在线规划。 这是决策方式的区别。Dreamer 用学好的世界模型在"想象"里**训练一个策略**(在 latent 里 rollout、用策略梯度优化策略),决策时直接用这个策略、不在线规划。TD-MPC 用世界模型做**在线采样规划**(每步用 MPPI/CEM 在 latent 里搜索,§6.3)——它有一个 policy prior,但最终动作来自在线规划而非直接用策略。简言之:Dreamer 把模型用于"离线训策略",TD-MPC 把模型用于"在线规划"。
把这两个区别列成表:
| 维度 | Dreamer 系列 | TD-MPC 系列 |
|---|---|---|
| latent 类型 | 重建式(有解码器、重建观测) | 任务导向(decoder-free、不重建) |
| 模型用途 | 在想象里训练策略 | 在线采样规划 |
| 决策方式 | 直接用训好的策略(快) | 在线规划(每步搜索) |
| 决策计算量 | 低(一次策略前向) | 高(每步采样规划) |
| 对模型误差 | 想象 rollout 可能较长,更受累积误差影响 | 短 horizon 规划,累积误差小 |
| 典型优势 | 决策快、想象高效 | 在线规划灵活、短 horizon 鲁棒 |
读这张表,没有绝对赢家——这又是一个权衡。Dreamer 决策快(训好策略后一次前向),适合对决策延迟敏感、或想充分利用"想象"训练的场景;TD-MPC 在线规划更灵活、短 horizon 对模型误差更鲁棒,适合愿意花在线计算换决策质量、或模型误差需要短 rollout 控制的场景。TD-MPC2 论文报告它在多个基准上超越 DreamerV3,但这不意味着 Dreamer 过时——两者的设计哲学不同,各有适用场景。
读到这里你可能会问:能不能取两者之长——任务导向的模型 + 想象训练 + 在线规划都要? 这正是研究在探索的方向之一。两种思路(重建 vs 任务导向、想象训练 vs 在线规划)不是非此即彼,未来的方法可能融合它们。理解了这两个区别的本质(模型学什么、模型怎么用),你就能看懂任何新方法在这两个维度上的选择。
TD-MPC vs TD-MPC2 对照¶
把两代方法系统对照一次,看清规模化路径:
| 维度 | TD-MPC(2022) | TD-MPC2(2024) |
|---|---|---|
| 核心思想 | latent 模型 + 终端价值 + TD | 同左(继承) |
| 模型类型 | latent 一致性(不重建) | implicit/decoder-free(更彻底) |
| latent 归一化 | 无特殊归一化 | SimNorm(稳尺度) |
| 网络细节 | 朴素 MLP | LayerNorm + Mish |
| reward/价值预测 | 标量回归 | 离散回归(对量级鲁棒) |
| 价值过估计 | 双 Q | Q 集成(num_q 个 + dropout) |
| policy prior | 确定性 + 高斯噪声 | 最大熵(类 SAC) |
| 规划动量 | 有 | 移除(简化) |
| 任务范围 | 单任务、需调参 | 单一超参覆盖 104 任务 |
| 多任务 | 不支持 | 任务嵌入 + 动作 masking,单模型 80 任务 |
| 规模 | 较小 | 最大 317M(比 TD-MPC 多 300× 参数) |
盯住"核心思想"那行的"继承"——TD-MPC2 没有改核心思想(latent 模型 + 终端价值 + TD 还是那一套,§6.2–§6.5 讲的全部适用),它改的全是"让核心思想能规模化、鲁棒化"的工程。所以学懂了 TD-MPC,TD-MPC2 只是在它之上加了一层"稳定化 + 统一化"的工程改进——这也是本章把核心思想(§6.2–§6.5)和规模化(§6.6)分开讲的原因:思想是地基,规模化是把地基上的房子盖大盖稳。
一个对学习者的福利:丰富的开源资源¶
TD-MPC2 还有一点值得专门提,因为它对你这样的学习者是实打实的福利:它开源得非常彻底。 据其发布,TD-MPC2 公开了总计 324 个模型 checkpoint(含 12 个多任务模型,参数量从 1M 到 317M,分别在 80、70、30 个任务上训练),还发布了用于训练多任务模型的 545M 和 345M 规模的 transition 数据集,以及完整的训练和评估代码。
这对学习意味着什么?你不必有大量算力,也能上手最前沿的世界模型。 具体地:(a) 想理解 TD-MPC2 实际什么水平?下一个预训练 checkpoint,跑评估、看它怎么完成任务(§6.7 的入门路径),不用自己训;(b) 想研究多任务世界模型?直接用它的多任务 checkpoint 和数据集,省去从零训练大模型的巨大成本;(c) 想做研究、提改进?以官方代码和 checkpoint 为基线,你的改进能直接和它对比(§6.8 的 TD-M(PC)² 正是这么做的——在官方实现上加不到十行)。
这种"开源 checkpoint + 数据集 + 代码"的做法,大大降低了进入这个方向的门槛——你站在巨人的肩膀上起步,而非从平地造轮子。这也是 TD-MPC2 作者明确倡导的:让模型和数据成为社区资源,鼓励更多人参与 model-based RL 研究。对你而言,善用这些资源,是高效学习和切入这个方向的最快路径。
⚠️ 常见陷阱¶
概念误区:以为 TD-MPC2 是和 TD-MPC 完全不同的新算法。 错误认识:看到 TD-MPC2 一堆新名词(SimNorm、离散回归、implicit world model),以为它是个全新算法,要重新学。 现象/后果:重复学习核心思想,看不出 TD-MPC2 的核心(latent 模型 + 终端价值 + TD)就是 TD-MPC、改的只是工程;高估学习成本。 根本原因:没区分"核心思想"和"工程改进"。TD-MPC2 完全继承 TD-MPC 的核心思想(§6.2–§6.5),所有改进都是为了规模化和鲁棒化(稳定训练、统一多任务),不动核心。 正确做法:把 TD-MPC2 理解为"TD-MPC + 一套稳定化/统一化工程改进"。先吃透 TD-MPC 的核心思想,TD-MPC2 的改进就是在这之上的增量,逐个理解即可(SimNorm 稳 latent、离散回归稳 reward 量级、任务嵌入统一多任务……)。
思维陷阱:以为"单一超参覆盖所有任务"意味着这套超参对每个任务都最优。 错误认识:既然 TD-MPC2 用单一超参覆盖 104 任务,那这套超参对每个任务都是最优的。 现象/后果:误以为不需要任何任务特定调整、迷信默认超参在自己任务上也最优;遇到默认超参不够好的任务时困惑。 根本原因:"单一超参鲁棒"指的是"一套超参在所有任务上都能达到强性能(不崩、够好)",而非"对每个任务都是该任务的全局最优"。鲁棒性是"无需逐任务精调也能работать好",不是"放弃了逐任务优化的空间"。 正确做法:把"单一超参"理解为"强鲁棒的默认值"——它让你不必为每个任务调参就能得到好结果(这是巨大的实用价值),但若你愿意为某个特定任务精调,仍可能进一步提升。鲁棒默认 ≠ 每任务最优,但鲁棒默认已经足够好用,这正是它的价值。
练习¶
-
(改进梳理,⭐⭐) 列出 TD-MPC2 相对 TD-MPC 的主要改进,并按"目的"分类:哪些是为了**稳定训练**(让模型能长大)、哪些是为了**统一多任务**(让一个模型做多个任务)、哪些是为了**抑制过估计**?然后回答:这些改进有没有动 TD-MPC 的核心思想(latent 模型 + 终端价值 + TD)?
-
(为什么 decoder-free 利于规模化,⭐⭐⭐,思考题) TD-MPC2 是 implicit/decoder-free 的。请论证:(a) 如果要用一个模型覆盖很多观测差异巨大的任务(状态向量、像素、不同维度),"重建观测"会遇到什么困难?(b) decoder-free 如何绕开这个困难?(c) 这和 §6.2 讲的"任务导向"是什么关系——decoder-free 是不是"任务导向"的极致?
-
(离散回归的作用,⭐⭐⭐) TD-MPC2 用离散回归(对数空间 two-hot)预测 reward 和价值,而非直接回归标量。请论证:(a) 不同任务 reward 量级差几个数量级时,直接回归标量会遇到什么训练问题(提示:损失被大量级任务主导)?(b) 离散回归(分类式)为什么对量级鲁棒?(c) 这对"单一超参覆盖不同 reward 量级任务"为什么是必需的?如果你有兴趣,可以查一下 two-hot 编码的具体做法,理解它如何把一个标量表示成相邻两个 bin 上的概率。
§6.7 实战与代码精读:从 planning.py 到最小实现 ⭐⭐⭐¶
动机:把前几节的零件拼成能跑的东西¶
前面几节把 TD-MPC 的架构(§6.2)、规划(§6.3–§6.4)、训练(§6.5)、规模化(§6.6)讲透了。这一节落到实战——精读官方 planning.py 的真实结构,并把前几节的零件拼成一个最小可运行的 TD-MPC。目标是让你从"理解原理"走到"能读懂官方代码、能自己写一个最小版"。
官方代码地图:tdmpc2 仓库怎么读¶
TD-MPC2 的官方实现是 nicklashansen/tdmpc2。如果你要读它,这里给一张地图,告诉你各文件的职责、按什么顺序读:
common/world_model.py——世界模型定义(对应 §6.2):编码器、动力学、reward、policy、Q 集成五个组件,以及encode/next/reward/pi/Q等方法。先读这个,它是一切的基础。tdmpc2.py——核心算法类,包含两个最重要的方法:plan(规划,对应 §6.3–§6.4)和update(训练一步,对应 §6.5)。第二读plan,它是本章的规划核心;第三读update,它是训练核心。common/layers.py——网络层细节:SimNorm、Mish、mlp 工厂等(对应 §6.6 的架构改进)。读懂原理后,这里只是细节确认。config.yaml——所有超参(对应 §6.6 的超参表)。对照它确认 horizon、num_samples 等默认值。
读代码的正确姿势:先读 world_model.py 建立"五个组件"的认识,再读 plan 把它和 §6.3 的伪代码对应起来,最后读 update 把它和 §6.5 的三项损失对应起来。 不要一上来逐行啃——先用本章的概念框架定位每个文件/函数的职责,再深入细节。
换个比方:本章的八节就是一张"读代码的地图"——你已经在脑子里建好了 TD-MPC 的概念结构(四组件、latent 规划、终端价值、联合训练、规模化改进),读官方代码时,每读到一段,就把它"挂"到地图上对应的概念位置。这段是编码器(§6.2)、这段是 latent rollout(§6.3)、这段是终端价值(§6.4)、这段是 TD 损失(§6.5)……有了地图,再多的代码也不会让你迷路,因为你始终知道"现在读的这段,在整体里是哪个零件、解决什么"。没有地图地逐行啃,才是真正会迷失的读法。所以读代码前先把本章的概念框架装进脑子,是最高效的准备。
精读 plan:官方实现的关键结构¶
基于 TD-MPC2 官方实现,plan 函数(规划)的关键结构如下(简化标注,聚焦与 §6.3–§6.4 的对应):
@torch.no_grad()
def plan(self, obs, t0=False, eval_mode=False, task=None):
# 1. 编码 + 从 policy prior 采一部分轨迹(对应 §6.3 的 policy prior 混合)
z = self.model.encode(obs, task) # 观测 -> latent
if self.cfg.num_pi_trajs > 0: # 从 policy prior rollout 一部分轨迹
pi_actions = ... # 在 latent 空间用 π rollout num_pi_trajs 条
# 2. 初始化高斯分布 + warm-start(对应 §6.3)
mean = torch.zeros(self.cfg.horizon, self.cfg.action_dim)
if not t0 and hasattr(self, '_prev_mean'):
mean[:-1] = self._prev_mean[1:] # warm-start: 上周期解平移
std = self.cfg.max_std * torch.ones(...)
# 3. 采样优化迭代(对应 §6.3 的迭代循环)
for i in range(self.cfg.iterations):
actions = mean.unsqueeze(1) + std.unsqueeze(1) * torch.randn(...) # 采样
actions = torch.cat([actions, pi_actions], dim=1).clamp(...) # 混入 policy prior
value = self._estimate_value(z, actions, task) # 4. 评估: latent rollout + 终端价值
elite_idxs = torch.topk(value.squeeze(), self.cfg.num_elites).indices # 取精英
elite_value, elite_actions = value[elite_idxs], actions[:, elite_idxs]
# 5. MPPI 式加权更新(对应 §6.3 的更新)
score = torch.softmax(self.cfg.temperature * (elite_value - elite_value.max()), dim=0)
mean = (score.unsqueeze(0) * elite_actions).sum(dim=1) / (score.sum() + 1e-9)
std = torch.sqrt(...).clamp(self.cfg.min_std, self.cfg.max_std)
self._prev_mean = mean # 存下来供下周期 warm-start
return mean[0] # 执行第一个动作
而 _estimate_value(评估一批动作序列的回报)正是 §6.4 那个核心公式的实现:
@torch.no_grad()
def _estimate_value(self, z, actions, task):
G, discount = 0, 1
for t in range(self.cfg.horizon): # latent rollout H 步
reward = math.two_hot_inv(self.model.reward(z, actions[t], task), self.cfg) # 这一步 reward
z = self.model.next(z, actions[t], task) # latent 推进
G += discount * reward # 累积折扣 reward
discount *= self.discount
# 终端价值: π 在末端选动作, 用 Q 估长期价值(§6.4 核心)
return G + discount * self.model.Q(z, self.model.pi(z, task)[1], task, return_type='avg')
把这两段和本章对照,处处是熟悉的影子:encode 是 §6.2 的编码器、next/reward 是 latent rollout(§6.3)、G + discount * Q(...) 是终端价值(§6.4 那个 \(\sum\gamma^t r_t + \gamma^H Q\) 公式)、warm-start 和 softmax 加权更新是 §6.3 的采样规划内核。官方代码没有任何你没在本章见过的东西——它就是 §6.2–§6.4 的忠实实现。这正是本章反复强调的:读懂了原理,官方代码只是原理的代码化。
一个值得注意的实现细节:reward 和 Q 的输出都经过 two_hot_inv 解码——这是 §6.6 讲的离散回归,网络输出的是 bin 上的分布,two_hot_inv 把它解码回标量。读代码时看到 two_hot_inv 别困惑,它就是"把离散回归的输出转回标量"。
这也是读这类研究代码的一个通用经验:官方实现里总会夹杂一些"工程细节函数"(two_hot_inv、SimNorm、各种 normalization),它们不影响主干逻辑的理解。第一遍读时,把它们当成"黑箱工具"(知道它干什么即可,如"two_hot_inv = 离散回归解码"),先看懂主干(编码→rollout→终端价值→更新);需要时再单独研究某个细节函数的内部实现。这样你不会被细节淹没,能始终抓住"这段代码在做本章的哪件事"。把工程细节和核心逻辑分层阅读,是高效读懂任何研究代码的关键。
最小实现:把组件拼成一个能跑的 TD-MPC¶
光读官方代码还不够,自己拼一个最小版才能真懂。下面给出一个最小 TD-MPC 的完整骨架——它把 §6.2 的世界模型、§6.3 的规划、§6.5 的训练拼在一起,去掉了 §6.6 的规模化改进(SimNorm、离散回归、多任务),保留核心。这个骨架可以在简单环境(如 Pendulum、双积分器)上跑通:
import torch, torch.nn as nn, numpy as np
def mlp(i, h, o, act=None):
L = [nn.Linear(i,h), nn.LayerNorm(h), nn.Mish(), nn.Linear(h,h), nn.LayerNorm(h), nn.Mish(), nn.Linear(h,o)]
return nn.Sequential(*L, act) if act else nn.Sequential(*L)
class MiniTDMPC(nn.Module):
def __init__(self, obs_dim, act_dim, latent=32, hidden=128, num_q=2):
super().__init__()
self.act_dim = act_dim
self.encoder = mlp(obs_dim, hidden, latent)
self.dynamics = mlp(latent+act_dim, hidden, latent)
self.reward = mlp(latent+act_dim, hidden, 1)
self.pi = mlp(latent, hidden, 2*act_dim)
self.Qs = nn.ModuleList([mlp(latent+act_dim, hidden, 1) for _ in range(num_q)])
def encode(self, o): return self.encoder(o)
def next(self, z, a): return self.dynamics(torch.cat([z,a],-1))
def rew(self, z, a): return self.reward(torch.cat([z,a],-1)).squeeze(-1)
def act(self, z): # policy prior 取均值动作
mu = self.pi(z).chunk(2,-1)[0]; return torch.tanh(mu)
def Q(self, z, a): # 取两个 Q 的较小值
qs = [q(torch.cat([z,a],-1)).squeeze(-1) for q in self.Qs]
return torch.min(torch.stack(qs,0), 0).values
@torch.no_grad()
def plan(self, obs, H=5, K=256, iters=4, n_elite=32, gamma=0.99, temp=0.5):
z0 = self.encode(obs.unsqueeze(0)) # (1, latent)
mean = torch.zeros(H, self.act_dim); std = torch.ones(H, self.act_dim)*0.5
for _ in range(iters):
acts = (mean.unsqueeze(1) + std.unsqueeze(1)*torch.randn(H,K,self.act_dim)).clamp(-1,1)
z = z0.expand(K,-1); G = torch.zeros(K); disc = 1.0
for t in range(H): # latent rollout(批量)
G += disc * self.rew(z, acts[t]); z = self.next(z, acts[t]); disc *= gamma
G += disc * self.Q(z, self.act(z)) # 终端价值(§6.4 核心)
elite = G.topk(n_elite).indices
ea = acts[:, elite]; w = torch.softmax(temp*(G[elite]-G[elite].max()),0)
mean = (w.view(1,-1,1)*ea).sum(1); std = ((w.view(1,-1,1)*(ea-mean.unsqueeze(1))**2).sum(1)).sqrt().clamp(0.05,2)
return mean[0]
这个 MiniTDMPC 把本章的核心全装下了:encode/next/rew/Q 是 §6.2 的四组件,plan 是 §6.3 的采样规划 + §6.4 的终端价值。训练部分(§6.5 的 train_step)前面已给过,拼上它和一个 replay buffer + 环境交互循环,就是一个完整的、能在简单任务上学起来的 TD-MPC。
读这段最小实现,对照官方 plan,你会发现结构一模一样、只是官方多了 policy prior 混合采样、离散回归、多任务支持等。核心的 latent rollout + 终端价值 + 采样更新,最小版和官方版没有区别。 这就是本章想让你建立的信心:TD-MPC 的核心,你用几十行就能写出来;官方实现的复杂,全在 §6.6 那些"规模化、鲁棒化"的工程外壳上,而非核心逻辑。
为了让"核心 vs 工程外壳"的边界彻底清楚,把最小实现和官方实现的差异列成清单——左边是两者共有的核心(你的最小版已经有了),右边是官方为规模化/鲁棒化额外加的:
| 核心逻辑(最小版已有,不可省) | 官方额外的工程外壳(规模化/鲁棒化) |
|---|---|
| 编码器 + latent 动力学 + reward + 价值四组件 | SimNorm latent 归一化(§6.6) |
| latent 空间批量 rollout | 离散回归 two-hot(reward/价值,§6.6) |
| 终端价值 \(\gamma^H Q\) | Q 集成(更多 Q + dropout,§6.6) |
| 采样 + 加权/精英更新 | policy prior 混合采样(更完整的实现) |
| warm-start | 多任务:任务嵌入 + 动作 masking(§6.6) |
| latent 一致性 + reward + TD 三项损失训练 | 大规模训练的各种稳定化技巧 |
读这张清单,左列是"没有就不是 TD-MPC"的核心——任何 TD-MPC 实现都必须有这些;右列是"有了能规模化、更鲁棒,但去掉核心逻辑照样转"的外壳。你的最小版有了左列全部,所以它是一个**功能完整的 TD-MPC**——能在简单任务上学起来、规划。官方版多的是右列——它们让 TD-MPC 能从"简单任务的最小版"长成"通吃 100+ 任务的 TD-MPC2"。
这张清单也是本章一以贯之的主旨的最终印证:TD-MPC 的核心思想(左列)是地基、不复杂,你几十行就能写出;规模化(右列)是工程、是把地基上的房子盖大盖稳。 读官方代码时,用这张清单区分"哪些是核心、哪些是外壳",你就不会在工程细节里迷失,能始终抓住主线。
最快的入门:跑预训练 checkpoint 看规划行为¶
理解原理后,最快建立"TD-MPC 实际跑起来什么样"的直觉的方式,是跑官方提供的预训练 checkpoint——这对应大纲的 A 型练习(DMControl Walker-Walk 跑预训练模型、可视化规划)。这条路径不需要训练(省时省算力),直接看一个学好的 TD-MPC 怎么规划、怎么完成任务。
大致步骤(具体命令以官方 README 为准):
- 装环境:clone
nicklashansen/tdmpc2,按 README 装依赖(官方提供 Dockerfile,省去环境配置的麻烦)。评估比训练轻,CPU 也能跑小任务的评估(GPU 更快)。 - 下 checkpoint:官方开源了 324 个 checkpoint。选一个单任务的(如 Walker-Walk、单任务模型
model_size=5),下载下来。 - 跑评估:用官方的
evaluate.py,指定任务和 checkpoint 路径,加上save_video=true把规划过程录成视频。 - 看规划行为:观察录下的视频——机器人怎么走、怎么完成任务;如果官方支持,可视化 MPPI 采样的轨迹分布、看规划器在 latent 空间"想象"了哪些未来。
读到这里你可能会问:跑别人训好的模型,能学到什么? 能学到三件事,都很有价值:(a) 直觉——看一个学好的 TD-MPC 怎么流畅地完成任务,建立"它实际什么水平"的感性认识;(b) 验证理解——对照代码看 plan 怎么调用世界模型,把 §6.3–§6.4 的伪代码和真实运行对应起来;(c) 调试基线——有一个"已知好的"模型,你后续自己训练时可以对照(你的模型行为和官方 checkpoint 差多少)。先会"用",再会"训",是最稳的入门顺序。
这之后,再按 §6.7 前面的"从单任务、小模型、状态观测起步"自己训练,就有了参照和信心。
实战要点与建议¶
把 TD-MPC 用起来,几条实战经验:
从单任务、小模型、状态观测起步。 别一上来就上多任务、像素、大模型。先在一个简单的状态观测任务(如 DMControl 的 Walker-Walk)上,用默认的 5M 单任务模型跑通,理解训练曲线和规划行为,再逐步加难度。TD-MPC2 官方提供预训练 checkpoint,先跑通评估、可视化规划,是最快的入门路径(对应大纲 A 型练习)。
先验证规划、再验证训练。 一个好的调试策略:先用一个"已知好的"模型(如官方 checkpoint)验证你的 plan 实现对不对(规划出的动作合理、能完成任务),再单独验证 train_step(损失能下降、latent 不塌缩)。把规划和训练分开调,比一起调容易定位问题。
监控 latent 一致性损失和价值估计。 训练时盯两个量:latent 一致性损失(若它降不下来,说明动力学没学好、或 latent 塌缩了)、价值估计的量级(若它持续升高、远超实际回报,说明价值过估计了,§6.8 会讲)。这两个量是 TD-MPC 健康与否的体温计。
把"该监控哪些指标"整理成一张清单,调试时对照着看,能帮你快速定位问题出在哪个环节:
| 监控指标 | 健康的样子 | 异常说明什么 |
|---|---|---|
| latent 一致性损失 | 稳步下降到较低 | 降不下去 → 动力学没学好或 latent 塌缩(查 stop-gradient) |
| reward 预测损失 | 稳步下降 | 降不下去 → 编码器没编码好 reward 相关信息 |
| 价值估计量级 vs 实际回报 | 大致相当 | 价值持续远超实际 → 过估计(查双 Q / policy mismatch) |
| latent 范数(rollout 中) | 稳定有界 | 越 rollout 越大 → 尺度发散(查 SimNorm) |
| 任务回报(训练曲线) | 随训练上升 | 长期不升 → 预热期过长或 pipeline 有 bug |
| 规划耗时 | 满足实时频率 | 太慢 → rollout 没向量化或采样数过大 |
读这张清单,它把前面 §6.8 故障排查的各个症状对应到了"训练时该盯的指标"——与其等问题严重了再排查,不如训练时就盯着这几个指标,一旦某个异常就知道大概是哪个环节出了问题。其中最该优先盯的是前三个:latent 一致性损失(模型学得好不好的地基)、价值量级(过估计的早期信号)、任务回报(最终性能)。这三个是 TD-MPC 健康的核心体温计,养成训练时盯着它们的习惯,能让你在问题萌芽时就发现,而非等到性能崩了才回头排查。
horizon 保持短(3~5),别试图调大。 回忆 §6.4——长期靠价值补,不靠加 horizon。若性能不好,先查价值学得准不准、latent 一致性好不好,而非加 horizon(加了既慢又因累积误差更差,§6.8)。
读到这里你可能会问:我没有 GPU,能玩 TD-MPC 吗? 能,但要降低期望。TD-MPC2 官方训练需要 GPU(单任务至少 12GB RAM、8GB 显存)。但你可以:(a) 在 CPU 上跑本节的最小实现 + 简单环境(如 Pendulum),理解机制;(b) 用官方提供的预训练 checkpoint 在 CPU 上做评估和可视化(推理比训练轻);(c) 跑本章 §6.4 的 NumPy demo 理解核心洞察。理解原理不需要 GPU,只有"训练大规模 TD-MPC2"才需要——而理解原理才是本章的目标。
这一点值得稍微强调,因为它关系到你该把精力放在哪。本章反复用 NumPy demo(§6.4 的短 horizon + 价值、§6.5 的 TD bootstrap、§6.8 的 compounding error)演示核心机制——这些 demo 都能在普通笔记本的 CPU 上几秒跑完,却把 TD-MPC 最核心的几个论点演示得清清楚楚。理解"为什么短 horizon + 价值有远见""为什么 TD 能 bootstrap 学长期""为什么学习模型有 compounding error",这些本质的东西,一台普通电脑足矣。 真正需要 GPU 和大算力的,是"把 TD-MPC2 训到论文那样的 SOTA、复现 317M 大模型"——那是工程和算力的事,不是理解本质的前提。所以别因为没有强算力就觉得学不了 TD-MPC:把本章的 demo 跑一遍、把原理想透,你对 TD-MPC 的理解就已经扎实了。算力决定你能复现到什么规模,但理解深度由你对原理的把握决定,二者无关。
⚠️ 常见陷阱¶
编程陷阱:读官方代码时,被 two_hot/two_hot_inv、SimNorm 等细节绊住,丢了主线。
错误做法:逐行啃官方代码,在 two_hot_inv、SimNorm、任务嵌入等工程细节上反复纠结,看不清整体结构。
现象/后果:陷在细节里,看不出 plan 就是 §6.3–§6.4 的采样规划 + 终端价值,误以为官方代码很复杂、和本章原理不是一回事。
根本原因:没有"先框架、再细节"地读。这些细节(two_hot 是离散回归的编解码、SimNorm 是 latent 归一化)是 §6.6 的规模化外壳,不影响核心逻辑的理解。
正确做法:先用本章的概念框架定位代码结构(这是编码、这是 latent rollout、这是终端价值、这是更新),把握主线;遇到 two_hot_inv 就理解成"离散回归解码回标量"、SimNorm 理解成"latent 归一化",不深究实现细节也能看懂主线。需要时再单独研究这些细节。
思维陷阱:以为不跑通大规模 TD-MPC2 就等于没学会。 错误认识:觉得只有在 GPU 上训出一个 SOTA 的 TD-MPC2 才算掌握本章。 现象/后果:因为没有 GPU/算力而气馁,或把大量精力花在复现 SOTA 上,反而忽略了对核心机制的理解。 根本原因:混淆了"理解原理"和"复现 SOTA"。本章的目标是理解"学习世界模型 + 采样规划 + 终端价值"的机制,这用 CPU 上的最小实现和 NumPy demo 就能达成;复现大规模 SOTA 是另一回事(需要算力和大量工程)。 正确做法:用最小实现和 demo 吃透核心机制(CPU 即可),这才是本章的目标。大规模复现是可选的进阶,不是理解的前提。能讲清"为什么短 horizon + 价值有远见、为什么 latent 一致性防塌缩",就算掌握了本章,无论你有没有 GPU。
练习¶
-
(代码地图,⭐⭐) 不看官方代码,根据本节的"代码地图",写出读 tdmpc2 仓库的顺序和每个文件/函数的职责。然后对照本章:
world_model.py对应哪节?plan对应哪节?update对应哪节?_estimate_value实现的是哪个公式? -
(最小实现跑通,⭐⭐⭐) 把本节的
MiniTDMPC加上 §6.5 的train_step和一个简单环境(Pendulum 或双积分器)+ replay buffer,拼成完整的训练循环,跑通。观察:(a) 训练初期规划行为是否随机、随训练逐渐变好?(b) latent 一致性损失是否下降?(c) 把 horizon 从 5 改成 1、10,闭环性能如何变化——和 §6.4 的核心洞察对照。 -
(精读 _estimate_value,⭐⭐⭐,思考题) 本节的
_estimate_value是 §6.4 核心公式的实现。请:(a) 逐行对应它和公式 \(G=\sum_{t=0}^{H-1}\gamma^t r_t + \gamma^H Q(z_H, a_H)\)——哪行是 rollout 累积、哪行是终端价值、discount变量如何对应 \(\gamma^t\) 和 \(\gamma^H\)?(b) 为什么终端动作 \(a_H\) 用pi(z)(policy prior)而非采样的动作?(c) 如果把终端价值那行删掉(只返回G),规划会退化成什么?在 §6.4 的小峰大峰任务上会发生什么?
§6.8 局限与前沿:学习世界模型不是免费午餐 ⭐⭐⭐¶
动机:诚实地划出能力边界¶
前七节讲了 TD-MPC 的全部威力——学习的 latent 模型让规划快、能吃像素,终端价值让短 horizon 有远见,TD-MPC2 让一套方法通吃。但一份诚实的教学,必须同样讲清它**不保证什么、什么时候会失灵**。这一节集中讲学习世界模型的局限和当前的开放问题,它和本课程一贯的诚实态度一致,也是你真正掌握一个方法(而非迷信它)的标志。更重要的是,这些局限直接指向当前最活跃的研究方向——它们是你将来做研究的题目来源。
局限一:compounding error——学习模型的原罪¶
学习世界模型最根本的局限,是 §6.2、§6.3 反复埋下伏笔的那个——compounding error(误差累积)。学习的动力学 \(d_\theta\) 每步预测都有小误差,rollout 越长,误差累积越大,最终 rollout 出的轨迹会严重偏离真实轨迹,让规划失真。
这不是危言耸听,用一个亲手验证的 demo 把它量化。我们让一个学习的动力学(带一点系统偏差和噪声,模拟学习不完美)和真实动力学从同一起点、用同一动作序列 rollout,看两者的偏离如何随步数累积:
import numpy as np
rng = np.random.default_rng(0)
def real_dyn(x, a): return 0.9*x + a # 真实动力学
def learned_dyn(x, a): return 0.92*x + a + 0.03 + 0.02*rng.standard_normal(np.shape(x))
# ↑系数偏差 ↑常数偏差 ↑随机误差(模拟学习不完美)
def compare(H, n_trials=200):
errs = np.zeros(H)
for _ in range(n_trials):
xr = xl = 0.0; a_seq = rng.standard_normal(H)*0.5
for t in range(H):
xr = real_dyn(xr, a_seq[t]); xl = learned_dyn(xl, a_seq[t])
errs[t] += abs(xl - xr) # 累积每步的预测偏离
return errs / n_trials
errs = compare(30)
跑出来的误差随步数变化:
=== 学习动力学 rollout 的 compounding error(每步小误差如何累积) ===
步数 t 平均预测误差 |x_learn - x_real|
1 0.0314 ███
3 0.0883 █████████
5 0.1323 ██████████████
10 0.2166 ████████████████████████
15 0.2769 ███████████████████████████████
20 0.3149 ███████████████████████████████████
30 0.3548 ████████████████████████████████████████
误差从第1步的 0.0314 累积放大到第30步的 0.3548 (放大 11.3×)
读这条曲线:每步只有 0.03 的小误差,但 rollout 到 30 步,误差累积放大到 0.35——放大了 11.3 倍。这就是 compounding error:单步看微不足道的误差,多步 rollout 后滚成大偏差,足以让规划基于一条"想象出来的、严重失真的"轨迹做决策。
这条曲线一举解释了本章好几个设计:
为什么 TD-MPC 必须用短 horizon(H=3~5)。 看曲线——前 3~5 步误差还小(0.03~0.13),可以信任;到 10 步以后误差累积到 0.2+,rollout 就不可靠了。所以 TD-MPC 把 rollout 限制在误差还小的前几步,把"误差会失控的长期"交给价值函数(§6.4)。短 horizon 不是任意选的,而是被 compounding error 逼出来的。
为什么终端价值是必需的(而非可选)。 既然 rollout 不能长(否则误差累积),那 horizon 之外的长期信息只能靠价值补——这就是 §6.4 终端价值不可或缺的根本原因。compounding error 和终端价值是一枚硬币的两面:因为有 compounding error 所以 rollout 要短,因为 rollout 短所以要终端价值补长期。
看到这里,本章前面那个"三设计协同"(§6.4 的洞察:latent 模型 + 短 horizon + 终端价值缺一不可)的根子就彻底清楚了——它们仨其实都是被 compounding error 这一个约束串起来的。学习模型必然有 compounding error → 所以 rollout 必须短(短 horizon)→ 所以长期必须靠价值补(终端价值)→ 而短 rollout 又恰好让快的 latent 模型够用(不必精确到能长 rollout)。一环扣一环,全是为了"与 compounding error 共处"。所以你回头看 §6.4 说的"三根柱子互相支撑",现在能看得更透:撑着它们的地基,正是"如何与学习模型的误差累积共处"这个根本约束。这也是为什么本章把 compounding error 放在最后讲——它是回过头来解释前面所有设计"为什么必须这样"的那把钥匙。
本质洞察:compounding error 是一切学习世界模型的"原罪"——只要模型是学出来的、有误差,多步 rollout 就必然累积误差,这是无法根除的。理解这一点,你就理解了为什么"学个完美模型再随便规划"是个幻想:模型永远不完美,rollout 永远会累积误差。TD-MPC 的高明之处,不在于消除 compounding error(做不到),而在于**绕开它**——用短 horizon 把 rollout 限制在误差还小的范围,再用学习的价值补足长期。这是一种"承认局限、设计绕过"的工程智慧:与其追求一个不可能的完美模型,不如设计一个"对模型误差鲁棒"的使用方式。这个思想远不止用于世界模型——任何用"不完美的预测"做"多步决策"的系统(金融预测、天气预报、供应链规划),都面临 compounding error,也都需要类似的"短期信任预测、长期用其他手段"的鲁棒设计。看清 compounding error 是学习模型的根本约束,你才不会对"学个模型规划"抱有不切实际的幻想,也才能欣赏 TD-MPC 设计的精妙。
读到这里你可能会问:第 5 章的免训练扩散 MPC 也做多步 rollout,它有 compounding error 吗? 这个跨章对比很能帮你看清 compounding error 的根源。答案是:第 5 章基本没有这个问题,因为它用的是精确(真实)动力学。 真实动力学每步预测没有"学习误差"(它就是真实的物理演化),所以多步 rollout 不会累积"模型误差"——它的 rollout 长度主要受计算成本限制,而非误差累积限制。这正是为什么第 5 章可以用较长的 horizon、用退火多级搜索,而不必像 TD-MPC 那样把 horizon 压到 3~5。
对比之下,本章的 TD-MPC 用**学习的** latent 动力学,每步都有学习误差,多步必累积——这是它和第 5 章最根本的区别之一,也直接导致了两者 horizon 选择的不同(第 5 章可长、本章必短)。这个对比印证了一个一般规律:compounding error 是"学习模型"特有的原罪,"精确模型"没有这个负担。 所以"用什么模型"(学习的还是精确的)直接决定了"能 rollout 多长"——这又回到了贯穿本章的"模型保真度 vs 速度/可学习性"权衡(§6.8 局限四):精确模型保真度高、可长 rollout,但要方程、可能慢;学习模型快、能吃像素,但有 compounding error、必须短 rollout + 价值补长期。两章的设计差异,根子上都源于这个权衡里"模型从哪来"的不同选择。
局限二:OOD(分布外)状态下,误差更失控¶
compounding error 还有一个更隐蔽的恶化因素:OOD(out-of-distribution,分布外)状态。学习的模型只在"训练数据覆盖到的状态"上准;一旦 rollout 把状态带到训练数据没覆盖的区域(OOD),模型的预测误差会急剧增大,compounding error 雪上加霜。
这在规划里是个真实的陷阱:采样规划会探索各种动作序列,其中一些会把 latent 带到 OOD 区域。在 OOD 区域,模型可能"自信地预测出一个错误的、甚至虚高回报的未来"——规划器被这个虚假的好回报吸引,选了一个实际上很糟的动作。这就是大纲点名的开放问题"world model 在 OOD 状态的 compounding error——robust planning under model uncertainty"。
为什么 OOD 难处理?因为模型不知道自己"不知道"——在 OOD 区域,它照样输出一个看似合理的预测,但这个预测可能完全错误,且模型不会主动告诉你"这里我没把握"。让模型"知道自己的不确定性"(uncertainty quantification)、并在规划时避开高不确定的区域,是当前活跃的研究方向(如用模型集成的方差估计不确定性、惩罚高不确定区域的回报)。
读到这里你可能会问:§6.5 的 Q 集成不是能估不确定性吗?为什么 OOD 还是开放问题? Q 集成(多个 Q 取较小值)缓解了"价值过估计",也能粗略反映价值的不确定性,但它不直接解决"动力学模型在 OOD 的预测失真"。动力学的 OOD 误差和价值的过估计是两个不同的问题。而且"准确地量化模型不确定性、并在规划时恰当地利用它"本身很难——估计得太保守会让规划畏手畏脚,太乐观又防不住 OOD。所以 OOD 下的鲁棒规划至今没有干净的解,是开放问题。
举一个具体的画面,让"模型在 OOD 自信地犯错"不再抽象。设想你训练了一个抓取的世界模型,训练数据里夹爪总是从桌面上方接近物体。现在规划时,采样探索到一条"让夹爪钻到桌面以下"的动作序列——这是训练数据从未覆盖的 OOD 状态。模型在这个 OOD 状态会怎样?它不会说"我没见过、不知道",而会**照常输出一个预测**:可能预测出"夹爪在桌面下方也能顺利抓到物体、reward 很高"——一个物理上荒谬、但模型"自信"给出的预测。规划器看到这条 OOD 轨迹的虚高 reward,可能就选了它,让夹爪去钻桌面。
这就是 OOD 的危险:模型的预测在训练分布内可信,在分布外可能完全错误,但模型不会主动标注"这里我没把握"。 规划器若无条件信任模型的所有预测(包括 OOD 区域),就会被这些虚假的高回报误导。而采样规划偏偏会主动探索各种动作序列,其中难免有把状态带到 OOD 的——所以采样规划和 OOD 风险天生相伴。这也是为什么"防 OOD"对 TD-MPC 的实际部署如此重要。
局限三:价值过估计与 policy mismatch¶
§6.5 讲过用双 Q/集成抑制价值过估计。但 TD-MPC 有一个更微妙、双 Q 解决不了的过估计来源——policy mismatch(策略不匹配)。
回忆 §6.5:"规划器既是决策者又是数据采集者"。问题就出在这里:规划器(MPC planner)采集数据用的"行为策略",和价值函数学习时假设的"策略",并不完全一致。 规划器通过在线采样优化产生动作(一个复杂的、隐式的行为策略),而价值是用 TD 目标学的(假设按 policy prior \(\pi\) 走)。两者的不匹配导致:价值函数学习时"看到"的数据分布,和它实际被查询(规划时)的分布不一致,于是价值函数在某些区域的误差得不到数据纠正、悄悄累积成过估计。
读到这里你可能会问:§6.5 的双 Q 不是治过估计吗,为什么治不了这个? 因为双 Q 和 policy mismatch 治的是**两种不同病因的过估计**。双 Q 针对的是"函数近似误差被 max 操作放大"——通过取两个 Q 的较小值,把"对乐观的偏好"往回压;它假设"只要数据覆盖到了,误差就能被纠正"。但 policy mismatch 的问题恰恰是**数据没覆盖到**:规划器实际会查询的某些状态-动作区域,行为策略采集的数据压根没怎么去过,于是价值在那里的误差既不会被双 Q 发现(双 Q 只在有数据的地方比较两个估计),也不会被 TD 更新纠正(没数据就没有更新信号)。打个比方,双 Q 像"对同一道题让两个学生作答、取较保守的答案"——能纠正会做但容易乐观的题;而 policy mismatch 是"考的题学生根本没复习过"——两个学生都不会,取较小值也没用。所以治 policy mismatch 不能靠双 Q,得让"行为策略采的数据"和"价值要查询的分布"对齐(比如约束 policy、或让规划别偏离数据太远),从源头补上数据覆盖。这正是下面 TD-M(PC)² 的思路。
这是 TD-MPC 后续工作 TD-M(PC)²(arXiv:2502.03550,ICLR 2025)专门诊断和处理的问题。该工作指出:TD-MPC 标准的 policy iteration 会导致**持续的价值过估计**,根因正是 policy mismatch——MPC planner 生成的行为策略采集的数据分布,与学习的价值/policy prior 不对齐,使价值函数的误差未被充分纠正。它还观察到 TD-MPC2 在某些**高维 locomotion(如 61 自由度人形)**任务上表现不尽如人意,正与此相关。TD-M(PC)² 用一个对 policy 的约束(不到十行代码的改动)缓解了这个问题,在高维任务上显著提升。
这个局限的启示:TD-MPC 把"规划"和"价值学习"耦合在一起(规划采数据、数据训价值、价值又用于规划),这个耦合既是它的力量来源,也是微妙问题的温床。 规划器采的数据分布和价值学习的假设不一致,是这类耦合系统的通病,也是当前的活跃课题。
局限四:贯穿始终的根本权衡——模型保真度 vs 速度/可学习性¶
把前面的局限拉高一层,会看到一个贯穿本章始终的根本权衡,它也是大纲思考题的核心:模型保真度(fidelity)vs 速度/可学习性。 这个权衡最好通过和你前置课程学过的梯度式 MPC 对比来理解。
你在前置课程里用过 OCS2 这类梯度式 MPC,它用 Pinocchio 的精确刚体动力学——基于物理方程,保真度极高、可解释、不用训练。而 TD-MPC 用**学习的 latent 动力学**——快、能吃像素、任务导向,但有误差、要数据、是黑箱。把两者并排,这个权衡就清晰了:
| 维度 | OCS2 + Pinocchio(精确动力学) | TD-MPC(学习的 latent 动力学) |
|---|---|---|
| 保真度 | 高(物理方程,精确) | 有误差(学出来的,compounding error) |
| 速度 | 取决于模型复杂度,全阶可能慢 | 快(小 MLP,可大批量) |
| 可解释性 | 高(物理量有明确含义) | 低(latent 是黑箱) |
| 需要什么 | 精确的动力学方程/参数 | 数据、训练 |
| 能吃像素吗 | 不能(要状态) | 能(编码器吃任意观测) |
| 换任务 | 改方程/代价 | 重新训练(或多任务模型) |
| OOD 行为 | 物理方程外推相对可靠 | OOD 预测可能严重失真 |
这张表没有"赢家"——它是一个**权衡谱**。保真度高的(Pinocchio)精确可靠但要方程、可能慢、不能吃像素;速度快、可学习的(latent)快且通用但有误差、是黑箱、OOD 不可靠。选哪个,取决于你的任务:
- 有精确动力学方程、状态可观测、要可靠精确(如工业机械臂精确轨迹跟踪)→ 倾向精确动力学(OCS2/Pinocchio,前置课程那条线)。
- 没有方程、观测是像素、要快要通用、能容忍误差(如从摄像头学操作的通用机器人)→ 倾向学习的 latent 模型(TD-MPC,本章)。
而很多真实任务落在两端之间——比如有近似的动力学方程但不够精确、或部分可观测。这时也不必非此即彼:可以用近似模型做主、学习模型补差(混合建模),或在不同阶段用不同模型(如自由空间用精确模型、接触阶段用学习模型)。权衡谱是连续的,你的任务在谱上的位置决定了你该偏向哪端、或如何混合——这正是"按任务定位"的实践含义,而非在两个极端里硬选一个。
本质洞察:模型保真度 vs 速度/可学习性,是模型驱动决策里一个无法回避的根本权衡,它贯穿本课程始终。第 5 章的免训练扩散 MPC 站在"高保真(用真实模型)"一端,本章的 TD-MPC 站在"可学习(学一个快但有误差的模型)"一端,而它们共享同一个采样规划内核。这个权衡的深刻之处在于:保真度和可学习性/速度,在根本上是冲突的——越精确的模型(物理方程)越难学、越可能慢、越需要领域知识;越快越通用的模型(神经网络)越有误差、越是黑箱。 你不可能同时要"物理方程的精确"和"神经网络的速度与通用"——这是个真实的 trade-off,不是工程不够努力。理解了这一点,你面对任何"用什么模型做决策"的选择,都不会去找一个不存在的"既精确又快又通用"的银弹,而是问"我的任务在这个权衡谱上该站哪里"——要精确可靠就接受慢和领域知识,要快和通用就接受误差和黑箱。这种"认清根本权衡、按任务定位"的思维,比掌握任何单个方法都更接近工程的本质。它也是整个采样式 MPC 部分(从精确模型到学习模型)想留给你的核心判断力。
把整个课程的"模型选择"脉络收束一下¶
学到这里,你已经见过控制里"用什么模型"的三种代表性答案,正好覆盖了"模型保真度 vs 速度/可学习性"权衡谱的不同位置。把它们收束成一张全局视图,作为你将来选型的指南针:
| 方法 | 模型从哪来 | 在权衡谱的位置 | 适合的任务 |
|---|---|---|---|
| 梯度式 MPC(OCS2/Pinocchio,前置课程) | 精确物理方程 | 最高保真、需领域知识 | 有方程、状态可观测、要高精度可靠 |
| 免训练扩散 MPC(第 5 章) | 已知动力学(免训练用) | 高保真、用采样优化 | 有模型、问题非凸/高维、不想训练 |
| 学习世界模型(本章 TD-MPC) | 从数据学的 latent 模型 | 高速/可学习、有误差 | 无方程、观测是像素、要通用 |
读这张表,看清一条主线:从左到右,模型的保真度递减、可学习性/通用性递增。 梯度式 MPC 用最精确的物理方程(保真度顶格),但要领域知识、状态可观测;免训练扩散 MPC 也用精确模型,但用采样优化处理非凸/高维;学习世界模型放弃了保真度(学一个有误差的模型),换来了能吃像素、能通用、不需要方程。
这条主线给你的选型指南针是:先问"我有没有精确模型、观测是什么、要不要通用",再在谱上定位。 有精确方程、要高精度 → 往左(梯度式/免训练精确模型);只有像素、要通用、容忍误差 → 往右(学习模型)。这三者不是谁取代谁,而是覆盖了不同任务的互补工具——这也正是整个采样式 MPC 课程(乃至它与梯度式 MPC、与 RL 的关系)想留给你的核心判断力:没有万能的模型,只有最匹配任务的模型,而"匹配"由这个根本权衡决定。
前沿方向¶
这个方向当前很活跃,几个值得关注的前沿(也是你能切入的题目):
鲁棒规划与不确定性量化。 针对局限一、二——让模型"知道自己的不确定性",在规划时避开高不确定的 OOD 区域。方法包括模型集成估计方差、惩罚高不确定区域的回报、保守的价值估计等。这是把 TD-MPC 推向真实、安全部署的关键。
缓解 policy mismatch。 针对局限三——如 TD-M(PC)² 用 policy 约束缓解价值过估计,让规划采的数据分布和价值学习更一致。如何在"规划-价值"耦合系统里保证价值学习的健康,是个有理论深度的课题。
世界模型的规模化与通用化。 沿 TD-MPC2 的方向继续——更大的模型、更多的任务、跨实体/跨形态的通用世界模型。这和当前"具身大模型/世界模型"的浪潮汇合,是最受关注的方向之一。
与其他范式的融合。 TD-MPC 的"学习模型 + 规划"可以和扩散(学一个扩散式的世界模型/策略先验)、Transformer(序列化的世界模型)、甚至大语言模型(高层规划 + TD-MPC 底层控制)融合。这些交叉是层出不穷的新工作的来源。
读到这里你可能会问:这么多局限,TD-MPC 到底还值不值得用? 非常值得——但要清醒地用。这些局限不否定 TD-MPC 的价值(它确实让采样式 MPC 上了像素、上了通用任务、用短 horizon 做出了远见决策),只是划清了它的适用边界:它擅长"没有精确模型、观测复杂、要通用、能容忍一定误差"的任务,不擅长"要绝对精确可靠、OOD 安全攸关"的任务。带着这份清醒,你既能用好它的强大,又不会在它失灵(OOD、高维过估计)时手足无措。这正是本节的目的——不是泼冷水,而是给你一张准确的能力边界地图。
⚠️ 常见陷阱¶
概念误区:以为只要把世界模型学得足够准,就能消除 compounding error、随便用长 horizon。 错误认识:compounding error 是因为模型不够准,只要数据更多、模型更大、训练更久,就能学出一个准到可以长 rollout 的模型。 现象/后果:在追求"完美模型"上投入过多,或盲目加长 horizon(以为模型够准了),结果 rollout 仍因累积误差失真,规划质量下降。 根本原因:compounding error 是学习模型的"原罪"——只要模型有任何非零误差(永远会有),多步 rollout 就必然累积,且累积速度随步数增长。再准的模型也只是让单步误差更小、累积更慢,无法根除累积本身。 正确做法:接受 compounding error 不可根除,用 TD-MPC 的方式绕开它——短 horizon(rollout 限制在误差还小的范围)+ 终端价值(补长期)。别试图靠"学个完美模型"来允许长 horizon,那是幻想。
思维陷阱:以为学习世界模型(TD-MPC)总比精确模型(OCS2/Pinocchio)先进、应该取代它。 错误认识:TD-MPC 是更新、更"AI"的方法,能吃像素、能通用,所以比传统的精确动力学 MPC 先进,应该用它取代 OCS2。 现象/后果:在有精确动力学方程、要求高精度可靠的任务上(如工业精密操作)硬上学习的 latent 模型,结果精度和可靠性反而不如成熟的精确动力学 MPC,还引入了训练成本、OOD 风险。 根本原因:脱离"模型保真度 vs 速度/可学习性"的根本权衡看问题。学习模型快、通用、能吃像素,但有误差、是黑箱、OOD 不可靠;精确模型精确、可靠、可解释,但要方程、可能慢、不能吃像素。没有谁先进谁落后,只有谁更匹配任务。 正确做法:按任务在权衡谱上定位——要精确可靠、有方程、状态可观测 → 精确动力学 MPC(前置课程那条线);要通用、吃像素、容忍误差 → 学习的 latent 世界模型(本章)。两者是互补的工具,不是替代关系(呼应 §6.1 的同款提醒和总论"采样式与梯度式互补"的基调)。
编程陷阱:规划时不防范 OOD,被模型在 OOD 区域的虚高回报误导。 错误做法:直接用学习模型的 rollout 回报做规划,不考虑"采样可能把状态带到 OOD 区域、那里模型预测不可靠"。 现象/后果:规划器被 OOD 区域的虚假高回报吸引,选出一个"模型觉得很好、实际很糟"的动作——尤其在训练数据覆盖不足的任务上,规划行为诡异、不稳定。 根本原因:学习模型在 OOD 区域"自信地犯错"——它照样输出预测,但预测可能完全错误,且不会标注自己的不确定。纯用 rollout 回报,等于无条件信任模型在所有区域的预测,包括它没把握的 OOD 区域。 正确做法:在能力范围内防范 OOD——用模型集成估计预测不确定性、对高不确定区域的回报打折/惩罚、或限制规划探索的范围(如约束动作不要偏离 policy prior 太远)。这正是"鲁棒规划"前沿在做的事。至少要意识到 OOD 风险的存在,监控规划是否被异常高的预测回报带偏。
练习¶
-
(复现 compounding error,⭐⭐) 把本节的 compounding error demo 敲一遍跑通,复现"误差从第 1 步累积放大到第 30 步约 11 倍"的结果。然后实验:(a) 减小学习模型的单步误差(把 0.03 偏差、0.02 噪声调小),累积误差曲线如何变化——能根除累积吗?(b) 把单步误差调大,累积有多快?(c) 据此论证:为什么 TD-MPC 用 H=3~5 而非 H=30?画出"误差 vs 步数"曲线,标出"误差还可信"的步数范围。
-
(权衡谱定位,⭐⭐⭐,思考题) 用本节"模型保真度 vs 速度/可学习性"的权衡,为下列任务各选"精确动力学 MPC(OCS2/Pinocchio)"还是"学习的 latent 世界模型(TD-MPC)",并说清理由:(a) 一台动力学方程已知、要做亚毫米级精密装配的工业机械臂;(b) 一个只有 RGB 摄像头、要学会各种家务的服务机器人;(c) 一个有精确仿真器、但要在上面快速试很多不同 reward 的研究平台;(d) 一个安全攸关、绝不能在分布外失控的医疗机器人。把你的选择和"模型保真度 vs 速度/可学习性"以及 OOD 风险对照。
-
(OOD 与鲁棒规划,⭐⭐⭐⭐,开放题) 学习模型在 OOD 区域"自信地犯错"。请论证:(a) 为什么采样规划特别容易触发 OOD(提示:它主动探索各种动作序列)?(b) 设计一个"防 OOD"的规划改进——如何用模型集成估计不确定性、并在规划时利用它(惩罚高不确定回报)?写出修改后的回报公式。(c) 这个改进的代价是什么(提示:太保守会怎样)?(d) 把这个问题和 §6.5 的价值过估计、本节的 policy mismatch 联系起来——它们都是"模型/价值在某些区域不可靠、却被规划信任"的不同表现,能否用一个统一的视角看待"规划时如何对待模型的不可靠"?
常见误解汇总¶
把本章各节的概念误区集中起来,方便你回头自查。每条都是初学者真实会踩的坑:
误解一:"TD-MPC 是一种全新的、和 MPPI/CEM 无关的强化学习算法。" 不是。TD-MPC 的规划内核就是你已经会的 MPPI/CEM——采样动作序列、rollout、加权/精英更新、执行第一个、滚动时域。它的"新"只在于换了两个零件:用**学习的 latent 动力学**替换真实动力学、在 horizon 末端加**学习的终端价值**。看穿这一点,学习成本骤降。
误解二:"TD-MPC 的世界模型要能重建观测。" 不要。TD-MPC 是**任务导向**的——latent 只为预测 reward/价值服务,不重建观测;TD-MPC2 更是 implicit/decoder-free,连解码器都没有。它用 latent 一致性损失(在 latent 空间比较递推 latent 和编码 latent)训练,全程不碰原始观测的重建。这是它比重建式模型(Dreamer/PlaNet)更高效的根源。
误解三:"要补足长期信息,就该加长规划 horizon。" 不该。加长 horizon 既慢(计算线性增长)、又因学习模型的 compounding error 而 rollout 失真、还因采样难度和折扣而未必抠得出长期信息(§6.4 demo 里 H=30 无价值仍困在小峰)。正确做法是**用学习的价值作终端代价**,在短 horizon 末端一次性补足长期——这是本章的核心洞察。
误解四:"既然价值能估长期,就该纯靠价值(model-free),不必 rollout。" 不该。价值是学出来的、有近似误差;短 rollout 是用模型实打实推演的、相对可靠。TD-MPC 用短 rollout 推演相对可靠的眼前、只把难推演的长期交给价值,比"纯靠价值"鲁棒。rollout 步数 \(H\) 是"信任模型 vs 信任价值"的平衡旋钮,TD-MPC 选小 \(H\) 取甜点。
误解五:"只要把世界模型学得足够准,就能消除 compounding error、随便用长 horizon。" 不能。compounding error 是学习模型的"原罪"——只要模型有任何非零误差(永远会有),多步 rollout 就必然累积。再准的模型也只是让累积更慢,无法根除。所以 TD-MPC 用短 horizon 绕开它,而非靠"完美模型"允许长 horizon。
误解六:"TD-MPC2 是和 TD-MPC 完全不同的新算法。" 不是。TD-MPC2 完全继承 TD-MPC 的核心思想(latent 模型 + 终端价值 + TD),改的全是"让核心思想能规模化、鲁棒化"的工程(SimNorm、离散回归、Q 集成、任务嵌入、单一超参)。学懂 TD-MPC,TD-MPC2 只是其上的工程外壳。
误解七:"学习世界模型(TD-MPC)总比精确模型(OCS2/Pinocchio)先进、该取代它。" 不是。这是"模型保真度 vs 速度/可学习性"的根本权衡——学习模型快、通用、能吃像素,但有误差、是黑箱、OOD 不可靠;精确模型精确、可靠、可解释,但要方程、可能慢、不能吃像素。没有谁先进,只有谁更匹配任务。两者互补,不替代。
误解八:"TD-MPC2 单一超参覆盖所有任务,意味着这套超参对每个任务都最优。" 不是。"单一超参鲁棒"指"一套超参在所有任务上都能达到强性能(不崩、够好)",而非"对每个任务都是全局最优"。它的价值是"无需逐任务精调就好用",但若为特定任务精调仍可能进一步提升。鲁棒默认 ≠ 每任务最优。
本章小结¶
术语速查表¶
| 术语 | 含义 | 首次出现 |
|---|---|---|
| 世界模型(world model) | 学习的环境模型,给定状态和动作预测未来;TD-MPC 的世界模型含编码/动力学/reward/价值 | §6.1 |
| TOLD | Task-Oriented Latent Dynamics,任务导向的 latent 动力学(编码 + 动力学 + reward) | §6.2 |
| 编码器 \(h_\theta\) | 把观测压成 latent 的网络;任务导向,不为重建服务 | §6.2 |
| latent 动力学 \(d_\theta\) | 在 latent 空间预测下一 latent 的小 MLP;快、可批量 | §6.2 |
| reward 预测 \(r_\theta\) | 在 latent 上预测每步 reward;让 rollout 全程在 latent 自洽 | §6.2 |
| 价值 \(Q_\theta\) | 估计从某 latent 出发的长期折扣回报;规划时作终端价值 | §6.2 |
| implicit/decoder-free | 无解码器的世界模型(TD-MPC2),不重建任何东西,任务导向的极致 | §6.2/§6.6 |
| latent 规划 | 把 MPPI/CEM 搬进 latent 空间——编码、latent rollout、终端价值、采样更新 | §6.3 |
| policy prior \(\pi\) | 学习的策略,规划时采一部分轨迹提供"好动作大概在哪"的引导 | §6.3 |
| 终端价值(terminal value) | 在短 horizon 末端加 \(\gamma^H Q\),补足 horizon 之外的长期回报 | §6.4 |
| 短 horizon + 价值 | 本章核心洞察:短 rollout(避累积误差)+ 学习价值(补长期)= 有远见 | §6.4 |
| latent 一致性损失 | 逼"递推 latent"接近"编码 latent",在 latent 空间训练动力学,不重建观测 | §6.5 |
| TD 目标 | \(r+\gamma Q_{\bar\theta}(z',a')\),bootstrap 地把长期价值学进 \(Q\) | §6.5 |
| 双 Q / Q 集成 | 多个 Q 取较小值,抑制价值过估计(从 SAC 迁移) | §6.5 |
| SimNorm | 单纯形归一化,约束 latent 尺度、防 rollout 发散(TD-MPC2) | §6.6 |
| 离散回归 | reward/价值用对数空间 two-hot 分类式预测,对 reward 量级鲁棒(TD-MPC2) | §6.6 |
| compounding error | 学习模型每步小误差,多步 rollout 累积放大;学习模型的"原罪" | §6.8 |
| policy mismatch | 规划器采数据的行为策略与价值学习假设的策略不一致,致价值过估计 | §6.8 |
| 模型保真度 vs 速度/可学习性 | 贯穿全章的根本权衡:精确模型 vs 学习模型各有得失 | §6.8 |
知识点总表¶
| 知识点 | 核心结论 | 对应节 |
|---|---|---|
| vanilla MPPI 的两个限制 | rollout 依赖真实动力学(慢/无模型)+ 短 horizon 看不到长期 | §6.1 |
| TD-MPC = 采样规划换两零件 | 学习的 latent 动力学(补限制一)+ 学习的终端价值(补限制二),内核不变 | §6.1 |
| 三组件架构 | 编码器 + latent 动力学 + reward + 价值(TOLD + 价值),都是小 MLP | §6.2 |
| 任务导向 latent | latent 只编码回报相关信息、不重建观测,靠联合训练学出 | §6.2 |
| latent 规划为何值得 | latent 动力学快、可大批量并行、自洽(不需真实模型,能吃像素) | §6.3 |
| policy prior 混合 | 摊销(策略给好起点)+ 即时(规划做精修),双层结构 | §6.3 |
| 终端价值核心洞察 | 短 horizon rollout + 学习价值 = 短 horizon 也有远见(demo: H=3+价值到大峰) | §6.4 |
| 加 horizon vs 加价值 | 加 horizon 救不了短视(demo: H=30 无价值仍困小峰),加价值 H=3 就够 | §6.4 |
| 三设计协同 | latent 模型(快)+ 短 horizon(避累积误差)+ 终端价值(补长期)缺一不可 | §6.4 |
| 联合训练三损失 | latent 一致性 + reward 预测 + TD 价值,联合训练共享编码器 | §6.5 |
| latent 一致性 vs 重建 | 在 latent 空间自洽(任务导向)而非重建观测;stop-gradient 防塌缩 | §6.5 |
| TD-MPC2 规模化 | implicit world model + 单一超参 + 工程改进,104 任务、317M、80 任务 | §6.6 |
| compounding error | 单步小误差多步累积(demo: 30 步放大 11×),逼出短 horizon | §6.8 |
| 根本权衡 | 模型保真度 vs 速度/可学习性——精确模型 vs 学习模型按任务定位 | §6.8 |
全章一句话速记¶
如果只能带走八句话,就是下面这八句——每节一句,串起来就是本章的完整骨架:
| 节 | 一句话 |
|---|---|
| §6.1 | vanilla 采样 MPC 有两个限制(依赖真实动力学、短 horizon 短视),学习世界模型给它换两个零件来补。 |
| §6.2 | TD-MPC 世界模型 = 编码器 + latent 动力学 + reward + 价值四个小网络,任务导向、不重建观测。 |
| §6.3 | 在 latent 空间跑 MPPI/CEM——编码、latent rollout、终端价值、采样更新,内核还是你会的采样规划。 |
| §6.4 | 短 horizon rollout + 学习的终端价值 = 短 horizon 也有远见;加 horizon 救不了短视,加价值能。 |
| §6.5 | 四网络用 latent 一致性 + reward + TD 三项损失联合训练,latent 一致性(非重建)是任务导向的关键。 |
| §6.6 | TD-MPC2 用 implicit 模型 + 单一超参 + 工程改进,把核心思想规模化成通吃 100+ 任务的通用控制器。 |
| §6.7 | 官方 plan 就是 §6.3–§6.4 的代码化;核心几十行就能写出,复杂全在规模化外壳。 |
| §6.8 | compounding error 是学习模型的原罪(逼出短 horizon);模型保真度 vs 速度是贯穿全章的根本权衡。 |
学完自检:你真的掌握了吗¶
读完本章,用下面几个问题自查。答不上来就回对应节再过一遍——这些是本章的"必须掌握"清单:
- 你能一句话说清"TD-MPC 和 MPPI/CEM 是什么关系"吗?(不能 → §6.1,关键词"换两个零件")
- 你能说清 TD-MPC 世界模型的四个组件各是什么、为什么在 latent 空间、为什么不重建观测吗?(不能 → §6.2)
- 你能解释"为什么短 horizon + 学习的价值能有远见,而加长 horizon 不行"吗?(不能 → §6.4,本章核心)
- 有人问"要补长期信息,加长 horizon 不就行了",你能指出为什么不行吗?(不能 → §6.4 + §6.8 compounding error)
- 你能说清 TD-MPC 训练的三项损失、为什么 latent 一致性要 stop-gradient 吗?(不能 → §6.5)
- 你能说清 TD-MPC2 相对 TD-MPC 改了什么、有没有动核心思想吗?(不能 → §6.6)
- 有人说"学个足够准的模型就能消除 compounding error、用长 horizon",你能反驳吗?(不能 → §6.8)
- 面对"有精确方程、要高精度"的任务和"只有像素、要通用"的任务,你会分别选精确动力学 MPC 还是 TD-MPC?(不确定 → §6.8 根本权衡)
能顺畅答完这八问,你就真正掌握了本章——不是记住了几个名字,而是抓住了"学习的 latent 模型 + 学习的价值 + 短 horizon + 清醒认识 compounding error 和根本权衡"这条完整的认知链。
承上启下¶
承上:本章是采样式 MPC 的一次重要延伸,也是它与强化学习的深度联姻。前几章(第 2–4 章)把采样规划的内核(MPPI/CEM)讲透,假设有一个能快速 rollout 的真实模型、用短 horizon。第 5 章在"已知模型、免训练"一端把采样优化做到极致。本章走到光谱另一端——学一个 latent 世界模型 + 学一个价值,把采样规划的两个零件(动力学、终端处理)换成学习的版本,从而绕开"依赖真实模型"和"短 horizon 短视"两个限制。第 2–4 章的采样规划内核、你的 RL 基础(价值函数、TD、SAC 双 Q),在本章被缝合成"在学习的 latent 空间里、用学习的价值做有远见的采样规划"。
启下:本章假设我们要么有真实模型(第 5 章)、要么能学一个模型(本章)。接下来的应用章节(腿足全身控制、导航/自驾/无人机)会把前面所有的采样式 MPC 工具——经典 MPPI、变体、扩散退火、学习世界模型——落到具体的机器人领域,看它们在真实系统上如何选型、组合、落地。本章的"学习世界模型 + 规划"会作为工具箱里的一件,和精确模型 MPC 互补;而本章建立的"模型保真度 vs 速度"的判断力,会指导你在真实应用里选择用哪种模型。
本章的累积项目¶
前几章你在搭一个"统一采样优化器"——从第 2 章的基础 MPPI,到第 4 章加上 weight(加权方式)、noise(噪声类型)、cov(协方差)三个正交维度,到第 5 章加上 schedule(退火)维度。本章给这个累积项目加上一个全新的、更高层的维度:model_source(动力学从哪来)和 terminal(终端怎么处理)。
具体地,把你的优化器接口扩展成支持两种模型来源和两种终端处理:
class UnifiedSamplingPlanner:
def __init__(self, weight='mppi', noise='gaussian', cov='fixed', schedule=None,
model_source='true', terminal='truncate'):
# 前几章的维度
self.weight = weight # 'mppi'(加权) / 'cem'(精英) —— 第4章
self.noise = noise # 'gaussian' / 'colored' —— 第4章
self.cov = cov # 'fixed' / 'adaptive' —— 第4章
self.schedule = schedule # None / 退火调度 —— 第5章
# 本章新增的两个维度
self.model_source = model_source # 'true'(真实动力学) / 'learned'(学习的latent) —— 本章
self.terminal = terminal # 'truncate'(直接截断) / 'value'(学习的价值) —— 本章
def rollout(self, z0, actions):
"""根据 model_source 选择在真实空间还是 latent 空间 rollout。"""
if self.model_source == 'true':
return self._rollout_true(z0, actions) # 真实动力学(第2-5章)
else:
return self._rollout_latent(z0, actions) # 学习的latent动力学(本章)
def terminal_cost(self, z_H, a_H):
"""根据 terminal 选择截断还是加价值。"""
if self.terminal == 'truncate':
return 0.0 # 直接截断(第2-5章)
else:
return self.gamma_H * self.Q(z_H, a_H) # 学习的价值(本章)
这样一来,你的统一优化器现在能表达的范围,从"在真实动力学里、短 horizon 的经典采样 MPC(第 2–5 章)"扩展到了"在学习的 latent 空间里、用学习价值的 TD-MPC(本章)"。把这两个维度和前几章的四个维度组合,你得到一个能覆盖从第 2 章到本章所有方法的统一框架:
model_source='true', terminal='truncate':经典 MPPI/CEM(第 2–4 章)model_source='true', terminal='truncate', schedule=anneal:扩散退火 MPC(第 5 章)model_source='learned', terminal='value':TD-MPC(本章)
读到这里你可能会问:这两个新维度和前四个维度是同一层级的吗? 不完全是。前四个维度(weight/noise/cov/schedule)都作用在"怎么采样、怎么更新"上,是采样优化的内部旋钮;而本章的两个维度(model_source/terminal)作用在"用什么模型、怎么收尾"上,是更外层的结构选择。它们正交于前四个维度——你可以在学习的 latent 模型上用退火(model_source='learned', schedule=anneal),也可以在真实模型上加价值(model_source='true', terminal='value',这其实就是经典 MPC 加终端代价)。这种正交性正是统一框架的威力:六个维度自由组合,覆盖一大片方法空间。
这个累积项目还能怎么往下走? 当前的 model_source='learned' 假设世界模型已经训好。一个自然的延伸是把**训练**也纳入框架——让优化器在"用模型规划采数据"和"用数据训模型"之间循环,成为一个完整的 TD-MPC 学习系统(§6.5)。如果你想在课程之外继续打磨,可以实现一个最小的训练循环(§6.7 的 MiniTDMPC + train_step),让你的统一规划器从"只会用给定模型规划"成长为"能自己学出模型再规划"。这会把你的项目从一个纯规划器,推向一个完整的 model-based RL 智能体。
延伸阅读¶
核心论文(按阅读顺序):
- TD-MPC(Hansen, Wang, Su, ICML 2022, arXiv:2203.04955):本章的源头,必读。重点读它如何用"任务导向 latent 动力学 + 终端价值 + TD 联合训练"融合 model-based 和 model-free。它的图 1(架构总览)和 latent 一致性损失(Eq. 10)值得仔细看。
- TD-MPC2(Hansen, Su, Wang, ICLR 2024, arXiv:2310.16828):规模化的代表。重点读它的架构改进(SimNorm、离散回归、Q 集成)和"单一超参覆盖 104 任务"的实验。配合 tdmpc2.com 上的可视化看更直观。
- TD-M(PC)²(arXiv:2502.03550, ICLR 2025):诊断 TD-MPC 的 policy mismatch / 价值过估计问题(§6.8 局限三)。读它如何用不到十行的 policy 约束缓解高维 locomotion 上的过估计——一个"小改动解决真问题"的范例。
背景与对照工作:
- Dreamer / DreamerV3(Hafner 等):另一条 latent world model 路线,用**重建式**模型 + 在 imagination 里优化策略。和 TD-MPC 对照读,能看清"重建式 vs 任务导向""想象优化 vs 规划"的区别。
- PlaNet(Hafner 等)、PETS(Chua 等):更早的 latent 动力学 + 规划工作。PlaNet 用 latent 动力学 + latent 空间轨迹优化,PETS 用概率模型集成 + CEM——理解它们能看清 TD-MPC 的改进从何而来。
- SAC(Haarnoja 等):TD-MPC 的价值学习、双 Q、最大熵 policy prior 都从 SAC 借来。RL 基础若需巩固,回看 SAC。
代码:
nicklashansen/tdmpc2:官方实现,约 770★。按 §6.7 的代码地图读:先world_model.py、再plan、再update。nicklashansen/tdmpc:TD-MPC 原版,更简洁,适合先读懂核心再看 TD-MPC2 的工程外壳。
一条务实的学习路线(综合以上资源):先跑通本章 §6.4 和 §6.8 的两个 NumPy demo 吃透核心洞察(短 horizon + 价值、compounding error),再读 TD-MPC 论文理解完整方法,然后按代码地图读 tdmpc 原版代码,最后若有算力再碰 TD-MPC2 的规模化。如果时间有限,哪怕只完成第一步(跑通两个 demo、亲手看到"加价值让短 horizon 有远见""误差如何累积"),你对本章核心的理解也会甩开"只读过论文"的人一大截——因为"短 horizon 为何要配价值"这件事,看一眼 demo 的数字,胜过读十遍文字。
怎么在这个高产方向里筛选新论文(元建议):学习世界模型 + 规划是当前最活跃的方向之一,每月都有新工作。用本章的框架快速筛选:(a) 先用"它的世界模型是重建式还是任务导向、规划用什么、终端怎么处理"给新工作定位;(b) 看它在哪个维度上推动了边界——更鲁棒(防 OOD/过估计)、更通用(跨任务/跨形态)、更省样本、还是更大规模;(c) 警惕"换个名字的 TD-MPC/Dreamer",用本章的概念框架几分钟就能判断它是真有新意还是换了层包装;(d) 优先读有真机实验、有开源代码的工作。在论文产量远超阅读能力的领域,"会筛选"比"读得多"更决定成长速度。
本章与后续章节的关系¶
本章在整个采样式 MPC 体系里的位置,以及它和前后章节的关系:
与前序章节(第 2–5 章):本章是采样规划内核的一次"换零件"延伸。第 2–4 章建立内核(MPPI/CEM)、假设真实模型 + 短 horizon;第 5 章在"已知模型、免训练"一端深耕。本章把动力学换成学习的 latent 模型、把终端截断换成学习的价值,走到"学习模型"一端。三者共享同一个采样规划内核,分居"模型从哪来"的不同位置。
与你的前置课程(梯度式 MPC / RL):本章是采样式 MPC 与 RL 的交汇点。它的规划用采样 MPC(本系列前几章),它的价值学习、双 Q、最大熵策略用 RL(你的 SAC 基础),它和梯度式 MPC(OCS2/Pinocchio)的对比构成"模型保真度 vs 速度"的根本权衡(§6.8)。学完本章,你手里的"采样 MPC"和"RL"两套工具被缝合成一个完整的 model-based RL 方法。
与后续应用章节(腿足、导航/自驾/无人机):后续章节会把本系列所有采样 MPC 工具落到具体机器人领域。本章的"学习世界模型 + 规划"是工具箱里的一件——在"没有精确模型、观测复杂、要通用"的场景(如从像素学操作)它是首选,在"有精确模型、要高精度"的场景则让位给精确模型 MPC。本章建立的"按模型保真度 vs 速度选型"的判断力,会直接指导后续应用里的工具选择。
与现代 model-based RL 浪潮:本章把你接到了当前最活跃的研究方向之一。理解了 TD-MPC,你再看 DreamerV3、世界模型、具身大模型等工作,都能用"学习的世界模型 + 某种规划/想象 + 价值"的框架去定位它们——本章是进入这个方向的钥匙。
把这些关系连起来看,本章既是采样式 MPC 的延伸(换零件),又是它与 RL 的联姻(融合价值),还是通往现代 model-based RL 的门户。学完它,你不只是多会了 TD-MPC,而是拿到了一把能打开"学习模型 + 规划"整个方向的钥匙。
再放到更大的图景里看一眼:当下机器人智能大致有两条主线在交汇——一条是"学习"(用海量数据训练大模型/策略),一条是"优化与控制"(用模型和算法在线求解)。本章正站在两条主线的交界处:它的规划内核是优化(采样 MPC),但它的模型和价值是学出来的(学习),并通过"短 horizon 规划 + 学习价值"把两者缝合。理解本章,某种意义上是理解"模型驱动"与"数据驱动"如何在控制里握手——而这正是未来机器人系统最可能的形态:不是纯学习、也不是纯优化,而是两者按问题特性各取所长地结合。你在本章建立的"用统一框架看待方法、按权衡定位工具"的能力,会是你在这个融合趋势里最稳的立足点。
故障排查手册¶
把 TD-MPC 实战中常见的故障按"症状 → 可能原因 → 排查步骤 → 相关节"整理,供你调试时查阅:
场景一:训练时 latent 一致性损失降不下来,或 latent 明显塌缩(所有状态编码成相近的向量)。
- 可能原因:latent 一致性损失忘了对编码目标 stop-gradient(编码器走捷径塌缩);或 reward/价值损失权重太小,没给 latent 提供足够的判别力信号。
- 排查步骤:① 检查 latent 一致性损失里编码目标是否 detach()/no_grad(§6.5 关键);② 打印不同状态的 latent,看是否塌成一团;③ 检查三项损失的权重比例,确保 reward/价值损失有足够分量塑造 latent;④ 确认编码器和动力学是联合训练(共享梯度)而非分开训。
- 相关节:§6.5(latent 一致性 + stop-gradient + 联合训练)、§6.2(任务导向)。
场景二:规划行为短视——只顾眼前、错过远处更优解(像 §6.4 demo 里困在小峰)。 - 可能原因:终端价值没加、或加错(忘乘 \(\gamma^H\));或价值函数没学好(估不准长期);或 horizon 太短且价值不可靠。 - 排查步骤:① 确认规划末端加了 \(\gamma^H Q(z_H, a_H)\)、折扣指数正确(§6.4 陷阱);② 单独评估价值函数准不准(在已知状态上对比预测价值和实际回报);③ 若价值不准,回到训练——检查 TD 损失是否收敛、目标网络是否正常软更新;④ 别靠加 horizon 救短视(§6.4/§6.8),而要查价值。 - 相关节:§6.4(终端价值核心)、§6.5(价值训练)。
场景三:价值估计持续升高、远超实际回报(价值过估计)。 - 可能原因:没用双 Q/集成(或集成数太少);或更深层的 policy mismatch(规划采的数据分布与价值学习不一致,§6.8);高维任务尤甚。 - 排查步骤:① 确认用了双 Q/Q 集成、取较小值(§6.5);② 监控价值估计量级 vs 实际回报,量化过估计程度;③ 若是高维 locomotion 且过估计顽固,可能是 policy mismatch(§6.8 局限三),考虑 TD-M(PC)² 的 policy 约束;④ 检查目标网络更新是否过快(过快会加剧过估计)。 - 相关节:§6.5(双 Q)、§6.8(policy mismatch)。
场景四:规划被"模型觉得很好、实际很糟"的动作误导,行为诡异不稳定。 - 可能原因:采样把状态带到 OOD 区域,模型在那里"自信地犯错"、给出虚高回报(§6.8 局限二);训练数据覆盖不足。 - 排查步骤:① 检查规划是否探索到训练数据没覆盖的区域(监控 latent 是否偏离训练分布);② 用模型集成估计预测不确定性,看被选中的动作是否落在高不确定区域;③ 考虑约束规划探索范围(动作别偏离 policy prior 太远)或惩罚高不确定回报;④ 增加训练数据对相关区域的覆盖。 - 相关节:§6.8(OOD、鲁棒规划)、§6.3(policy prior 引导)。
场景五:rollout 长一点(加 horizon)性能就变差,短 horizon 反而好。 - 可能原因:这正是 compounding error(§6.8 局限一)——学习模型多步 rollout 累积误差,长 horizon 的 rollout 失真。 - 排查步骤:① 这不是 bug 而是学习模型的固有特性(§6.8),确认你理解了;② 把 horizon 保持短(3~5),靠终端价值补长期(§6.4),而非加 horizon;③ 若想验证,跑 §6.8 的 compounding error demo,看误差随步数累积;④ 若长期信息确实不足,查价值学得准不准,而非加 horizon。 - 相关节:§6.8(compounding error)、§6.4(短 horizon + 价值)。
场景六:latent 在多步 rollout 中数值发散(越来越大或 NaN)。 - 可能原因:latent 没有归一化约束(TD-MPC2 用 SimNorm 约束尺度),或学习率过大导致动力学不稳定。 - 排查步骤:① 检查是否用了 SimNorm 或其他 latent 归一化(§6.6);② 监控 rollout 中 latent 的范数,看是否随步数增长;③ 检查动力学网络的训练是否稳定(LayerNorm、合理学习率);④ 确认 latent 一致性损失正常(它间接约束 latent 不乱跑)。 - 相关节:§6.6(SimNorm)、§6.5(latent 一致性)。
场景七:训练初期规划行为完全随机、长时间不见好转。 - 可能原因:训练刚开始时模型(动力学、reward、价值)都还没学好,规划基于一个"乱猜"的模型,行为自然随机——这在初期是**正常**的;但若长时间(远超正常预热期)不见好转,则可能是 reward 信号有问题、学习率不当、或 buffer 数据太少/太单一。 - 排查步骤:① 先确认这是不是正常的初期预热(TD-MPC 需要积累一定交互、模型才开始学好,初期随机是预期的);② 检查 reward 是否正确传入、量级是否合理(reward 全 0 或异常会让什么都学不到);③ 检查 replay buffer 是否在正常积累数据、采样是否正常;④ 监控三项损失是否在下降(若损失完全不降,是训练 pipeline 的 bug,而非预热);⑤ 对照官方在同任务上的训练曲线,看你的预热期是否异常长。 - 相关节:§6.5(训练循环)、§6.7(实战:先验证训练 pipeline)。
场景八:规划太慢,达不到实时控制频率。 - 可能原因:latent rollout 没有向量化(逐条 rollout,§6.3 陷阱);或采样数/迭代次数/horizon 设得过大;或在 CPU 上跑本该用 GPU 的规模。 - 排查步骤:① 首先确认 latent rollout 是批量并行的(\(K\) 条一起推,只有 \(H\) 步串行)——这是最常见的性能杀手(§6.3 陷阱);② 检查 num_samples、iterations、horizon 是否远超默认值(默认 512/6/3 已经够用,别盲目调大);③ 确认 policy prior 和 warm-start 都开着(它们让少量迭代就够,§6.3);④ 大规模任务用 GPU;⑤ 若仍不够快,考虑减小采样数或模型规模,权衡质量与速度。 - 相关节:§6.3(latent 规划批量化、warm-start、迭代次数)、§6.7(实战要点)。
概念与 API 速查表¶
把本章用到的关键概念、公式、超参整理成速查表,供动手时查阅。
核心公式速查:
| 公式 | 含义 | 出处 |
|---|---|---|
| \(z = h_\theta(o)\) | 编码器:观测 → latent | §6.2 |
| \(z' = d_\theta(z, a)\) | latent 动力学:预测下一 latent | §6.2 |
| \(\hat r = r_\theta(z, a)\) | reward 预测(latent 上) | §6.2 |
| \(G = \sum_{t=0}^{H-1}\gamma^t r_\theta(z_t,a_t) + \gamma^H Q_\theta(z_H, a_H)\) | 一条轨迹的回报:rollout + 终端价值(本章核心) | §6.4 |
| \(Q_{\text{target}} = r + \gamma Q_{\bar\theta}(z', a')\) | TD 目标(学价值) | §6.5 |
| \(\|z_t - \text{sg}(h_\theta(o_t))\|^2\) | latent 一致性损失(编码目标 stop-gradient) | §6.5 |
| \(\mathcal{L} = \sum_t \lambda^t[c_1 L_{\text{cons}} + c_2 L_{\text{rew}} + c_3 L_{\text{TD}}]\) | 联合损失三项 | §6.5 |
TD-MPC2 默认超参速查:
| 参数 | 默认值 | 说明 |
|---|---|---|
| horizon | 3 | 短 horizon(TD-MPC v1 用 5) |
| num_samples | 512 | 每次规划采样数 |
| num_elites | 64 | 精英数 |
| iterations | 6 | 迭代轮数(动作维度≥20 时 +2) |
| num_pi_trajs | 24 | policy prior 轨迹数 |
| 单任务模型 | 5M 参数 | 单任务在线 RL 默认 |
| 多任务模型 | 1/5/19/48/317M | 可选规模 |
| gamma | 启发式 | \(\min(\max(\frac{\text{ep}/5-1}{\text{ep}/5}, 0.95), 0.995)\) |
关于这些起点值的一句话:这些是 TD-MPC2 跨所有任务的鲁棒默认值("单一超参"的含义)——直接用通常就好,不必逐任务精调。重点记住 horizon=3(短,靠价值补长期)、单任务模型才 5M(任务导向、不浪费容量)。
按问题特征快速选择(速查):
| 你的问题有这个特征 | 倾向的选择 | 出处 |
|---|---|---|
| 有精确动力学方程、状态可观测、要高精度 | 精确动力学 MPC(OCS2/Pinocchio,前置课程) | §6.8 |
| 观测是像素、没有动力学方程 | 学习的 latent 世界模型(TD-MPC) | §6.1/§6.8 |
| 要一套方法通吃多个任务 | TD-MPC2(单一超参 + 多任务模型) | §6.6 |
| 规划短视、错过远处更优 | 加学习的终端价值,别加 horizon | §6.4 |
| 长 rollout 反而变差 | compounding error,保持短 horizon | §6.8 |
| latent 塌缩 / 一致性损失不降 | 检查 stop-gradient + 联合训练 | §6.5 |
| 价值持续高估 | 双 Q/集成;高维顽固则查 policy mismatch | §6.5/§6.8 |
| latent 多步发散 | 加 SimNorm 归一化 | §6.6 |
| 规划被虚高回报误导 | OOD,估不确定性 / 约束探索范围 | §6.8 |
| 没有 GPU | 跑最小实现 + 简单环境 / 用预训练 checkpoint 评估 | §6.7 |
研究与实践建议¶
把本章的经验提炼成几条建议,无论你是做研究还是工程:
动手跑 demo,胜过反复读论文。 本章核心洞察(短 horizon + 价值有远见、compounding error 累积)用两个 NumPy demo 就能看清。亲手跑、改参数、看数字怎么变,建立的直觉比读十遍论文牢。这个方向高度依赖"看到模型 rollout 和价值如何影响决策"的直觉。
先吃透 TD-MPC 核心,再碰 TD-MPC2 工程。 TD-MPC 的核心(latent 模型 + 终端价值 + TD)是地基,TD-MPC2 的一堆改进(SimNorm、离散回归等)是规模化外壳。先把地基打牢,外壳逐个理解即可。别被 TD-MPC2 的工程细节吓住,它们不改核心。
把"任务导向"刻进脑子。 TD-MPC 区别于 Dreamer/PlaNet 的命门是"任务导向、不重建观测"。理解了"表示该为下游任务定制、而非追求通用重建",你不仅懂 TD-MPC,还握住了现代表示学习的一个核心思想(呼应自监督学习)。
清醒对待 compounding error 和 OOD。 学习模型有"原罪"(compounding error)和盲区(OOD),别幻想"学个完美模型"。设计时承认局限、绕过它(短 horizon + 价值、防 OOD),这是务实的工程态度。监控 latent 一致性和价值量级,是 TD-MPC 健康的体温计。
用"模型保真度 vs 速度"做选型判断。 面对"用什么模型做决策",别找不存在的银弹,而问"任务在权衡谱上站哪里"。要精确可靠就用精确模型(接受慢/要方程),要通用吃像素就用学习模型(接受误差/黑箱)。这个判断力比掌握任何单个方法都重要。
把"调代价/reward"和"调算法"同等重视。 本章和前几章一样,规划质量既取决于算法(latent 模型、价值),也取决于 reward 设计——一个写错的 reward 会让再好的世界模型学出错误的价值、规划出错误的行为。reward 设计是 model-based RL 同样关键的一环。
关注这个方向的开放问题。 compounding error 的鲁棒规划、policy mismatch、世界模型的规模化/通用化——这些是当前最活跃、最可能出新工作的题目。一个方法的局限,往往就是下一批研究的起点。
版本信息速查¶
本章涉及的方法、论文、代码的版本信息,便于查阅和引用:
| 项目 | 信息 |
|---|---|
| TD-MPC 论文 | Hansen, Wang, Su, Temporal Difference Learning for Model Predictive Control, ICML 2022, PMLR 162, pp. 8387–8406, arXiv:2203.04955 |
| TD-MPC2 论文 | Hansen, Su, Wang, TD-MPC2: Scalable, Robust World Models for Continuous Control, ICLR 2024, arXiv:2310.16828 |
| TD-M(PC)² 论文 | Improving Temporal Difference MPC Through Policy Constraint, arXiv:2502.03550, ICLR 2025 |
| TD-MPC 代码 | github.com/nicklashansen/tdmpc(原版,约 500★) |
| TD-MPC2 代码 | github.com/nicklashansen/tdmpc2(约 770★),项目页 tdmpc2.com |
| TD-MPC2 开源资源 | 324 个 checkpoint(12 个多任务模型,1M~317M)+ 545M/345M transition 数据集 |
| 主要基准 | DMControl、Meta-World、ManiSkill2、MyoSuite(TD-MPC2 共 104 任务) |
| 对照方法 | SAC、DreamerV3(被 TD-MPC2 超越);PlaNet、PETS、Dreamer(latent 模型先驱) |
也要提醒一句关于数字的态度:本章引用的性能结论(如"104 任务""317M 参数""首次 1M 步解决 Dog 任务")都来自原论文在特定设置下的报告,它们证明的是"这条路走得通、效果显著"这一质的结论,不是你换个任务就能照搬的承诺。引用时务必回到原论文核对口径(什么任务、什么基线、什么指标),并以正式发表版为准。一个好习惯:转述论文数字时,连同它的任务条件和对比对象一起转述,而非孤立地甩一个数字。
收束语¶
到这里,本章走完了——从"vanilla 采样 MPC 的两个限制"出发,到学习的 latent 世界模型如何给采样规划换上两个零件,到"短 horizon + 学习价值 = 有远见"这个核心洞察,到联合训练、规模化,最后到诚实的局限与根本权衡。
回头看你走了多远:前几章你掌握了采样规划的内核(MPPI/CEM),假设有真实模型、用短 horizon。本章你把这个内核搬进了一个**学习的 latent 空间**、用**学习的价值**补足了长期——采样式 MPC 由此从"在真实动力学里做短视的局部优化",升级为"在学习的世界模型里做有远见的规划"。更重要的是,你看清了这次升级的本质:它没有抛弃采样规划,而是给它换了两个零件(动力学、终端处理),并借此和强化学习的价值学习深度联姻。
这一路你收获的,远不止"TD-MPC"这一个方法。你练就的是一种看待"模型 + 规划"的眼光:任何用学习模型做规划的方法,都逃不开 compounding error 的原罪,都需要"短期信任模型、长期用价值"的鲁棒设计;任何"用什么模型"的选择,都落在"保真度 vs 速度/可学习性"的权衡谱上,没有银弹;任何"学习 + 规划"的混合方法,都能用"摊销给起点、规划做精修"的骨架去理解。带着这副眼光,你再看 DreamerV3、世界模型、具身大模型这些当下最热的工作,都不再是陌生的新大陆,而是同一片海域里、用同一套航海术去探索的新航线。
而把这一章放进整个采样式 MPC 部分,你会看到一条清晰的脉络:从路径积分理论(第 1 章)到 MPPI 核心(第 2 章)、变体与统一(第 3–4 章)、扩散退火(第 5 章),再到本章的学习世界模型——采样式 MPC 的能力边界,被一步步从"低维、已知模型、短视"推向"高维、学习模型、有远见"。每一章都在同一个采样规划内核上做文章,却让它能解的问题越来越大。
接下来的应用章节,会把这一路积累的全部工具——经典 MPPI、六大变体、扩散退火、学习世界模型——落到腿足、导航、自驾、无人机这些真实的机器人领域,看它们如何在真实系统上选型、组合、落地。本章建立的"模型保真度 vs 速度"的判断力,会一路陪你走下去:在真实应用里,你不会问"哪个方法最先进",而会问"我的任务该站在权衡谱的哪里"。出发吧。
跨章综合应用¶
把本系列的工具串成一条完整的解题链,用一个具体情境演示它们如何协同。这不是新知识,而是帮你看清各章如何拼成一个整体——也是检验你是否真把这几章学成了"一棵知识树"而非"一堆散点"的好机会。
情境:你要为一个**只有 RGB 摄像头、要学会多种桌面操作任务的机械臂**设计控制方案。没有精确的动力学方程(接触复杂、物体多样),观测是高维像素,且希望一套方案能做多个任务。
第 1 步——判断该用哪类方法(§6.1 + §6.8 + 总论)。先在"模型保真度 vs 速度/可学习性"的权衡谱上定位:观测是像素(没有状态方程)、要通用(多任务)、能容忍一定误差——这把你推向"学习的 latent 世界模型"一端,而非精确动力学 MPC(OCS2/Pinocchio 那条线,它要状态方程、不吃像素)。所以选 TD-MPC 系列。
第 2 步——搭世界模型(§6.2)。设计四个组件:编码器把像素观测压成 latent(任务导向,不重建图像)、latent 动力学在 latent 空间预测、reward 预测、价值。用 TD-MPC2 的 implicit/decoder-free 设计——不重建像素,只在 latent 空间工作(§6.6)。
第 3 步——在 latent 空间规划(§6.3 + §6.4)。用采样规划(MPPI/CEM)在 latent 空间 rollout:编码当前像素 → 采动作序列 → latent rollout 短 horizon(H=3~5)→ 末端加学习的价值补长期 → 加权更新 → 执行第一个动作。短 horizon 避开 compounding error,终端价值给远见(§6.4 核心)。掺入 policy prior 加速规划(§6.3)。
第 4 步——联合训练(§6.5)。用 latent 一致性 + reward + TD 三项损失联合训练四个网络。latent 一致性 stop-gradient 防塌缩,reward/价值损失塑造任务导向的 latent。用双 Q/集成抑制价值过估计。规划采数据、数据训模型,循环往复。
第 5 步——多任务规模化(§6.6)。要一套方案做多个任务:用 TD-MPC2 的可学习任务嵌入 + 动作 masking,让一个模型吃多个任务的不同观测/动作空间。用单一超参集(不逐任务调参),按需选模型规模。
第 6 步——诚实评估,防范风险(§6.8)。跑出结果后清醒评估:监控 latent 一致性损失(防塌缩)和价值量级(防过估计);警惕规划被 OOD 区域的虚高回报误导(像素任务尤其容易遇到没见过的视觉场景);保持 horizon 短(别试图加 horizon 救任何问题)。若高维任务价值过估计顽固,考虑 policy 约束(§6.8 TD-M(PC)²)。
这条链清楚地展示了各章的分工:总论和 §6.8 给"选哪类方法(精确 vs 学习模型)",§6.2 给"模型长什么样",§6.3–§6.4 给"怎么规划、核心洞察",§6.5 给"怎么训练",§6.6 给"怎么规模化",§6.8 给"怎么诚实评估、防风险"。前几章的采样规划内核(第 2–4 章)则贯穿第 3 步——TD-MPC 的规划就是它们。一个真实问题,需要你把整串工具按顺序调用,而非孤立地用某一个。
跨章综合思考题¶
下面几题需要你调用多章知识综合作答,没有标准答案,重在论证过程。建议把它们当成"用写作倒逼理解"的练习——能把一个跨章问题论证清楚,往往比做对十道套公式的题更能暴露你哪里还没真懂。
-
(采样规划内核的"不变量",⭐⭐⭐) 从第 2 章的 vanilla MPPI,到第 4 章的统一视角,到第 5 章的扩散退火,再到本章的 TD-MPC,采样规划的内核始终是"采样—rollout—加权/精英更新—执行第一个—滚动时域"。请论证:(a) 这个内核在这四章里分别"换了什么、没换什么"?(提示:第 4 章换更新方式/噪声/协方差,第 5 章加退火调度,本章换模型来源 + 终端处理。)(b) 为什么这个内核如此稳定、能承载这么多变化?(c) 这种"稳定内核 + 可换零件"的设计,对你理解和创造新方法有什么启发?
-
(精确模型 vs 学习模型的终极权衡,⭐⭐⭐⭐) 综合第 5 章(免训练、用精确模型)和本章(学习模型),以及你的前置课程(OCS2/Pinocchio 精确动力学 MPC),论证"模型保真度 vs 速度/可学习性"这个根本权衡:(a) 把"精确动力学 MPC(OCS2)""免训练扩散 MPC(第 5 章)""学习世界模型(TD-MPC)"三者放在权衡谱上排序,各自的位置和理由是什么?(b) 给定一个具体任务(你自选),论证你会选谁、为什么。(c) 有没有可能"既要精确又要快又要通用"?为什么这个权衡是根本的、不是工程不够努力?(d) 三者能否在一个系统里组合(如学习模型做高层、精确模型做底层)?设想一个这样的混合系统。
-
(终端价值与前瞻搜索的统一视角,⭐⭐⭐⭐) 本章的"短 horizon rollout + 学习的终端价值",和 AlphaZero 的"MCTS 树搜索 + 价值网络"在思想上高度一致——都用"有限的前瞻 + 学习的价值"逼近"无限 horizon 的最优决策"。请论证:(a) 把 TD-MPC 的"短 horizon 采样 + 终端价值"和 AlphaZero 的"MCTS + value network"逐一对应——前瞻部分各是什么、价值部分各是什么、如何结合?(b) 为什么"有限前瞻 + 学习价值"是个比"纯前瞻(无限 horizon)"或"纯价值(model-free)"都好的范式?(c) 这个范式的成立,依赖什么前提(提示:前瞻要准、价值要准)?(d) 你能否把这个统一视角推广成一个一般原则——"如何用有限的计算 + 学习的概括,逼近无限的最优"?这个原则还能用在哪些别的问题上?
-
(compounding error 的跨方法视角,⭐⭐⭐) compounding error(学习模型多步 rollout 误差累积)是本章的核心局限。请论证:(a) 第 5 章的免训练扩散 MPC 用的是精确模型,它有 compounding error 吗?为什么?(b) 本章的 TD-MPC 用学习模型,它如何"绕过"(而非消除)compounding error?(c) 把"用不完美预测做多步决策"这个问题推广——金融预测、天气预报、供应链规划都面临类似的误差累积,它们一般怎么应对?(d) 是否存在一个通用的"对预测误差鲁棒的多步决策"原则?TD-MPC 的"短期信任模型、长期用价值"是它的一个实例吗?
-
(学习 + 规划的混合范式全景,⭐⭐⭐⭐) 本章的 TD-MPC(学习模型 + 采样规划 + 价值)、第 5 章末尾的 learned prior(数据先验 + 扩散规划)、AlphaZero(学习价值/策略 + 树搜索),都是"学习 + 规划"的混合。请综合论证:(a) 这些方法都在用"学习的组件"和"规划的组件"配合,各自的"学习部分"和"规划部分"分别是什么?(b) 为什么"学习 + 规划"普遍优于"纯学习"或"纯规划"?(用"摊销 vs 即时""泛化 vs 精确"的语言。)(c) 提炼一个一般的"学习 + 规划"设计模式——学习负责什么、规划负责什么、如何分工?(d) 用这个模式预测:未来"学习 + 规划"的混合方法,可能在哪些方向继续发展?