Lecture 15: 客座讲座 —— 世界建模的世界(Guest Lecture: World of World Modeling, Shane Gu)

目录 · ← l14 · l16 →

Lecture 15: 客座讲座 —— 世界建模的世界(Guest Lecture: World of World Modeling, Shane Gu)

对应材料:官方 ShaneGuCS234_2026.pdf(36 页,标题页署名「Shane Gu 顾世(World)翔,Senior Staff RS, Google DeepMind」——把「World」嵌进中文名里是本讲的第一个双关;本讲不在 SPEC §7 的 SB 章节映射中,讲义即唯一阅读材料) 日程:Week 9 周一(官方日程表记为 2026-03-02;PDF 标题页印的日期是 2026-02-25)。lecture14pre.pdf 第 2 页明确写着「Last time: MCTS and guest lecture Shane Gu from DeepMind on World Models」,可据此确认本讲在课程中的位置 一句话定位:本讲把「世界模型」从 L2 的表格 $\hat P(s^{\prime}\vert s,a)$ 一路推广到 L13–L14 的隐空间模型与视频生成模型,是整门课中唯一把 model-based RL 与大规模生成式序列建模放在同一框架下讨论的一讲;讲者本人的立场是「世界模型就是 model-based RL 里的那个 model」(讲义第 5 页原话)。

讲义性质说明(重要):本讲幻灯片以图为主,PDF 抽取出的文本层只有约 8 KB、312 行,大量幻灯片只剩标题与年份、图内文字完全丢失(第 6、7、9、18、19、20、24、29、32 页等)。下文凡是讲义文本明确给出的内容,均按原文忠实转述;凡是只有标题/年份而正文缺失的地方,我们按标题补写该主题的标准技术内容,并一律用「标题推断」标注,绝不冒充讲义原文。讲义第 8 页讲者还主动声明:「I won’t talk about any Gemini / Veo / Genie.」——因此本笔记也不会替讲者补充这三条产品线的内容。


15.1 概述

本讲回答的问题是:当我们说在 RL 里「学一个模型」时,我们到底在学什么? 讲者给出的最短答案是第 5 页那句「World model is the ‘model’ in model-based RL」——世界模型(world model)就是模型基强化学习(model-based reinforcement learning, model-based RL)中那个用来替代真实环境的可学习对象。但讲座的真正野心在第 11–13 页:他把预测上升为理解的同义词,用 Solomonoff 归纳(Solomonoff induction)说明「最好的预测就是推出能复现数据的最短程序」,进而论证因果结构才是分布外(out-of-distribution, OOD)泛化的来源,而 GPT-3 式的「什么都预测」正是靠多样化干预数据逼近这一目标。第 14–17 页给出全场最凝练的框架:预测的三个层次(Level 1 被动拟合世界、Level 2 主动拟合世界、Level 3 主动让世界变得可预测),并坦承 Level 3「Nobody has cracked this yet at scale」。第 18–28 页回到工程:前向模型与逆向模型、射击法(shooting)与直接配点法(direct collocation)的规划对比、接触不变优化(Contact Invariant Optimization, CIO)、以及把值函数与决策 Transformer(decision transformer)都重新解释为「隐式世界模型」。最后第 29–35 页展望物理与符号世界模型:LLM 用符号推理,视频模型在空间与时间中推理,并提出链式帧(Chain-of-Frames, CoF)与思维链(Chain-of-Thoughts, CoT)的类比。本讲在课程知识链上位于 L13–L14(MCTS、AlphaZero/MuZero)之后,把「模型可以已知(L2 的表格、AlphaZero 的模拟器)」推进到「模型必须自己学、而且可以学在隐空间或像素空间」。

15.2 核心概念的数学形式化

本节按讲义页序逐页还原概念。每个概念给出「严格定义 → 直观解释 → 具体示例 → 与监督学习/纯 model-free RL 的对比」。

15.2.1 世界模型:定义之争(讲义第 3–5 页)

严格定义(讲者的立场,第 5 页原文):世界模型就是 model-based RL 中的模型。形式化地,给定 MDP $(\mathcal{S},\mathcal{A},P,R,\gamma)$,世界模型是一对可学习的近似

\[\hat P(s'\mid s,a)\;\approx\;P(s'\mid s,a),\qquad \hat R(s,a)\;\approx\;R(s,a),\qquad (s,a,s')\in\mathcal{S}\times\mathcal{A}\times\mathcal{S}.\]

讲义第 4 页引用了 Jitendra Malik 的批评:这个术语本身造成了混乱,「control theorists started using [the term ‘dynamics model’] in 1960」,而「world models」一词流行起来之后「we now have so much confusion about which definition of a world model we are discussing」。讲者把这个定义争议放在讲座最前面,等于宣告:本讲的「世界模型」是一个家族,不是一个算法。

直观解释:世界模型是一台「如果……会怎样」的机器。给定当前局面和你的动作,它替你回答「下一步世界会变成什么样、我会拿到多少奖励」。它与真实环境的差别,就是它与 L2 里那张已知转移表之间的差别。

具体示例(5×5 随机 GridWorld,本笔记 §15.4 实测环境):状态 $S=25$,动作 $A=4$(上/右/下/左),打滑概率 $\text{slip}=0.1$,每步奖励 $-0.04$,抵达目标 $+1$,$\gamma=0.95$。真实世界模型是一个 $25\times 4\times 25$ 的张量:$P(0,\text{上},0)=0.9+0.025=0.925$(因为另外三个动作各有 $0.1/4=0.025$ 的概率也会把状态 $0$ 送回状态 $0$),$P(0,\text{右},1)=0.925$,$R(0,\text{上})=-0.04$。学到的 $\hat P$ 就是对这个张量的估计。

与监督学习/前序方法的对比:监督学习学的是 $p(y\mid x)$,世界模型学的是给定动作条件下的状态转移分布——多了「动作」这个干预变量,因此它不是单纯的相关性拟合,而是(如第 13 页所说)要逼近因果结构。与纯 model-free RL(L4 的 Q-learning、L5–L7 的策略梯度)相比,世界模型允许在「不碰真实环境」的前提下做规划(planning)与想象(imagination),代价是要额外承担模型误差。

关于第 3 页(Schmidhuber 谱系):讲义列出了 Jürgen Schmidhuber 的六项工作,本笔记照原文转述——1990 年提出基于 RNN 的世界模型用于规划;1990 年提出高维多向量奖励信号;1990 年给出RNN 的确定性策略梯度;1990 年发明对抗式人工好奇心(讲者标注为 GAN 的基础);1991 年提出神经网络蒸馏与计算意识;2004–2005 年把世界模型应用于物理 AI 与自愈机器人。这一段的历史意义是:世界模型并非生成式模型时代的新发明,而是一条从 1990 年延续至今的线索。

15.2.2 预测 = 理解:Solomonoff 归纳(讲义第 9–12 页)

严格定义:Solomonoff 归纳(第 11 页原文「Formalization of Bayes theorem in computation theory」)是在程序空间上做贝叶斯推断。设观测为 $\mathcal{D}=(x_1,\dots,x_n)$,先验 $2^{-\ell(p)}$ 偏向短程序($\ell(p)$ 为程序 $p$ 的比特长度),则对下一个符号的预测为

\[p(x_{n+1}\mid \mathcal{D}) \;=\; \sum_{p\,:\,p(\mathcal{D})=x_{1:n}} 2^{-\ell(p)}\; p(x_{n+1}\mid \mathcal{D},p)\;\;\Big/\;\;\sum_{p\,:\,p(\mathcal{D})=x_{1:n}} 2^{-\ell(p)} .\]

这正是奥卡姆剃刀的数学形式;讲义把与之相关的工具点名为柯尔莫哥洛夫复杂度(Kolmogorov complexity)与最小描述长度(minimum description length, MDL),并指出它启发了 C-Test(Hernandez-Orallo et al. 1998)与通用智能(Universal Intelligence, Legg & Hutter 2007)。

直观解释:第 12 页的公式化表述是「The best prediction is inferring the shortest program that reproduces the data」(讲者引用 Ilya Sutskever),并由等号连成一条链条:

\[\text{Prediction}\;=\;\text{Understanding}\;=\;\text{Inferring the causal program of a phenomenon.}\]

具体示例(讲义原文列举):IQ 测试、顿悟(”Aha!” moments)、科学发现、深度学习中的突现泛化(grokking)、物理学中的相变(phase transitions)。讲义进一步给出两个跨模态例证:文本预测产生情感理解(OpenAI Sentiment Neuron),视频/音频预测产生物理与情感理解(Google Veo3)。结论句是「Despite hardware differences, humans and AI models both build intelligence through prediction—mastering prediction means mastering understanding.」

与监督学习/前序方法的对比:标准监督学习固定假设类(比如线性函数、固定深度的网络),在这个类里最小化经验风险;Solomonoff 归纳不固定假设类,而在全部可计算程序上做加权,因此它的「模型选择」是自动的。这也解释了为什么世界模型的容量选择(表格?图网络?视频模型?)在本讲里被当作建模哲学问题而非超参数问题。

15.2.3 因果性与 OOD 泛化(讲义第 13 页)

严格定义(讲义原文要点):不变风险最小化(Invariant Risk Minimization, IRM, 2019)指出「non-causal spurious data biases prevent true OOD generalization in ML」。讲义给出的补救是:让数据来自真实因果图的不同干预(interventions),则泛化可以实现,并把这条路线压缩为一句口号「Diversity is all you need」→ GPT-3,即「train to predict everything」。

直观解释:只在一个环境里训练的世界模型学到的是「相关」而不是「因果」。比如房间里有一台会随机播放噪点的电视(噪声电视,noisy TV),预测误差驱动的好奇心会被它永久吸引——因为你永远预测不准它。只有见过同一因果机制在多种干预下的表现,模型才能区分「因果变量」与「虚假相关」。

具体示例:在 §15.4 的 GridWorld 里,若只用一条确定性轨迹(永远向右、向下)训练世界模型,那么模型永远学不到向上/向左的转移,学到的 $\hat P$ 在那些 $(s,a)$ 上是均匀先验(拉普拉斯平滑后为 $1/25$)。一旦策略改变,模型立刻失效——这就是「数据分布不覆盖干预」的代价。

与监督学习的对比:监督学习的 i.i.d. 假设在这里被明确放弃。世界模型训练数据的分布由策略决定,而策略又由模型决定,构成反馈回路——这正是 15.2.5 要讲的 Level 2 与 Level 3。

15.2.4 前向模型与逆向模型(讲义第 18–19 页)

严格定义:讲义第 19 页给出两族模型,并注明「assume deterministic for simplicity」:

\[\text{前向模型(forward model):}\quad \hat s_{t+1}=f_\phi(s_t,a_t),\qquad \text{逆向模型(inverse model):}\quad \hat a_t=g_\psi(s_t,s_{t+1}).\]

(讲义第 19 页还写了一句「will explain why I chose those symbols」,但该页的符号细节在图里、未进入文本层,故此处不作推测。)

直观解释:前向模型回答「做了这个动作会到哪」,用于规划与想象;逆向模型回答「从这儿到那儿需要做什么」,用于从无动作标签的视频里反推动作、给表示学习提供监督信号,以及模仿学习。

具体示例:在 GridWorld 中,前向模型就是那张 $P(s^{\prime}\vert s,a)$ 表;逆向模型则是「若 $s_t=(0,0)$、$s_{t+1}=(0,1)$,则动作必为右」,即 $g(0,1)=\text{右}$。两者合起来:前向模型用于规划,逆向模型用于从观测中恢复意图

与监督学习的对比:前向模型是以动作为输入的监督学习(回归/分类);逆向模型是以「未来状态」为标签的监督学习,与 L7–L8 的模仿学习直接相关——讲义第 16 页把 DAgger、GAIL 放进 Level 2,正是因为它们也用「当前策略诱导的数据分布」去训练模型/策略。

15.2.5 赋能与预测的三个层次(讲义第 14–17 页)

这是本讲最具辨识度的框架。讲义第 14 页原文:

  • Level 1:Passively fit your world model on world(被动地让世界模型拟合世界)
  • Level 2:Actively fit your world model on world(主动地让世界模型拟合世界)
  • Level 3Actively fit world to your world model(主动让世界去拟合你的世界模型)

记号约定(讲义原文):$s=$ future of the world,$z=$ your actions。讲义把 empowerment(赋能) 归功于 Daniel Polani (2005) 与 Shakir Mohammed (2015)。

严格定义(赋能):给定策略 $\pi$ 与转移核 $P$,赋能定义为动作序列与未来状态之间的互信息

\[\mathfrak{E}(s)=\max_{\pi}\;\; I\big(z_{t+k};\; s_{t+k}\mid s_t\big) =\max_{\pi}\;\; \mathbb{E}\Big[\log\frac{p(s_{t+k}\mid z_{t+k},s_t)}{p(s_{t+k}\mid s_t)}\Big],\]

即「你的动作能在多大程度上改变世界的未来」。

Level 1(第 15 页):对应预训练、监督学习、自监督学习、生成式建模;讲义强调「Data distribution is stationary during predictive training」。用 §15.2.1 的记号,$s_{t+1}\sim P$ 与策略无关,优化目标是 $\max_\phi \mathbb{E}{(s,a,s^{\prime})\sim \mathcal{D}}\log \hat P\phi(s^{\prime}\vert s,a)$。

Level 2(第 16 页):对应后训练(post-training)、DAgger、GAIL、主动学习;讲义强调「Data distribution is non-stationary during predictive training」。讲义点名三项经典工作:VIME(Houthooft et al. 2017)tackles noisy TV problem(用贝叶斯神经网络后验的熵作为信息增益奖励,从而不被噪声电视永久吸引);DPM(Stadie 2016)与 ICM(Pathak 2017)incentivizes novelty(用预测误差/前向-逆向特征作为内在奖励)。

Level 3(第 17 页):在世界上采取行动,使世界相对于你或你自己的世界模型变得可预测。讲义原文举的三个例子是:Politicians(政客)、Financial firms(金融机构)、X Influencers(X 上的网红)——即通过行动改变世界以让世界符合自己的预测。讲义的评价是「Difficult objective. Nobody has cracked this yet at scale.」(第 36 页的告别语也正是「Thank you! Remember the Level 3.」)

具体示例:在 GridWorld 里,Level 1 是「随机策略采集 3000 条数据拟合 $\hat P$」;Level 2 是「用当前学到的模型做规划、执行、把新数据回灌,反复迭代」;Level 3 则对应「主动改造环境(例如把噪声电视关掉)使世界更可预测」。

与纯 model-free RL 的对比:纯 model-free 方法没有显式的「模型拟合」步骤,因此三层次框架对它们无从谈起;但同时,Level 2 的 DAgger/GAIL 与 Level 3 的干预式数据采集,恰好是 L9–L12 探索(exploration)主题在「模型视角」下的重述。

15.2.6 射击法与直接配点法(讲义第 20–23 页)

严格定义:讲义第 20 页标题为「Shooting vs Direct Collocation for Planning」。标题推断(该页正文与公式在图中、未进入文本层)的标准内容如下:

\[\text{射击法:}\quad \max_{a_{0:H-1}}\; \sum_{t=0}^{H-1}\gamma^t R\big(x_t,a_t\big)\quad \text{s.t.}\quad x_{t+1}=f(x_t,a_t),\;\; x_0\ \text{给定},\]

即只把动作序列当作决策变量,状态由动力学前向展开得到(每一步都精确满足动力学,因此仿真是逐步进行的)。而直接配点法(direct collocation)把状态也当作决策变量,动力学约束松弛为罚项:

\[\max_{\{x_t,a_t\}}\; \sum_{t=0}^{H-1}\Big[\gamma^t R(x_t,a_t)-\lambda\big\|x_{t+1}-f(x_t,a_t)\big\|^2\Big].\]

直观解释:射击法是「只能往前推」,一旦某一步走错就全盘皆错(对应本讲反复强调的复合误差);直接配点法是「先假装物理可以被违反,把任务解出来,再把物理修回去」。讲义第 21 页把这一思想命名为接触不变优化(Contact Invariant Optimization, CIO)[Mordatch et al. 2012, SIGGRAPH],原文两句话是:「Constrained optimization wrt dynamics constraints := relaxing (hacking) dynamics during planning」、「First solve task, then fix physics」。

具体示例(讲义第 22 页原文):CIO 的优点是「Direct collocation solves contact-rich tasks with minimal reward shaping, i.e. dynamics relaxation provides appropriate ‘reward shaping’」——即动力学松弛本身就起到了奖励塑形的作用。讲义还给出一个精彩类比:「Analogy: autoregressive video diffusion vs bidirectional video diffusion」——射击法像自回归(逐帧向前)视频扩散,直接配点法像双向(可回看全局)视频扩散。

与纯 model-free RL 的对比:射击法就是「用学到的世界模型做 H 步 roll-out + 搜索」,与 L13–L14 的 MCTS 同族(MCTS 是带采样的自适应射击法);直接配点法则更接近 L2 的有模型规划(在已知模型上做全局轨迹优化),而不是逐步自举。讲义第 23 页从反面补充了一个教训:Dexterity with shooting method is hard,并引用 Kamyar Ghasemipour, Byron David, Daniel Freeman, Shixiang Shane Gu, Satoshi Kataoka, Igor Mordatch, “Learning to Assemble with Large-Scale Structured Reinforcement Learning” (2022) 作为证据——精细装配任务上射击法难以奏效。

15.2.7 值函数与决策 Transformer 都是隐式世界模型(讲义第 24–28 页)

严格定义(时序差分模型,Temporal Difference Models, TDM, Pong et al. 2018, ICLR):讲义第 25 页原文三点:①「Goal-conditioned optimal policy or Q-function as an implicit world model (temporally-extended)」;②「Use hindsight relabeling trick」;③「Value functions are world models with different time scale and representation」。形式化地,TDM 学习

\[Q^\pi(s,a,g,n)\;\approx\;\mathbb{E}\Big[\sum_{t'=t}^{t+n-1}\gamma^{t'-t}r_{t'}+\gamma^{n}\,\mathbb{1}[s_{t+n}\approx g]\Big],\]

即「在 $n$ 步内到达目标 $g$ 的折扣最优值」。它之所以是世界模型,是因为 $Q(s,a,g,n)$ 隐含回答了「从 $s$ 出发、做 $a$、($n$ 步内)会到达 $g$ 吗」这一前向预测问题——只是时间尺度是时间扩展的(temporally-extended),表示是值的而非概率的。

直观解释:与其显式学 $\hat P$ 再搜索,不如直接学「什么动作能把我带到哪」。hindsight relabeling(事后重标记)是指:把实际到达的状态 $s_{t+n}$ 当作目标 $g$ 回填标签——「我事实上做到了,所以这条轨迹在『以 $s_{t+n}$ 为目标』的任务上是成功的」。

具体示例:在 GridWorld 中,$Q(s=(0,0),a=\text{右},g=(0,1),n=1)=0.95\,?$ 由折扣定义精确计算约为 $-0.04+0.95\times1=0.91$(若一步到达目标)。TDM 的 $n$ 越大,模型越「粗糙但越远视」。

广义决策 Transformer(Generalized Decision Transformer, GDT, Furuta, Matsuo, Gu, ICLR 2022 Spotlight):讲义第 27 页原文两点——训练:hindsight BC(behavioral cloning)wrt “any future statistics”;测试:provide unseen “future” and ask it for “generalization”。第 26、28 页则给出两个组合:Direct Collocation with TDMs(「Hierarchical RL with goal-conditioned Q-function + direct collocation」)与 Direct Collocation with GDTs (untested)(「Search for a ‘reachable future’ using the policy function」)。注意讲者自己标注了 (untested),这是一个尚未验证的研究设想。

与监督学习的对比:GDT 的训练其实就是一个条件序列建模问题(对着「未来的任意统计量」做行为克隆),与 L8 的模仿学习同源;只不过条件不是当前状态而是未来信息,测试时给一个没见过的未来条件,要求模型泛化——这与 LLM 的 in-context 泛化在形式上一致。

15.2.8 物理世界模型与符号世界模型(讲义第 29–35 页)

讲义原文按页转述

  • 第 30 页「2022: AGI Year 0」:两条并行判断——「LLMs can reason」→ 符号 AGI 可通过 LLM 实现;「ImagenVideo / DreamFusion」→ 物理 AGI 可通过视频模型实现。
  • 第 31 页「2025: Video model as the missing foundation model」:世界由符号、空间、时间组成;LLM 在符号中推理,视频模型在空间与时间中推理;并提出链式帧(Chain-of-Frames, CoF)vs 思维链(Chain-of-Thoughts, CoT)
  • 第 33 页「Older work: [Sanchez-Gonzalez et al. 2020]」:Particle-based simulation = message passing on graphs(粒子式仿真等价于图上的消息传递);讲者的判断是「We unlikely won’t need graph nets / NeRF etc. Just video models.」(原文即为这句双重否定,语义上是「我们很可能不再需要图网络/NeRF,只需要视频模型」),并抛出「AlphaFold?」作为反问。
  • 第 34 页「2026+: Modeling humanity」,附注「Simile: model 8B people」;第 35 页「2026+: Modeling financial market」。这两页只有标题与一行附注、没有任何展开论证,本笔记不作超出原文的推断。

「标题推断」的标准技术内容(讲义未展开,仅为帮助理解):所谓「视频模型作为世界模型」,标准做法是把视频帧序列当作可交互序列来建模,条件于动作或潜在动作。这一路线的代表作是 Ha & Schmidhuber, “World Models” (2018)(用 VAE 学视觉编码、RNN 学隐空间动力学、小控制器在隐空间里演化)、Genie: Generative Interactive Environments (2024)(从无动作标注的视频里学一个动作可控的生成式环境)、以及 Google DeepMind 的 Dreamer 系列(Hafner et al., “Dream to Control: Learning Behaviors by Latent Imagination”, ICLR 2020;后续 DreamerV2/V3)与 MuZero(Schrittwieser et al., “Mastering Atari, Go, chess and shogi by planning with a learned model”, Nature 2020)。请特别注意:这些论文并非讲义第 29–35 页所引,讲义明确说要「check out new models」但不在此讲展开,讲者也声明不讲 Gemini / Veo / Genie。把它们写在这里只是为了说明「标题推断」的标准技术背景,它们与讲义的直接关联仅在于同一主题。

隐空间世界模型的形式化(标题推断 + 标准内容):设观测 $o_t$、隐状态 $z_t$、确定性递归状态 $h_t$,则

\[\underbrace{h_t=f_\phi(h_{t-1},z_{t-1},a_{t-1})}_{\text{序列模型(deterministic)}},\qquad \underbrace{z_t\sim q_\phi(z_t\mid h_t,o_t)}_{\text{编码器(posterior)}},\qquad \underbrace{\hat z_{t+1}\sim p_\phi(z_{t+1}\mid h_t,z_t,a_t)}_{\text{隐空间动力学/先验}},\] \[\underbrace{\hat o_t\sim p_\theta(o_t\mid h_t,z_t)}_{\text{解码器(重构)}},\qquad \hat r_t=r_\psi(h_t,z_t),\qquad \hat \gamma_t=\gamma_\chi(h_t,z_t).\]

在隐空间中做 RL/规划:这一点直接对应讲者的定义「世界模型就是 model-based RL 里的那个 model」。Dreamer 式做法是在想象(latent imagination)中展开隐轨迹 $\hat\tau=(\hat z_0,a_0,\hat r_0,\dots)$,在隐空间里训练 actor 与 critic,完全不接触真实环境。

与监督学习的对比:这是「表示学习 + 动力学学习 + 策略学习」的三合一。相较 §15.2.1 的表格 $\hat P$,隐空间模型不要求 $z_t$ 可解释(不需要 $z_t$ 等于 $s_t$),代价是模型误差不再可解释——你无法像在表格里那样画出 $\vert \hat P-P\vert $ 的热图。


为便于对照,下表汇总本讲的核心概念、讲义出处与本笔记的处理方式:

概念讲义出处数学对象本笔记处理
世界模型 = model-based RL 的 model第 5 页(原文)$\hat P(s^{\prime}\vert s,a),\ \hat R(s,a)$忠实原文
Solomonoff 归纳 / 预测即理解第 11–12 页(原文)程序空间上的贝叶斯后验忠实原文 + 形式化
因果性与 OOD 泛化(IRM、干预多样性)第 13 页(原文)干预分布下的不变性忠实原文
预测三层次 + 赋能第 14–17 页(原文)$\max_\pi I(z;s^{\prime})$忠实原文 + 形式化
前向/逆向模型第 19 页(仅标题+符号)$f_\phi(s,a),\ g_\psi(s,s^{\prime})$标题推断
射击法 vs 直接配点法第 20 页(仅标题)轨迹优化 / 松弛约束标题推断 + 讲义第 21–22 页 CIO 原文
TDM 作为隐式世界模型第 25–26 页(原文)$Q(s,a,g,n)$ + hindsight relabeling忠实原文 + 形式化
GDT(hindsight BC wrt 未来统计量)第 27–28 页(原文)条件序列建模忠实原文
视频模型作为世界模型第 30–33 页(原文观点)像素/隐空间序列生成忠实原文 + 明确标注的标题推断补充
隐空间世界模型 / Dreamer 风格讲义未展开$q_\phi,p_\phi,p_\theta,r_\psi,\gamma_\chi$标题推断 + 标准内容(§15.3 推导)

15.3 算法伪代码与完整推导

本节的推导对象是「隐空间世界模型 + 想象中训练策略」这一标准范式(讲义未给公式,故按 §15.2.8 的「标题推断」处理;讲义第 5 页的定义与第 8 页的 outline 是其动机来源)。

15.3.1 隐空间世界模型的学习目标:ELBO + 奖励 + 折扣

第一步:从对数似然到 ELBO。 我们要最大化观测序列的边际似然 $\ln p(o_{1:T})$。引入编码器 $q_\phi(z_{1:T}\mid o_{1:T})$ 作为变分后验,由 Jensen 不等式:

\[\ln p(o_{1:T})\;\ge\;\mathbb{E}_{q_\phi(z_{1:T}\mid o_{1:T})}\Big[\ln \frac{p_\phi(z_{1:T},o_{1:T})}{q_\phi(z_{1:T}\mid o_{1:T})}\Big]\;=\;\mathcal{L}_{\text{ELBO}}.\]

按隐空间世界模型的因子分解 $p(z_t\mid h_t)$(先验)、$q_\phi(z_t\mid h_t,o_t)$(后验)、$p_\theta(o_t\mid h_t,z_t)$(解码器),逐项分解得到

\[\mathcal{L}_{\text{ELBO}}=\mathbb{E}_{q}\Big[\sum_{t=1}^{T}\underbrace{\ln p_\theta(o_t\mid h_t,z_t)}_{\text{重构项}}\;-\;\underbrace{\mathrm{KL}\big(q_\phi(z_t\mid h_t,o_t)\,\big\|\,p_\phi(z_t\mid h_t)\big)}_{\text{KL 正则项}}\Big].\]

$\mathrm{KL}$ 项的梯度可用重参数化技巧(reparameterization trick)估计:

\[\nabla_\phi\,\mathbb{E}_{q_\phi}[f(z)]=\mathbb{E}_{\epsilon\sim\mathcal{N}(0,I)}\big[\nabla_\phi f\big(\mu_\phi+\sigma_\phi\odot\epsilon\big)\big].\]

第二步:加上奖励与折扣预测。 世界模型不只要重构观测,还要预测奖励与终止。把两者作为额外的似然项(用 stop-gradient 阻断其梯度回流到表示学习):

\[\mathcal{L}_{\text{WM}}(\phi,\theta,\psi,\chi)=\mathbb{E}_{q}\Big[\sum_{t}\underbrace{-\ln p_\theta(o_t\mid h_t,z_t)}_{\text{重构}}+\beta\underbrace{\mathrm{KL}\big(q_\phi(z_t\mid h_t,o_t)\|p_\phi(z_t\mid h_t)\big)}_{\text{KL 正则}}\underbrace{-\ln p_\psi(r_t\mid h_t,z_t)}_{\text{奖励预测}}\underbrace{-\ln p_\chi(\gamma_t\mid h_t,z_t)}_{\text{折扣/终止预测}}\Big].\]

这就是「Dreamer 风格损失」的完整形式:重构 + KL 正则 + 奖励预测 + 折扣预测。$\beta$ 控制「表示学习要多靠近先验」——$\beta$ 越大越接近纯自回归先验模型,$\beta$ 越小越依赖重构像素。

15.3.2 在想象轨迹上做策略梯度:完整推导

第一步:策略梯度定理。 对任何 MDP,目标 $J(\theta)=\mathbb{E}{s_0\sim\rho}[V^{\pi\theta}(s_0)]$ 的梯度为

\[\nabla_\theta J(\theta)=\mathbb{E}_{s\sim d^{\pi_\theta}}\mathbb{E}_{a\sim\pi_\theta(\cdot\mid s)}\Big[\nabla_\theta\ln \pi_\theta(a\mid s)\;Q^{\pi_\theta}(s,a)\Big].\]

第二步:把采样分布从真实环境换成世界模型。 这是本讲的核心操作。真实环境里 $s\sim d^{\pi}$ 由 $P$ 生成;在 model-based RL 里我们用一个学到的分布 $\hat d^{\pi}$ 由 $\hat P$ 生成。于是估计量变成

\[\nabla_\theta J(\theta)\;\approx\;\mathbb{E}_{\hat\tau\sim \text{world model}}\Big[\sum_{t=0}^{H-1}\nabla_\theta\ln\pi_\theta(a_t\mid \hat s_t)\;\hat A_t\Big],\qquad \hat\tau=(\hat s_0,a_0,\hat r_0,\hat s_1,\dots,\hat s_H).\]

第三步:为什么它仍然是「对 $\theta$ 的无偏梯度」? 关键在于世界模型的参数不参与对 $\theta$ 的求导。只要 $\hat P$ 固定,$\hat s_t$ 与 $\theta$ 无关(它由 $\hat P$ 与过去的动作采样而来),因此对 $\log$ 项求导时不需要穿过环境,REINFORCE 型估计量在模型内部依然成立:

\[\nabla_\theta\,\mathbb{E}_{\hat\tau}\big[\hat G_0\big]=\mathbb{E}_{\hat\tau}\Big[\sum_{t}\nabla_\theta\ln\pi_\theta(a_t\mid\hat s_t)\,\big(\hat G_t-\hat b(\hat s_t)\big)\Big].\]

但要注意:这个无偏性只在相对于模型的意义上成立。对真实目标 $J(\theta)$ 而言,$\hat P\neq P$ 引入了不可避免的偏差,即 §15.5 的模型偏差(model bias)

第四步:复合误差的形式。 设每步的「模型误差」为 $\epsilon_1=\max_{s}\vert \hat P(\cdot\vert s,a)-P(\cdot\vert s,a)\vert {TV}$(对策略访问到的状态取最大)。对两条分布递推 $d{t+1}=d_t K$、$\hat d_{t+1}=\hat d_t\hat K$($K(s,s^{\prime})=\sum_a\pi(a\vert s)P(s^{\prime}\vert s,a)$),用 TV 距离的三件套(三角不等式 + 数据处理的压缩性 + 最大行差):

\[\|d_{t+1}-\hat d_{t+1}\|_{TV}\;\le\;\underbrace{\|d_tK-\hat d_tK\|_{TV}}_{\le\,\|d_t-\hat d_t\|_{TV}}\;+\;\underbrace{\|\hat d_t(K-\hat K)\|_{TV}}_{\le\,\epsilon_1}\;\le\;\|d_t-\hat d_t\|_{TV}+\epsilon_1 .\]

对 $t$ 求和即得 H 步复合误差界

\[\boxed{\;\|d_H-\hat d_H\|_{TV}\;\le\;\min\big(1,\;H\,\epsilon_1\big)\;}\]

(上界 $1$ 来自 TV 距离本身的取值域 $[0,1]$。)§15.4 的实测(表格模型初段 log-log 斜率 $1.011$)与这一线性界吻合。

15.3.3 伪代码:世界模型 + 想象中训练

算法 15.1  Latent World Model + Imagination Training (Dreamer 式范式; 讲义未给公式, 按 §15.2.8 标准内容撰写)
------------------------------------------------------------------------------------------
输入: 真实环境交互预算 N_real, 想象回合数 K, 想象视界 H, 学习率 α_φ, α_θ, 折扣 γ
输出: 世界模型参数 φ, 策略参数 θ, 价值参数 w

 1  初始化: Replay buffer D ← ∅ ; 世界模型 (φ,θ_dec) ; actor π_θ ; critic V_w
 2  # ---------- 阶段 A: 收集真实数据, 训练世界模型 ----------
 3  while |D| < N_real do
 4      用 π_θ 在真实环境中采样轨迹 τ, 把 (o_t, a_t, r_t, γ_t) 写入 D
 5  end while
 6  repeat
 7      从 D 采样一批序列, 由编码器算 q_φ(z_t | h_t, o_t)
 8      按下式做一步梯度下降:
 9          L_WM = E_q[ Σ_t -ln p_θ(o_t|h_t,z_t) + β·KL(q_φ(z_t|h_t,o_t) || p_φ(z_t|h_t))
10                       - ln p_ψ(r_t|h_t,z_t) - ln p_χ(γ_t|h_t,z_t) ]
11  until 世界模型收敛
12  # ---------- 阶段 B: 完全在想象中训练 actor / critic ----------
13  for k = 1 to K do
14      取 D 中一个状态 s 作为想象起点, 令 ĥ_0, ẑ_0 = encoder(s)
15      for t = 0 to H-1 do
16          a_t ~ π_θ(· | ĥ_t, ẑ_t)                      # actor 采样 (重参数化或 REINFORCE)
17          ẑ_{t+1} ~ p_φ(· | ĥ_t, ẑ_t, a_t)             # 世界模型前向一步 (不碰真实环境)
18          r̂_t = r_ψ(ĥ_t, ẑ_t) ;  γ̂_t = γ_χ(ĥ_t, ẑ_t)
19      end for
20      从后往前算 λ-回报:  Ĝ_t = r̂_t + γ̂_t·[(1-λ)V_w(ĥ_{t+1},ẑ_{t+1}) + λ·Ĝ_{t+1}]
21      更新 critic:      w ← w - α_w · ∇_w Σ_t ½‖V_w(ĥ_t,ẑ_t) - sg(Ĝ_t)‖²
22      更新 actor:       θ ← θ + α_θ · ∇_θ Σ_t [ Ĝ_t·ln π_θ(a_t|ĥ_t,ẑ_t) + η·H(π_θ(·|ĥ_t,ẑ_t)) ]
23  end for
24  # ---------- 阶段 C: 回到真实环境 ----------
25  用更新后的 π_θ 在真实环境评估; 若性能未达停止条件, 回到第 3 行继续收集
26  return φ, θ, w
------------------------------------------------------------------------------------------
终止条件: 达到真实交互预算 N_real 或真实环境回报的平台期
复杂度:   每步想象 O(dim(z)²) (隐空间前向), 不含真实环境交互;
          每轮真实数据收集 O(N_real) 步环境交互 (这是唯一的"真实代价")

算法逻辑解说:三个阶段对应讲义的三个层次——阶段 A 是 Level 1(被动拟合世界),阶段 B 是「在模型里做 RL」(模型固定时的 Level 1 复用),阶段 C 把新策略送回真实环境产生新数据、再回来更新模型,这一步才构成 Level 2(主动拟合世界,数据分布非平稳)。

数学推导与理论对应:第 9–10 行的损失就是 §15.3.1 的 $\mathcal{L}_{\text{WM}}$;第 13–23 行是 §15.3.2 的想象策略梯度;第 20 行的 $\lambda$-回报在 $\lambda=0$ 时退化为单步 TD(对应 L3/L4 的 TD 学习),$\lambda=1$ 时退化为蒙特卡洛(对应 L3 的 MC)。因此这个伪代码把 L3–L6 的所有值估计工具原封不动搬进了隐空间。

15.3.4 一个可手算的对照:想象梯度 vs 真实梯度

在 §15.4 的 GridWorld 中,取表格 softmax 策略 $\pi_\theta(a\vert s)\propto e^{\theta_{s,a}}$,则

\[\nabla_{\theta_{s,\cdot}}\ln\pi_\theta(a\|s)=\mathbf{e}_a-\pi_\theta(\cdot\|s).\]

真实环境里的 REINFORCE 更新(L5 的标准形式)是

\[\theta_{s_t,\cdot}\;\leftarrow\;\theta_{s_t,\cdot}+\alpha\,\gamma^{t}\,G_t\,\big(\mathbf{e}_{a_t}-\pi_\theta(\cdot\|s_t)\big),\]

而「在想象中训练」用的更新式一模一样,唯一区别是 $(s_t,a_t,G_t)$ 全部由 $\hat P,\hat R$ 生成。这正是 §15.4 实验三要让代码说清楚的事:同样的更新式,换一个采样器

15.4 代码实现与实验分析

全部代码在 cs234/code/L15_world_model.py 中,纯 NumPy,不依赖 torch/gym/gymnasium/scipy,单次运行约 19 秒。环境自写为 5×5 随机 GridWorld($S=25$,$A=4$,$\text{slip}=0.1$,每步 $-0.04$,目标 $+1$,$\gamma=0.95$,上限 50 步)。下文的「实验观察」数值全部来自完整脚本 python3 L15_world_model.py 的真实输出(三个实验共享同一个随机数流,因此独立粘贴运行单个代码块时数值会有 $\pm0.05$ 量级的小幅浮动,结论方向不变)。

15.4.1 实验一:极小世界模型(表格 MLE vs 线性回归)

"""实验一:在 5x5 GridWorld 上用表格统计 / 线性回归学一个"极小世界模型"。"""
import numpy as np
np.random.seed(0)


class GridWorld:
    ACTIONS = [(-1, 0), (0, 1), (1, 0), (0, -1)]

    def __init__(self, n=5, slip=0.1, step_reward=-0.04,
                 goal_reward=1.0, gamma=0.95, max_steps=50):
        self.n, self.slip = n, slip
        self.step_reward, self.goal_reward = step_reward, goal_reward
        self.gamma, self.max_steps = gamma, max_steps
        self.start, self.goal = (0, 0), (n - 1, n - 1)
        self.S, self.A = n * n, 4
        self.s0, self.sg = self.idx(self.start), self.idx(self.goal)

    def idx(self, rc):
        return rc[0] * self.n + rc[1]

    def reset(self):
        self.rc, self.t = self.start, 0
        return self.s0

    def step(self, a):
        if np.random.rand() < self.slip:          # 打滑:执行随机动作
            a = np.random.randint(self.A)
        dr, dc = self.ACTIONS[a]
        self.rc = (min(max(self.rc[0] + dr, 0), self.n - 1),
                   min(max(self.rc[1] + dc, 0), self.n - 1))
        self.t += 1
        if self.rc == self.goal:
            return self.sg, self.goal_reward, True
        return self.idx(self.rc), self.step_reward, self.t >= self.max_steps

    def true_model(self):                          # 上帝视角,仅用于评估
        S, A, n, slip = self.S, self.A, self.n, self.slip
        P, R = np.zeros((S, A, S)), np.zeros((S, A))
        for s in range(S):
            rc = (s // n, s % n)
            for a in range(A):
                for a2 in range(A):
                    w = (1.0 - slip if a2 == a else 0.0) + slip / A
                    dr, dc = self.ACTIONS[a2]
                    nr = min(max(rc[0] + dr, 0), n - 1)
                    nc = min(max(rc[1] + dc, 0), n - 1)
                    ns = nr * n + nc
                    P[s, a, ns] += w
                    R[s, a] += w * (self.goal_reward if ns == self.sg else self.step_reward)
        P[self.sg, :, :] = 0.0
        P[self.sg, :, self.sg] = 1.0              # 终止态自环
        R[self.sg, :] = 0.0
        return P, R


def uniform_policy(S, A):
    return np.full((S, A), 1.0 / A)


def collect(env, n_samples, pi, seed=1):
    """在真实环境中按 pi 采样 n_samples 个 (s,a,s',r,done)。"""
    rng, S, A = np.random.RandomState(seed), env.S, env.A
    data = np.zeros((n_samples, 5), dtype=float)
    s = env.reset()
    for k in range(n_samples):
        a = rng.choice(A, p=pi[s])
        ns, r, done = env.step(a)
        data[k] = (s, a, ns, r, float(done))
        s = env.reset() if done else ns
    return data


def fit_table_model(data, S, A, alpha=0.01, sg=None):
    """表格 MLE 世界模型:计数 + 拉普拉斯平滑;R_hat 为样本均值。"""
    cnt, rsum, rcnt = np.zeros((S, A, S)), np.zeros((S, A)), np.zeros((S, A))
    for s, a, ns, r, _ in data:                    # 注意 r 是浮点,不能整型化
        s, a, ns = int(s), int(a), int(ns)
        cnt[s, a, ns] += 1
        rsum[s, a] += r
        rcnt[s, a] += 1
    P = cnt + alpha
    P /= P.sum(axis=2, keepdims=True)
    R = np.where(rcnt > 0, rsum / np.maximum(rcnt, 1), 0.0)
    if sg is not None:
        P[sg, :, :] = 0.0
        P[sg, :, sg] = 1.0
        R[sg, :] = 0.0
    return P, R, cnt.sum(axis=2)                   # N(s,a) 访问计数


def fit_linear_model(data, S, A, ridge=1e-2):
    """线性回归世界模型:one-hot(s,a) 特征 -> 最小二乘拟合 next-state one-hot。"""
    d = S + A
    X, Y = np.zeros((len(data), d)), np.zeros((len(data), S))
    for k, (s, a, ns, r, _) in enumerate(data):
        s, a, ns = int(s), int(a), int(ns)
        X[k, s] = 1.0
        X[k, S + a] = 1.0
        Y[k, ns] = 1.0
    W = np.linalg.solve(X.T @ X + ridge * np.eye(d), X.T @ Y)
    Ptab = np.zeros((S, A, S))
    for s in range(S):
        for a in range(A):
            x = np.zeros(d)
            x[s], x[S + a] = 1.0, 1.0
            v = np.clip(x @ W, 1e-6, None)
            Ptab[s, a] = v / v.sum()
    return Ptab, W


def eval_next_state_accuracy(P, data):
    """留出集上的一步预测:平均对数似然 + argmax 命中率。"""
    ll, hit = [], []
    for s, a, ns, r, _ in data:
        s, a, ns = int(s), int(a), int(ns)
        ll.append(np.log(max(P[s, a][ns], 1e-12)))
        hit.append(int(np.argmax(P[s, a]) == ns))
    return float(np.mean(ll)), float(np.mean(hit))


if __name__ == "__main__":
    env = GridWorld()
    Ptrue, Rtrue = env.true_model()
    pi_rand = uniform_policy(env.S, env.A)
    train = collect(env, 3000, pi_rand, seed=1)
    hold = collect(env, 800, pi_rand, seed=99)
    Pt, Rt, N = fit_table_model(train, env.S, env.A, sg=env.sg)
    Pl, _ = fit_linear_model(train, env.S, env.A)
    print("访问过的 (s,a) 对 = %d / %d" % (int((N > 0).sum()), env.S * env.A))
    for name, P in [("表格 MLE", Pt), ("线性回归", Pl)]:
        ll, hit = eval_next_state_accuracy(P, hold)
        print("  %-10s : log-lik = %+.4f, 命中率 = %.4f" % (name, ll, hit))
    print("  R_hat 平均绝对误差 = %.5f" % np.abs(Rt - Rtrue)[N > 0].mean())

代码做什么collect 用均匀随机策略在真实 GridWorld 上采 3000 条转移;fit_table_model 用「计数 + 拉普拉斯平滑 $\alpha=0.01$」估计 $\hat P(s^{\prime}\vert s,a)$,用样本均值估计 $\hat R(s,a)$;fit_linear_model 改用 one-hot 特征 $(s,a)$ 做岭回归($\lambda=10^{-2}$),再归一化成概率;最后在独立的 800 条留出转移上比较两步预测的 log-likelihood 与 top-1 命中率。

RL 机制透视:这就是讲义第 5 页「世界模型就是 model-based RL 里的 model」的最小可运行实例。表格 MLE 的样本复杂度是「每个 $(s,a)$ 需要足够多的 $s^{\prime}$ 样本」——它的误差来源只有估计误差($\hat P\neq P$ 纯粹因为采样噪声)。线性回归则额外引入逼近误差:因为真实动力学是分段线性的(撞墙截断),one-hot 线性假设类根本装不下它。这一「估计误差 vs 逼近误差」的二分,正是 L4 讲函数逼近时同一套语言。注意代码里 data[k] = (s, a, ns, r, float(done))for s, a, ns, r, _ in data——奖励是 $-0.04$ 的浮点数,任何 data.astype(int) 都会把它变成 $0$,这是本笔记开发过程中真实踩到的坑(fit_table_model 的注释即为提示)。

实验观察(真实运行输出)

[实验一] 极小世界模型:3000 条随机策略真实转移,5x5 GridWorld
  覆盖情况: 访问过的 (s,a) 对 = 96 / 100 ;这些对上的样本数 平均 31.2,最少 8,最多 94
  表格 MLE 世界模型      : 留出集一步 log-likelihood = -0.4894, next-state 命中率 = 0.9225
  线性回归世界模型         : 留出集一步 log-likelihood = -1.4418, next-state 命中率 = 0.4863
  奖励模型 R_hat(s,a) 对真实 R(s,a) 的平均绝对误差 = 0.00443
  分桶(按 N(s,a))一步 top-1 命中率:
    N ∈ [  6,  20] : (s,a) 对数  28, 命中率 = 0.8721
    N ∈ [ 21,  60] : (s,a) 对数  64, 命中率 = 0.9288
    N ∈ [ 61,   ∞] : (s,a) 对数   4, 命中率 = 0.9273

三点读数:①3000 条转移只覆盖了 96/100 个 $(s,a)$ 对——因为打滑让状态 $24$(目标)成为吸收态、且均匀策略下各状态访问不均,这正是 15.2.3 「干预多样性」问题的缩影;②表格 MLE 命中率 $0.9225$,与理论预期一致($\text{slip}=0.1$ 时有 $10\%$ 概率走随机方向,$1-0.1+0.1/4\approx0.925$ 的下一状态众数命中率);③线性回归命中率只有 $0.4863$,log-likelihood 从 $-0.4894$ 掉到 $-1.4418$,逼近误差远大于估计误差——同样的 3000 条数据,模型类选错就损失一半精度。

15.4.2 实验二:roll-out 复合误差随 $H$ 的累积

# ============================================================================
# 【共享工具】以下 4 个定义与「实验一」中的完全一致,为保证本代码块**可独立运行**
# 而在此重复。若你已按顺序读过实验一,可直接跳过本段。
# ============================================================================
import numpy as np

class GridWorld:
    ACTIONS = [(-1, 0), (0, 1), (1, 0), (0, -1)]

    def __init__(self, n=5, slip=0.1, step_reward=-0.04,
                 goal_reward=1.0, gamma=0.95, max_steps=50):
        self.n, self.slip = n, slip
        self.step_reward, self.goal_reward = step_reward, goal_reward
        self.gamma, self.max_steps = gamma, max_steps
        self.start, self.goal = (0, 0), (n - 1, n - 1)
        self.S, self.A = n * n, 4
        self.s0, self.sg = self.idx(self.start), self.idx(self.goal)

    def idx(self, rc):
        return rc[0] * self.n + rc[1]

    def reset(self):
        self.rc, self.t = self.start, 0
        return self.s0

    def step(self, a):
        if np.random.rand() < self.slip:          # 打滑:执行随机动作
            a = np.random.randint(self.A)
        dr, dc = self.ACTIONS[a]
        self.rc = (min(max(self.rc[0] + dr, 0), self.n - 1),
                   min(max(self.rc[1] + dc, 0), self.n - 1))
        self.t += 1
        if self.rc == self.goal:
            return self.sg, self.goal_reward, True
        return self.idx(self.rc), self.step_reward, self.t >= self.max_steps

    def true_model(self):                          # 上帝视角,仅用于评估
        S, A, n, slip = self.S, self.A, self.n, self.slip
        P, R = np.zeros((S, A, S)), np.zeros((S, A))
        for s in range(S):
            rc = (s // n, s % n)
            for a in range(A):
                for a2 in range(A):
                    w = (1.0 - slip if a2 == a else 0.0) + slip / A
                    dr, dc = self.ACTIONS[a2]
                    nr = min(max(rc[0] + dr, 0), n - 1)
                    nc = min(max(rc[1] + dc, 0), n - 1)
                    ns = nr * n + nc
                    P[s, a, ns] += w
                    R[s, a] += w * (self.goal_reward if ns == self.sg else self.step_reward)
        P[self.sg, :, :] = 0.0
        P[self.sg, :, self.sg] = 1.0              # 终止态自环
        R[self.sg, :] = 0.0
        return P, R

def uniform_policy(S, A):
    return np.full((S, A), 1.0 / A)

def collect(env, n_samples, pi, seed=1):
    """在真实环境中按 pi 采样 n_samples 个 (s,a,s',r,done)。"""
    rng, S, A = np.random.RandomState(seed), env.S, env.A
    data = np.zeros((n_samples, 5), dtype=float)
    s = env.reset()
    for k in range(n_samples):
        a = rng.choice(A, p=pi[s])
        ns, r, done = env.step(a)
        data[k] = (s, a, ns, r, float(done))
        s = env.reset() if done else ns
    return data

def fit_table_model(data, S, A, alpha=0.01, sg=None):
    """表格 MLE 世界模型:计数 + 拉普拉斯平滑;R_hat 为样本均值。"""
    cnt, rsum, rcnt = np.zeros((S, A, S)), np.zeros((S, A)), np.zeros((S, A))
    for s, a, ns, r, _ in data:                    # 注意 r 是浮点,不能整型化
        s, a, ns = int(s), int(a), int(ns)
        cnt[s, a, ns] += 1
        rsum[s, a] += r
        rcnt[s, a] += 1
    P = cnt + alpha
    P /= P.sum(axis=2, keepdims=True)
    R = np.where(rcnt > 0, rsum / np.maximum(rcnt, 1), 0.0)
    if sg is not None:
        P[sg, :, :] = 0.0
        P[sg, :, sg] = 1.0
        R[sg, :] = 0.0
    return P, R, cnt.sum(axis=2)                   # N(s,a) 访问计数

# ============================================================================
# 【本实验代码】
# ============================================================================
"""实验二:复合模型误差。(2a) 表格模型 H 步截断值误差与状态分布 TV;
                (2b) 连续线性动力学,误差严格线性累积。"""


def policy_value(P, R, pi, gamma, iters=800):
    """精确策略评估 V^pi = sum_a pi(a|s)[R + gamma P V]。"""
    V = np.zeros(P.shape[0])
    for _ in range(iters):
        V = (pi * (R + gamma * P @ V)).sum(axis=1)
        V[-1] = 0.0
    return V


def optimal_value(P, R, gamma, iters=1500):
    """值迭代求最优值 V*。"""
    V = np.zeros(P.shape[0])
    for _ in range(iters):
        V = (R + gamma * P @ V).max(axis=1)
        V[-1] = 0.0
    return V


def truncated_value(P, R, pi, gamma, H):
    """H 步截断策略评估:从 V_0=0 迭代 H 次 => 恰好是 H 步 roll-out 的值。"""
    V = np.zeros(P.shape[0])
    for _ in range(H):
        V = (pi * (R + gamma * P @ V)).sum(axis=1)
        V[-1] = 0.0
    return V


def state_distribution(P, start, pi, H, S):
    """从 start 按 pi 走 H 步后的状态边际分布。"""
    d = np.zeros(S)
    d[start] = 1.0
    for _ in range(H):
        d = np.einsum("s,sa,sat->t", d, pi, P)     # d'_{s'} = Σ_s d_s Σ_a π(a|s) P(s'|s,a)
    return d


def tv(p, q):
    return 0.5 * float(np.abs(p - q).sum())


if __name__ == "__main__":
    env = GridWorld()                              # 环境与 fit_table_model/collect 见实验一
    Ptrue, Rtrue = env.true_model()
    S, A = env.S, env.A
    pi_rand = uniform_policy(S, A)
    Vstar = optimal_value(Ptrue, Rtrue, env.gamma)
    Qstar = Rtrue + env.gamma * Ptrue @ Vstar
    pi_det = np.zeros((S, A))                      # 确定性最优贪心策略
    pi_det[np.arange(S), Qstar.argmax(axis=1)] = 1.0

    print("  %5s | %14s | %14s | %10s | %10s"
          % ("H", "mean|dV(s0)|", "mean|dV|(全状态)", "TV(分布)", "L1(分布)"))
    for n_real in [300, 3000]:
        for H in [1, 2, 5, 10, 20, 50]:
            dv0, dv, tvs, l1s = [], [], [], []
            for sd in range(8):                    # 8 个独立数据种子
                d = collect(env, n_real, pi_rand, seed=100 + sd)
                Pm, Rm, _ = fit_table_model(d, S, A, sg=env.sg)
                a = truncated_value(Ptrue, Rtrue, pi_det, env.gamma, H)
                b = truncated_value(Pm, Rm, pi_det, env.gamma, H)
                dv0.append(abs(a[env.s0] - b[env.s0]))
                dv.append(np.abs(a - b).mean())
                dt = state_distribution(Ptrue, env.s0, pi_det, H, S)
                dl = state_distribution(Pm, env.s0, pi_det, H, S)
                tvs.append(tv(dt, dl))
                l1s.append(float(np.abs(dt - dl).sum()))
            print("  n=%d H=%2d : |dV(s0)|=%.5f mean|dV|=%.5f TV=%.5f L1=%.5f"
                  % (n_real, H, np.mean(dv0), np.mean(dv), np.mean(tvs), np.mean(l1s)))

    # ---- (2b) 连续状态:double integrator,误差严格线性累积 ----
    dt_ = 0.1
    Atrue = np.array([[1.0, dt_], [0.0, 1.0]])
    Btrue = np.array([0.0, dt_])
    rng = np.random.RandomState(0)
    X, Y, x = [], [], np.array([0.0, 0.0])
    for _ in range(400):
        a = rng.uniform(-1, 1)
        xn = Atrue @ x + Btrue * a + 0.005 * rng.randn(2)      # 带观测噪声
        X.append(np.concatenate([x, [a]])); Y.append(xn); x = xn
    X, Y = np.array(X), np.array(Y)
    W = np.linalg.solve(X.T @ X + 1e-6 * np.eye(3), X.T @ Y)   # 线性世界模型
    Ahat, Bhat = W[:2].T, W[2]

    def rollout(x0, acts, A, B):
        xs, x = [x0.copy()], x0.copy()
        for a in acts:
            x = A @ x + B * a
            xs.append(x.copy())
        return np.array(xs)

    acts, x0 = [0.5] * 20, np.array([0.0, 0.0])
    tr, ha = rollout(x0, acts, Atrue, Btrue), rollout(x0, acts, Ahat, Bhat)
    e1 = float(np.linalg.norm(tr[1] - ha[1]))
    for H in [1, 2, 5, 10, 20]:
        e = float(np.linalg.norm(tr[H] - ha[H]))
        print("  H=%2d  ||s_H - s_hat_H|| = %.6f   (e/e1 = %.2f)" % (H, e, e / e1))

代码做什么:(2a) 用 8 个独立数据种子,分别以 300 与 3000 条真实转移拟合表格世界模型,然后计算 $H$ 步截断策略评估(从 $V_0=0$ 迭代 $H$ 次,等价于恰好展开 $H$ 步 roll-out)在真实模型与学到的模型之间的差,同时用 state_distribution 比较两条 $H$ 步状态边际分布的全变差(TV)与 L1 距离。(2b) 换成连续状态的小车(double integrator),用 400 条带噪转移做线性最小二乘,然后比较两条 20 步开环轨迹。

RL 机制透视truncated_value 是本实验的关键设计——它把「$H$ 步想象」与「无限步评估」严格区分开。若用 policy_value(迭代到收敛),$H$ 再大结果都一样,就看不到复合误差了。TV 距离用 einsum("s,sa,sat->t", ...) 计算 $d^{\prime}_{s^{\prime}}=\sum_s d_s\sum_a\pi(a\vert s)P(s^{\prime}\vert s,a)$,这是把「策略 + 转移核」合成一个状态转移矩阵 $K$ 的标准做法。所有评估用的都是上帝视角的真实模型,所以测出来的纯粹是模型误差,不含任何评估偏差。

实验观察(完整脚本的真实输出节选)

[实验二] 复合模型误差:imagined roll-out 的 H 步误差
  (2a) 表格世界模型 + 确定性最优贪心策略,8 个独立数据种子取平均
      H |   mean|ΔV(s0)| |  mean|ΔV|(全状态) |     TV(分布) |     L1(分布)
      1 |        0.00000 |        0.00527 |    0.02541 |    0.05082      (n=3000)
      2 |        0.00022 |        0.01438 |    0.06345 |    0.12690      (n=3000)
      5 |        0.00387 |        0.02759 |    0.10438 |    0.20876      (n=3000)
     10 |        0.02061 |        0.01697 |    0.04124 |    0.08248      (n=3000)
     20 |        0.01420 |        0.01496 |    0.00052 |    0.00105      (n=3000)
     50 |        0.01330 |        0.01484 |    0.00000 |    0.00000      (n=3000)
      (对照 n=300):
      1 |        0.00000 |        0.03126 |    0.07087 |    0.14174      (n=300)
      2 |        0.00237 |        0.04793 |    0.17432 |    0.34864      (n=300)
      5 |        0.06738 |        0.28634 |    0.58758 |    1.17516      (n=300)
     10 |        0.18479 |        0.15366 |    0.33001 |    0.66001      (n=300)
     20 |        0.07673 |        0.11342 |    0.07264 |    0.14527      (n=300)
     50 |        0.12626 |        0.13655 |    0.02058 |    0.04116      (n=300)
  初段(H ≤ 5)log-log 斜率,理论上该段接近 1(线性累积):
    n=300  mean|ΔV|(全状态)      : 斜率 = 1.406
    n=300  TV(分布)             : 斜率 = 1.315
    n=3000 mean|ΔV|(全状态)      : 斜率 = 1.011
    n=3000 TV(分布)             : 斜率 = 0.860

  (2b) 连续状态:小车动力学 s_{t+1} = A s_t + B a_t(double integrator)
      真实 A = [[1.0, 0.1], [0.0, 1.0]], B = [0.0, 0.1]
      学到 A = [[0.9999, 0.1004], [-0.0001, 1.0003]], B = [0.0005, 0.0999]
      H |      ‖s_H - ŝ_H‖ |             位置误差 |        比值/ε₁
      1 |         0.000239 |         0.000237 |       1.0000
      2 |         0.000495 |         0.000493 |       2.0736
      5 |         0.001383 |         0.001383 |       5.7986
     10 |         0.003328 |         0.003313 |      13.9533
     20 |         0.009190 |         0.009035 |      38.5330
      log-log 斜率 = 1.2092(理论:误差 ≈ ε₁·H ⇒ 斜率 1;>1 因为 A 的谱半径略被高估)

四点评注:① $H\le 5$ 段两处都接近线性累积(n=3000 时斜率 $1.011$,n=300 时 $1.406$),与 §15.3.2 推出的 $\vert d_H-\hat d_H\vert _{TV}\le H\epsilon_1$ 一致;② 数据量从 3000 降到 300 时,$H=1$ 的 TV 从 $0.0254$ 涨到 $0.0709$(约 $2.8\times$),而 $H=5$ 的 TV 从 $0.104$ 涨到 $0.588$(约 $5.6\times$)——模型越差,复合误差放大得越快;③ 长 $H$ 段误差回落甚至归零,原因是 GridWorld 的打滑($\text{slip}=0.1$)让状态分布快速混合到平稳分布,两个模型在平稳分布上趋于一致,且 TV 天然被截断在 $[0,1]$。这提醒我们:复合误差界是最坏情况,环境的混合性(mixing)会缓解它;④ (2b) 的连续系统没有混合效应,误差严格线性累积:第 20 步误差是单步误差的 $38.5$ 倍,绝对值仍只有 $0.0092$(因为线性模型本身拟合得很好,$\hat A$ 与 $A$ 的差在 $10^{-4}$ 量级)——精度高的模型可以把复合误差推得很远,但斜率 $1$ 无法改变

15.4.3 实验三:在想象中训练策略 vs 直接在真实环境训练

# ============================================================================
# 【共享工具】以下 4 个定义与「实验一」中的完全一致,为保证本代码块**可独立运行**
# 而在此重复。若你已按顺序读过实验一,可直接跳过本段。
# ============================================================================
import numpy as np

class GridWorld:
    ACTIONS = [(-1, 0), (0, 1), (1, 0), (0, -1)]

    def __init__(self, n=5, slip=0.1, step_reward=-0.04,
                 goal_reward=1.0, gamma=0.95, max_steps=50):
        self.n, self.slip = n, slip
        self.step_reward, self.goal_reward = step_reward, goal_reward
        self.gamma, self.max_steps = gamma, max_steps
        self.start, self.goal = (0, 0), (n - 1, n - 1)
        self.S, self.A = n * n, 4
        self.s0, self.sg = self.idx(self.start), self.idx(self.goal)

    def idx(self, rc):
        return rc[0] * self.n + rc[1]

    def reset(self):
        self.rc, self.t = self.start, 0
        return self.s0

    def step(self, a):
        if np.random.rand() < self.slip:          # 打滑:执行随机动作
            a = np.random.randint(self.A)
        dr, dc = self.ACTIONS[a]
        self.rc = (min(max(self.rc[0] + dr, 0), self.n - 1),
                   min(max(self.rc[1] + dc, 0), self.n - 1))
        self.t += 1
        if self.rc == self.goal:
            return self.sg, self.goal_reward, True
        return self.idx(self.rc), self.step_reward, self.t >= self.max_steps

    def true_model(self):                          # 上帝视角,仅用于评估
        S, A, n, slip = self.S, self.A, self.n, self.slip
        P, R = np.zeros((S, A, S)), np.zeros((S, A))
        for s in range(S):
            rc = (s // n, s % n)
            for a in range(A):
                for a2 in range(A):
                    w = (1.0 - slip if a2 == a else 0.0) + slip / A
                    dr, dc = self.ACTIONS[a2]
                    nr = min(max(rc[0] + dr, 0), n - 1)
                    nc = min(max(rc[1] + dc, 0), n - 1)
                    ns = nr * n + nc
                    P[s, a, ns] += w
                    R[s, a] += w * (self.goal_reward if ns == self.sg else self.step_reward)
        P[self.sg, :, :] = 0.0
        P[self.sg, :, self.sg] = 1.0              # 终止态自环
        R[self.sg, :] = 0.0
        return P, R

def uniform_policy(S, A):
    return np.full((S, A), 1.0 / A)

def collect(env, n_samples, pi, seed=1):
    """在真实环境中按 pi 采样 n_samples 个 (s,a,s',r,done)。"""
    rng, S, A = np.random.RandomState(seed), env.S, env.A
    data = np.zeros((n_samples, 5), dtype=float)
    s = env.reset()
    for k in range(n_samples):
        a = rng.choice(A, p=pi[s])
        ns, r, done = env.step(a)
        data[k] = (s, a, ns, r, float(done))
        s = env.reset() if done else ns
    return data

def fit_table_model(data, S, A, alpha=0.01, sg=None):
    """表格 MLE 世界模型:计数 + 拉普拉斯平滑;R_hat 为样本均值。"""
    cnt, rsum, rcnt = np.zeros((S, A, S)), np.zeros((S, A)), np.zeros((S, A))
    for s, a, ns, r, _ in data:                    # 注意 r 是浮点,不能整型化
        s, a, ns = int(s), int(a), int(ns)
        cnt[s, a, ns] += 1
        rsum[s, a] += r
        rcnt[s, a] += 1
    P = cnt + alpha
    P /= P.sum(axis=2, keepdims=True)
    R = np.where(rcnt > 0, rsum / np.maximum(rcnt, 1), 0.0)
    if sg is not None:
        P[sg, :, :] = 0.0
        P[sg, :, sg] = 1.0
        R[sg, :] = 0.0
    return P, R, cnt.sum(axis=2)                   # N(s,a) 访问计数

# ============================================================================
# 【本实验代码】
# ============================================================================
"""实验三:相同 REINFORCE 更新式,采样器换成世界模型。"""
import numpy as np


def softmax(z):
    z = z - z.max(axis=-1, keepdims=True)
    e = np.exp(z)
    return e / e.sum(axis=-1, keepdims=True)


def score(theta, s, a):
    """∇_θ log π_θ(a|s) = e_a - π_θ(·|s)。"""
    p = softmax(theta[s])
    g = -p.copy()
    g[a] += 1.0
    return g


def reinforce_real(env, n_episodes, alpha=0.10, seed=0):
    """标准 REINFORCE(真实环境)。返回 (θ, 训练回报序列, 累计真实样本数)。"""
    rng, S, A = np.random.RandomState(seed), env.S, env.A
    theta, samples, hist = np.zeros((S, A)), 0, []
    for _ in range(n_episodes):
        s, Ss, As, Rs, done = env.reset(), [], [], [], False
        while not done:
            a = rng.choice(A, p=softmax(theta[s]))
            ns, r, done = env.step(a)
            Ss.append(s); As.append(a); Rs.append(r); s = ns
        samples += len(Rs)
        G, acc = np.zeros(len(Rs)), 0.0
        for t in range(len(Rs) - 1, -1, -1):
            acc = Rs[t] + env.gamma * acc
            G[t] = acc
        hist.append(G[0])
        for t in range(len(Rs)):
            theta[Ss[t]] += alpha * (env.gamma ** t) * G[t] * score(theta, Ss[t], As[t])
    return theta, np.array(hist), samples


def imagine_episode(P, R, gamma, theta, start, rng, H, sg):
    """在学到的世界模型里生成一条 imagined 轨迹(遇到终止态提前结束)。"""
    S, A = P.shape[0], P.shape[1]
    s, Ss, As, Rs = start, [], [], []
    for _ in range(H):
        a = rng.choice(A, p=softmax(theta[s]))
        ns = rng.choice(S, p=P[s, a])
        r = R[s, a]
        Ss.append(s); As.append(a); Rs.append(r)
        s = ns
        if s == sg:
            break
    return Ss, As, Rs


def train_in_imagination(env, n_real, n_imag_episodes, alpha=0.10, seed=0, H=50,
                         data_seed=7):
    """先用 n_real 个真实样本学世界模型,再完全在想象中做 REINFORCE。"""
    S, A = env.S, env.A
    data = collect(env, n_real, uniform_policy(S, A), seed=data_seed)
    Pm, Rm, N = fit_table_model(data, S, A, sg=env.sg)
    reach = np.where(N.sum(axis=1) > 0)[0]         # 想象起点只取访问过的状态
    rng, theta, hist = np.random.RandomState(seed), np.zeros((S, A)), []
    for _ in range(n_imag_episodes):
        s = reach[rng.randint(len(reach))]
        Ss, As, Rs = imagine_episode(Pm, Rm, env.gamma, theta, s, rng, H, env.sg)
        G, acc = np.zeros(len(Rs)), 0.0
        for t in range(len(Rs) - 1, -1, -1):
            acc = Rs[t] + env.gamma * acc
            G[t] = acc
        hist.append(G[0])
        for t in range(len(Rs)):
            theta[Ss[t]] += alpha * (env.gamma ** t) * G[t] * score(theta, Ss[t], As[t])
    return theta, np.array(hist), Pm, Rm, n_real


def optimal_value(P, R, gamma, iters=1500):
    V = np.zeros(P.shape[0])
    for _ in range(iters):
        V = (R + gamma * P @ V).max(axis=1)
        V[-1] = 0.0
    return V


def policy_value(P, R, pi, gamma, iters=800):
    V = np.zeros(P.shape[0])
    for _ in range(iters):
        V = (pi * (R + gamma * P @ V)).sum(axis=1)
        V[-1] = 0.0
    return V


if __name__ == "__main__":
    env, S, A = GridWorld(), 25, 4
    Ptrue, Rtrue = env.true_model()
    Vstar = optimal_value(Ptrue, Rtrue, env.gamma)
    print("上帝视角最优值 V*(s0) = %.4f" % Vstar[env.s0])

    # (a) 纯 model-free:不同真实样本预算
    for ne in [100, 200, 400, 800]:
        Js, sm = [], []
        for sd in range(3):
            th, h, samp = reinforce_real(env, ne, seed=sd)
            Js.append(policy_value(Ptrue, Rtrue, softmax(th), env.gamma)[env.s0])
            sm.append(samp)
        print("  model-free 回合=%3d 真实样本=%.0f J=%.4f (占最优 %.1f%%)"
              % (ne, np.mean(sm), np.mean(Js), 100 * np.mean(Js) / Vstar[env.s0]))

    # (b) 世界模型 + 规划(值迭代 + 贪心)
    for n_real in [300, 1000, 3000]:
        Js = []
        for sd in range(5):
            d = collect(env, n_real, uniform_policy(S, A), seed=200 + sd)
            Pm, Rm, _ = fit_table_model(d, S, A, sg=env.sg)
            Vh = optimal_value(Pm, Rm, env.gamma)
            pig = np.zeros((S, A))
            pig[np.arange(S), (Rm + env.gamma * Pm @ Vh).argmax(axis=1)] = 1.0
            Js.append(policy_value(Ptrue, Rtrue, pig, env.gamma)[env.s0])
        print("  model+plan 真实样本=%4d J=%.4f (占最优 %.1f%%) [%.4f, %.4f]"
              % (n_real, np.mean(Js), 100 * np.mean(Js) / Vstar[env.s0], min(Js), max(Js)))

    # (c) 想象中训练(世界模型固定)
    theta_m, hist_m, Pm, Rm, n_real = train_in_imagination(env, 3000, 400, seed=0, H=50)
    Vm = policy_value(Ptrue, Rtrue, softmax(theta_m), env.gamma)
    print("  想象中训练: 想象回报 %.4f -> %.4f,真实 J=%.4f(占最优 %.1f%%),高估 %.4f"
          % (hist_m[:100].mean(), hist_m[-100:].mean(), Vm[env.s0],
             100 * Vm[env.s0] / Vstar[env.s0], hist_m[-100:].mean() - Vm[env.s0]))

    # (d) 模型偏差:数据不足时"在坏模型里最优"反而坑了自己
    for n_real in [100, 300, 3000]:
        d = collect(env, n_real, uniform_policy(S, A), seed=7)
        Pm, Rm, _ = fit_table_model(d, S, A, sg=env.sg)
        Vh = optimal_value(Pm, Rm, env.gamma)
        pi_hat = np.zeros((S, A))
        pi_hat[np.arange(S), (Rm + env.gamma * Pm @ Vh).argmax(axis=1)] = 1.0
        print("  n=%4d 模型内 V*=%.4f 真实 V*=%.4f 偏差 %+.4f 贪心策略真实 J=%+.4f"
              % (n_real, Vh[env.s0], Vstar[env.s0], Vh[env.s0] - Vstar[env.s0],
                 policy_value(Ptrue, Rtrue, pi_hat, env.gamma)[env.s0]))

代码做什么:(a) 跑标准 REINFORCE(真实环境),记录累计真实样本数;(b) 用「学到的世界模型 + 值迭代 + 贪心」得到策略,再用上帝视角的真实模型精确评估它的 $J$;(c) 用 3000 个真实样本训好世界模型后冻结它,只在想象中跑 400 条轨迹做同样的 REINFORCE 更新;(d) 用 100/300/3000 个真实样本学模型,比较「模型内最优值」与「真实最优值」的偏差。

RL 机制透视:这个实验的设计目的是把讲义第 5 页的定义变成可测量的对照。reinforce_realtrain_in_imagination 的更新式完全一样(都是 $\theta_{s}\mathrel{+}=\alpha\gamma^t G_t(\mathbf{e}_a-\pi)$),唯一区别是采样器:前者是 env.step,后者是 rng.choice(S, p=Pm[s,a])。因此两者的差异必然全部来自模型误差,而不是算法差异。另一个关键细节是 reach = np.where(N.sum(axis=1) > 0)[0]:想象的起点只能取真实数据访问过的状态——这暴露了 model-based RL 的一个硬约束:世界模型只能在你见过的地方做想象,无法凭空创造新状态。(c)中想象回报被高估,正是讲义第 17 页与第 25 页那种「模型内最优 ≠ 真实最优」的直接体现。

实验观察(真实运行输出)

[实验三] 在想象中训练策略 vs 直接在真实环境训练
  上帝视角: 最优值 V*(s0) = 0.4104(真值模型值迭代)
  (a) 纯 model-free REINFORCE:真实样本预算 vs 精确评估 J(θ)=V^{π_θ}(s0)(3 seed)
       回合数 |        真实样本数 |         J(θ) |        占最优
       100 |         4180 |      -0.5088 |    -124.0%
       200 |         7687 |      -0.2967 |     -72.3%
       400 |        11764 |       0.0349 |       8.5%
       800 |        18348 |       0.2205 |      53.7%
  (b) 世界模型 + 规划:真实样本预算 vs 真实环境中的 J(π_hat)
       真实样本数 |     J(π_hat) |        占最优 | [min, max](5 seed)
         300 |      -0.3818 |     -93.0% | [-0.7948, 0.4036]
        1000 |       0.4085 |      99.5% | [0.4055, 0.4103]
        3000 |       0.4074 |      99.3% | [0.4058, 0.4089]
  (c) 想象中训练:固定世界模型,400 条 imagined 轨迹,H=50
      世界模型用 3000 真实样本训练;想象回报 -0.1930 -> 0.4038(前/后 100 条,模型内乐观值)
      真实环境精确评估 J(θ) = -0.0197(占最优 -4.8%)——想象回报被高估了 0.4235
      注: 想象中的策略梯度只在访问过的状态下更新(起点集合 24 个状态),
          因此它是 model-based RL 的**弱化版**:J=-0.020 远不如同样本量下「模型+规划」的 J=0.407。
      对照: model-free 需要 18348 个真实样本才到 J=0.2205;
            而「学模型 + 规划」只用 1000 个真实样本就到 J=0.4085(占最优 99.5%)。
  (d) 模型偏差(model bias):数据不足时世界模型里的最优 ≠ 真实最优
      n= 100 : 模型内 V*_hat(s0)=+0.6408,真实 V*(s0)=+0.4104,乐观偏差 +0.2304,在该模型里贪心的策略真实 J=-0.4213
      n= 300 : 模型内 V*_hat(s0)=+0.4786,真实 V*(s0)=+0.4104,乐观偏差 +0.0681,在该模型里贪心的策略真实 J=+0.3938
      n=3000 : 模型内 V*_hat(s0)=+0.4348,真实 V*(s0)=+0.4104,乐观偏差 +0.0244,在该模型里贪心的策略真实 J=+0.4072

四点读数:①样本效率的巨大差距:model-free 用了 18348 个真实样本只到 $J=0.2205$(占最优 $53.7\%$),而「学世界模型 + 规划」只用 1000 个真实样本就到 $J=0.4085$(占最优 $99.5\%$)——样本效率差约 $18\times$,且模型法还差得更优。这量化了讲义把世界模型放在核心位置的理由。②模型偏差是最危险的失败模式:$n=100$ 时模型内的 $V^*$ 是 $+0.6408$,比真实的 $+0.4104$ 乐观了 $+0.2304$;在该模型里贪心的策略在真实环境中只有 $J=-0.4213$——在坏模型里做最优规划,结果比随机策略还糟。③数据量回到 3000 后,偏差收敛到 $+0.0244$,贪心策略的真实 $J=0.4072$ 已接近真最优 $0.4104$。④「在想象中训练」(c)是三者中最弱的一环($J=-0.0197$):因为想象起点只覆盖 24 个访问过的状态,且 REINFORCE 的方差在想象中没有真实环境探索来纠正——这恰好说明为什么工业级系统(MuZero、Dreamer)必须把「模型学习」与「策略改进」交替迭代(伪代码第 25 行),而不是把模型冻结后一路想象到底。

15.5 评估指标与理论保证

15.5.1 世界模型本身的评估指标(对应讲义第 9–12 页「预测即理解」)

指标定义优点陷阱
一步预测误差$\mathbb{E}_{(s,a)\sim\mathcal{D}}\vert \hat P(\cdot\mid s,a)-P(\cdot\mid s,a)\vert _1$易计算、可诊断与策略性能弱相关
一步对数似然 / NLL$-\mathbb{E}\log\hat P(s^{\prime}\mid s,a)$对校准敏感、可跨模型类比较偏爱大方差模型(§15.4 中线性模型 NLL 差 $0.95$)
多步 roll-out 误差$\vert d_H-\hat d_H\vert _{TV}$,$H=1,2,5,10,20,\dots$直接对应规划质量受环境混合性影响会饱和(§15.4 实测)
长时程一致性在 $H$ 步内是否出现物理/逻辑矛盾与「理解」直接相关(讲义第 12、22 页)难以自动化度量
下游策略性能真实环境中的 $J(\pi_{\text{plan}})$最终唯一重要的指标需要真实交互,违背省样本的初衷

关键结论(本讲与 §15.4 的联合教训):一步预测精度高 ≠ 规划好。§15.4 实验一中表格模型命中率 $92.25\%$ 已是全实验最好的模型;但实验三 (d) 显示 $n=100$ 时模型内的「最优」直接导致真实性能崩溃。因此评估世界模型必须看多步 roll-out 误差下游规划性能,不能只看一步 NLL。

15.5.2 规划与策略学习的理论保证

(1)仿真引理(Simulation Lemma,Kearns & Singh 2002):若对所有 $(s,a)$ 有 $\vert R(s,a)-\hat R(s,a)\vert \le\epsilon_R$ 且 $\vert P(\cdot\vert s,a)-\hat P(\cdot\vert s,a)\vert _1\le\epsilon_P$,则对任意策略 $\pi$ 与任意起始状态 $s$,

\[\big|V^{\pi}(s)-\hat V^{\pi}(s)\big|\;\le\;\frac{\epsilon_R+\gamma R_{\max}\epsilon_P}{1-\gamma}.\]

这是 model-based RL 的最坏情况保证:模型误差被 $1/(1-\gamma)$ 放大。条件依赖:需要一致误差界(所有状态动作对上),而这在函数逼近下通常不成立。

(2)$H$ 步复合误差界(本笔记 §15.3.2 推导,讲义未给):

\[\|d_H-\hat d_H\|_{TV}\;\le\;\min\big(1,\ H\epsilon_1\big),\qquad \epsilon_1=\max_{s,a}\|P(\cdot\|s,a)-\hat P(\cdot\|s,a)\|_{TV}.\]

这是线性而非 $1/(1-\gamma)$ 的放大,因为它衡量的是 $H$ 步截断分布而非无限时程值函数。§15.4 实验二 (2a) 在 $H\le5$ 段实测斜率 $1.011$;(2b) 连续系统实测斜率 $1.209$(严格线性,略高于 $1$ 是因为学到的 $\hat A$ 谱半径略大)。注意与仿真引理的关系:$H$ 步截断值误差 $\to$ 完整值误差时,线性界会被 $(1-\gamma)^{-1}$ 类因子接管。

(3)表格世界模型的估计误差:对固定 $(s,a)$,用 $N(s,a)$ 个样本估计 $P(\cdot\vert s,a)$,由 Hoeffding 不等式,以概率 $\ge 1-\delta$ 有

\[\|\hat P(\cdot\mid s,a)-P(\cdot\mid s,a)\|_1\;\le\;\sqrt{\frac{2\,\|\mathcal{S}\|\,\ln(2\|\mathcal{S}\|\|\mathcal{A}\|/\delta)}{N(s,a)}},\]

每个 $(s,a)$ 需要 $O(\vert \mathcal{S}\vert \log(\vert \mathcal{S}\vert \vert \mathcal{A}\vert /\delta)/\epsilon_1^2)$ 个样本才能把 TV 误差压到 $\epsilon_1$。$\S15.4$ 实验一中平均每对 $(s,a)$ 有 $31.2$ 个样本,$\vert \mathcal{S}\vert =25$,代入即预期 TV 误差约 $\sqrt{2\cdot25\cdot\ln(2\cdot100/0.05)/31.2}\approx2.4$(被截断到 $1$)——这解释了为什么 3000 条转移远不足以精确估计 $25\times4\times25$ 的转移张量,也解释了实验三中 $n=300$ 时的高方差($[-0.7948,0.4036]$,跨越了近 $1.2$ 的价值区间)。

(4)model-based vs model-free 的样本复杂度权衡:model-based 方法把真实交互花在估计模型上(表格情形为 $\Theta(\vert \mathcal{S}\vert \vert \mathcal{A}\vert )$ 个「参数」),之后所有规划/想象都是免费的;model-free 方法把真实交互直接花在估计值函数上($\vert \mathcal{S}\vert \vert \mathcal{A}\vert $ 个值,但每次更新只利用一步信息)。这解释了 §15.4 中 $18\times$ 的样本效率差。代价是 model-based 多承担模型偏差(实验三 (d):$n=100$ 时真实 $J$ 从 $+0.41$ 崩到 $-0.42$)。

(5)条件依赖分析

  • 探索策略:世界模型只在访问过的 $(s,a)$ 上可信(实验三 (c) 的 reach 集合只有 24 个状态)。因此探索策略(L9–L12)决定了模型的有效支撑集,讲义第 16 页把 DPM/ICM/VIME 放在 Level 2 正是这个道理。
  • 函数逼近:§15.4 实验一给出直接证据——同一份数据下,表格 MLE 命中率 $0.9225$、线性回归只有 $0.4863$。模型类选择(表格 / 线性 / 图网络 / 视频模型)就是讲义第 29–35 页争论的核心。
  • 在线/离线:伪代码的阶段 C 决定了这是在线(数据分布随策略变化)还是离线(固定数据集)。讲义第 15–16 页的 Level 1/Level 2 之分,本质上就是「平稳数据分布 vs 非平稳数据分布」。
  • 规划视界 $H$:仿真引理的 $1/(1-\gamma)$、复合误差的 $\epsilon_1H$、以及 §15.4 中 $H=50$ 时想象回报高估 $0.4235$——三者都在说同一件事:视界越长,模型越不可信

15.6 与其他讲次的关联

  • 与 L2(Tabular MDP Planning,有模型):L2 假设 $P,R$ 已知,直接做值迭代/策略迭代;本讲把「已知模型」换成「学到的模型 $\hat P,\hat R$」。§15.4 实验三 (b) 的「学模型 + 值迭代 + 贪心」就是 L2 算法套上本讲的模型。可以说 L15 = L2 + 模型学习
  • 与 L3–L4(TD/MC 与 Q-learning、函数逼近):仿真引理(§15.5.2)是 L3 策略评估误差分析的模型化版本;§15.4 实验一的「估计误差 vs 逼近误差」与 L4 的函数逼近讨论是同一套语言;§15.4 实验三的 REINFORCE 更新式即 L5 的形式。
  • 与 L5–L7(策略梯度、基线、PPO/GAE):§15.3.2 的想象策略梯度在估计量形式上与 L5–L7 完全相同($\nabla_\theta\log\pi_\theta\cdot\hat A_t$),唯一区别是采样器。讲义第 27 页的 GDT(hindsight BC wrt “any future statistics”)则与 L7–L8 的模仿学习/行为克隆直接相连。
  • 与 L8(模仿学习 / RLHF / DPO):逆向模型 $g_\psi(s_t,s_{t+1})$ 是从观测反推动作的标准工具;DAgger/GAIL 被讲义第 16 页明确放进 Level 2。
  • 与 L9–L12(样本效率与探索):这是关系最紧的一组。讲义第 16 页点名 VIME(2017)、DPM(2016)、ICM(2017)——它们都是「用模型的不确定性/新颖性做内在奖励」,正是 L9–L12 的探索框架在模型视角下的实现。此外 L11–L12 的 RMax 与 PSRL 是表格 model-based RL 的经典样本复杂度结果,本讲的「学模型→规划」是它们的深度学习版本;Solomonoff 归纳(第 11 页)与 PSRL 的先验、Occam 剃刀也是同一条思路。
  • 与 L13–L14(MCTS、AlphaZero/MuZero):讲义第 20、28 页的「射击法」正是 MCTS 的连续动作版本(用学到的模型做前向展开 + 搜索);第 26、28 页把 TDM/GDT 与直接配点法结合,是 MCTS 之外的另一种规划范式(全局轨迹优化 vs 逐步搜索)。MuZero(L14 主题)本质上就是把 AlphaZero 的已知模拟器换成学到的隐空间模型——这正是本讲第 5 页那句定义的实例化。讲义第 8 页还提到一个未展开的话题「Control as inference: e.g. particle smoothing as optimal control, MCTS vs beam search」,可作为 L13–L14 的延伸阅读方向。
  • 与 L16(Alignment / 价值对齐):讲义 Level 3「主动让世界去拟合你的世界模型」在语义上有直接的伦理含义——当主体通过行动改造世界以使世界符合自己的预测时,这正是价值对齐问题的一个侧面。讲义举的例子(政客、金融机构、X 网红)本身就带有社会后果。

15.7 关键要点

  1. 世界模型就是 model-based RL 里的那个 model(讲义第 5 页原话)。因此本讲的每一个概念都可以翻译成 L2 的语言:$\hat P,\hat R$、规划、roll-out、模型误差。
  2. 预测 = 理解(讲义第 12 页):最好的预测是推出能复现数据的最短程序(Solomonoff 归纳),因此世界模型的质量不仅是数值精度问题,更是「是否抓到了因果程序」的问题;这也是 OOD 泛化的来源(第 13 页 IRM 与「Diversity is all you need」)。
  3. 三层次框架是全场纲领(第 14–17 页):Level 1 被动拟合(预训练/自监督,数据平稳)、Level 2 主动拟合(后训练/DAgger/GAIL/主动学习,数据非平稳)、Level 3 主动改造世界使其可预测(未解决,「Remember the Level 3」)。
  4. 规划有两族方法(第 20–23 页):射击法(前向展开,对应 MCTS 与自回归视频扩散,精细装配任务上很难)vs 直接配点法(松弛动力学约束,「先解任务再修物理」,对应双向视频扩散)。
  5. 值函数与决策 Transformer 都是隐式世界模型(第 25、27 页):TDM 的 $Q(s,a,g,n)$ 是时间扩展的隐式模型,GDT 的 hindsight BC 对着「任意未来统计量」训练、测试时给未见过的未来要求泛化。
  6. 样本效率的代价是模型偏差:§15.4 实测 model-based 用 $1000$ 个真实样本达到最优的 $99.5\%$(model-free 用 $18348$ 个样本只到 $53.7\%$,约 $18\times$ 差距),但 $n=100$ 时「在坏模型里最优」的策略真实性能是 $-0.4213$,比不做规划还糟
  7. 复合误差按 $H$ 线性累积:$\vert d_H-\hat d_H\vert _{TV}\le\min(1,H\epsilon_1)$,实测斜率 $1.011$(表格,$n=3000$)与 $1.209$(连续线性系统)。长视界想象必然失真,因此必须「模型学习 ↔ 策略改进」交替迭代。

15.8 常见误区与注意事项

  1. 误区:世界模型就是「预测下一帧的视频模型」。 改正:按讲义第 4–5 页,世界模型首先是 model-based RL 里的模型($\hat P,\hat R$),它可以退化成表格、图网络、值函数(TDM)甚至隐空间无解释变量。「视频模型」只是讲义第 31 页在讨论的一种具体实现载体,而且讲者明确声明本讲不展开 Gemini / Veo / Genie 相关产品。
  2. 误区:一步预测准确率高的世界模型就一定好用。 改正:§15.4 中表格 MLE 一步命中率 $92.25\%$ 已是最优模型,但 $n=100$ 时在它里面贪心得到的策略真实 $J=-0.4213$。必须看多步 roll-out 误差下游规划性能;这与讲义第 12 页「预测即理解」是同一枚硬币的两面——只拟合像素噪声不算理解。
  3. 误区:模型误差会随 $H$ 指数爆炸($e^{H}$ 式)。 改正:本笔记 §15.3.2 的推导与 §15.4 的实测都支持线性上界 $H\epsilon_1$,且 TV 被截断在 $1$;更常见的情况是环境混合性让误差饱和甚至回落(实测 $n=3000$ 时 $H=50$ 的 TV 降到 $0.00000$)。真正的指数放大出现在值函数层面,由仿真引理的 $1/(1-\gamma)$ 因子承担,不是 $e^H$。
  4. 误区:既然世界模型能省样本,那就把数据全花在模型上、一开始就把模型训到最好。 改正:世界模型只在访问过的 $(s,a)$ 上可信。§15.4 实验三 (c) 的想象起点只有 24 个状态,导致「想象中训练」的真实 $J=-0.0197$,远逊于「模型 + 规划」的 $0.407$。正确做法是伪代码第 25 行的交替迭代(Level 2)。
  5. 误区:Level 3 只是学术玩笑,不必当真。 改正:讲义把它与「政客、金融机构、X 网红」并列,并放在第 36 页的告别语里(「Remember the Level 3」)。它描述的是一种用行动改造环境以使环境符合自身模型的行为模式,在讨论 AI 系统与价值对齐(L16)时具有直接的现实含义。
  6. 误区:射击法一定不如直接配点法。 改正:讲义第 22–23 页的态度是分场景的——直接配点法(CIO)在接触丰富的任务上「solves contact-rich tasks with minimal reward shaping」,而射击法在精细装配上很难(Ghasemipour et al. 2022)。两者是同一枚硬币的两面,讲义用「自回归 vs 双向视频扩散」精确刻画了这一对偶。
  7. 误区:表格实验里的世界模型误差就是全部误差。 改正:§15.4 实验一同一份 3000 条数据下,表格 MLE 命中率 $0.9225$,线性回归仅 $0.4863$——逼近误差可以远大于估计误差。在谈论「模型学得好不好」时,必须先说清楚假设类。

15.9 思考题(带答案)

题 1(计算题:复合误差界) 在 §15.4 的 5×5 GridWorld 中,测得学到的世界模型每步最大 TV 误差 $\epsilon_1=0.02$。请给出 $H=20$ 步 roll-out 的 TV 距离上界,并说明为什么实测值往往远小于这个上界。(提示:参考 §15.4 中 $n=3000$ 的实测数据。)

答案:由 §15.3.2 的复合误差界,$\vert d_{20}-\hat d_{20}\vert _{TV}\le\min(1,20\times0.02)=0.40$。§15.4 实测(表格模型,确定性贪心策略,$n=3000$)$H=20$ 的 TV 只有 $0.00052$,比上界小约 $770$ 倍。原因有三:① 上界是最坏情况,它假设每步的误差都以最不利的方向叠加;② GridWorld 的打滑($\text{slip}=0.1$)使状态分布快速混合到平稳分布,而两个模型在平稳分布上几乎一致,因此误差被「冲淡」;③ 上界忽略了误差项可能带相反符号而互相抵消。注意:上界依然有意义——它是可证明的保证,且当环境不混合时(如 §15.4 的连续 double integrator,$H=20$ 时误差是单步的 $38.5$ 倍)会逼近线性行为。

题 2(推导题:想象策略梯度的无偏性边界) 设世界模型参数为 $\phi$,策略参数为 $\theta$。请说明在什么条件下 $\mathbb{E}{\hat\tau}[\sum_t\nabla\theta\log\pi_\theta(a_t\vert s_t)\hat A_t]$ 是 $\hat J(\theta)$(模型内的目标)的无偏梯度,并解释为什么它对真实目标 $J(\theta)$ 有偏。

答案:无偏性的关键条件是 $\phi$ 不依赖 $\theta$(即世界模型在想象训练期间被冻结,或至少对 $\theta$ 视作常数)。此时 $\hat s_t$ 的分布由 $\phi$ 与过去的动作决定,与 $\nabla_\theta$ 无关,可以直接套用策略梯度定理(§15.3.2 第一步):

\[\nabla_\theta\hat J(\theta)=\mathbb{E}_{\hat\tau}\Big[\sum_t\nabla_\theta\log\pi_\theta(a_t\|\hat s_t)\big(\hat G_t-\hat b(\hat s_t)\big)\Big],\]

这正是伪代码第 13–23 行做的事。对真实目标有偏的原因是 $\hat P\neq P$ 且 $\hat R\neq R$:$\hat J$ 与 $J$ 是两个不同的 MDP 上的目标,模型内的梯度方向在真实 MDP 上是不动点偏移的。误差大小由仿真引理(§15.5.2)控制:$\vert J-\hat J\vert \le(\epsilon_R+\gamma R_{\max}\epsilon_P)/(1-\gamma)$。实践推论:世界模型不能冻结太久——必须像伪代码第 25 行那样回到真实环境、用新数据刷新 $\phi$(这正是讲义 Level 2 与 §15.4 实验三 (c) 的现实教训)。

题 3(概念题:三层次框架的判定) 把下列四项活动分别归入讲义的 Level 1/2/3,并说明理由:(a) 用固定数据集训练一个视频预测模型;(b) DAgger 中用当前策略采集新数据并重新训练;(c) 一家做市商通过报单影响市场价格以使自己的成交预测更准确;(d) 用 ICM 的新颖性奖励驱动智能体去探索未访问的房间。

答案

  • (a) Level 1(被动拟合)。数据分布是固定的离线数据集,预测训练期间分布平稳——对应讲义第 15 页「Data distribution is stationary during predictive training」。
  • (b) Level 2(主动拟合)。DAgger 的本质是「用当前策略诱导的分布去重训策略」,讲义第 16 页明确把 DAgger 列在 Level 2,并强调「Data distribution is non-stationary」。
  • (c) Level 3(主动改造世界使其可预测)。讲义第 17 页原文的三个例子是「Politicians / Financial firms / X Influencers」,做市商通过行动改变市场(世界)以使自身的价格预测更准,完全对应「Actively fit world to your world model」。
  • (d) Level 2(主动拟合)。ICM 在讲义第 16 页被明确点名(「DPM (Stadie 2016) and ICM (Pathak 2017) incentivizes novelty」),它用内在奖励改变数据采集分布,让世界模型在更多区域变得准确,但没有改造世界本身。

题 4(对比题:射击法 vs 直接配点法) 在 §15.4 的 GridWorld 中,「用学到的 $\hat P$ 展开 $H=50$ 步并执行第一步」(模型预测控制,MPC)属于射击法还是直接配点法?若改成「对整条 50 步轨迹同时优化状态与动作、并允许动力学约束以权重 $\lambda$ 被违反」,则属于哪一类?请结合讲义第 21–22 页的 CIO 说明后者的直觉。

答案:前者是射击法——决策变量只有动作序列,状态由 $\hat P$ 逐步前向展开,每一步都必须精确满足(学到的)动力学,因此误差会按 §15.5.2 的 $H\epsilon_1$ 累积;这正是 §15.4 实验二中 $H=50$ 的长视界想象。后者是直接配点法——状态与动作同时作为决策变量,动力学 $\hat s_{t+1}=f(\hat s_t,a_t)$ 以罚项 $\lambda\vert \hat s_{t+1}-f(\hat s_t,a_t)\vert ^2$ 松弛,允许「先违反物理再修回来」。按讲义第 21 页 CIO 的两句原文:「Constrained optimization wrt dynamics constraints := relaxing (hacking) dynamics during planning」和「First solve task, then fix physics」;讲义第 22 页进一步指出「dynamics relaxation provides appropriate ‘reward shaping’」——即松弛本身替代了人工奖励塑形,使接触丰富(contact-rich)的任务更容易求解,代价是最终解必须通过增大 $\lambda$ 才能变得物理可行。