跳转到正文

9.3 基于模型的强化学习

本节导读

核心内容

  • 理解 Model-Based RL 和 Model-Free RL 的根本区别:为什么"先学环境模型再训策略"能把样本效率提升 10-100 倍。
  • 掌握 Dyna 框架:如何把环境模型当成"额外数据生成器",每次真实交互后做 N 次模拟更新。
  • 理解模型误差累积问题:为什么长 rollout 会让预测误差爆炸,Lipschitz 常数怎么刻画这个问题。
  • 了解 PETS 如何用概率集成(probabilistic ensembles)量化两种模型不确定性,配合 CEM 规划做鲁棒控制。
  • 掌握 MBPO 的短 horizon rollout 思想:为什么只做 5 步模型预测就重置到真实状态,能避免误差累积同时大幅提升样本效率。

上一节 9.2 我们解决了连续控制 model-free 算法的稳定性问题——TD3 用三个工程补丁、SAC 用最大熵重构目标函数,让 DDPG 终于在 MuJoCo 上稳定可用,训练百万步能给出相当不错的策略。

但是,让我们停下来想一下。百万步在仿真器(MuJoCo)里可能只要几小时,但如果是真实机器人呢?机械臂的电机有磨损、电池续航有限、真实环境中碰撞可能损坏设备——每次真实环境采样都是有成本的。百万步对真实机器人来说,可能意味着几个星期甚至几个月的不间断运行,这在实践中根本不可承受。

这就引出了 Model-Based RL 的核心问题:能不能让智能体在和真实环境交互很少的情况下,也能学到好策略? Model-Based RL 给出的答案是:学一个环境模型——也就是学一个"如果我在状态 做动作 ,下一状态会是什么、奖励会是多少"的预测器——然后让策略主要在这个模型上训练,把和真实环境的交互次数从百万步降到万步级别。

这一节我们就来拆解 model-based RL 的三条主流路线:从最简单的数据增强(Dyna),到概率集成 + 轨迹采样(PETS),再到短 horizon rollout(MBPO)。

Model-Based 与 Model-Free 的根本区别

前面所有算法(DDPG/TD3/SAC)都是 model-free 的。你可能会问:"model-free 是什么意思?free 的是什么?" Model-free 不是说"没有模型",而是说智能体不试图去理解、建模环境的运作规律。它就像一个强化学习者:你给我状态、我输出动作、你给我奖励,我只根据奖励信号调整策略——至于环境为什么会给出这个奖励、做了这个动作世界会怎么变,我完全不关心。

Model-Based RL 反其道而行之。它说:在学策略之前,或者在学策略的同时,我先学一个环境模型:

让我们把这两个符号拆开看:

  • :这是动力学模型。给定当前状态 和动作 ,预测下一状态 的概率分布。帽子 表示这是我们学到的近似模型,不是真实环境
  • :这是奖励模型。给定状态 和动作 ,预测即时奖励。

有了这两个模型,智能体就可以"在脑子里想象":如果我现在做这个动作,会发生什么?会得到多少奖励?然后基于这些想象出来的轨迹来做规划或者训练策略。

为什么用模型?

最核心的动机就是样本效率

让我们用具体数字感受一下差距。Model-free 算法(比如 SAC)在 MuJoCo 上通常需要 100 万步(1M steps)才能收敛到好策略。Model-based 算法呢?MBPO 只需要 10-100 千步(10K-100K steps)就能达到同等性能——样本效率提升了 10-100 倍

这不是一个小数字。如果每一步真实交互需要 1 秒(真实机器人运动需要时间),100 万步就是约 11.5 天不间断运行;而 10 万步只需要约 1 天。对于更昂贵的场景——比如自动驾驶、工业机器人、化学反应控制——这个差距可能就是"能用"和"不能用"的区别。

为什么 model-based 能省这么多真实样本?因为一旦模型学好了,你可以在模型里无限次"想象"采样,而这些想象出来的采样几乎是零成本的。就像人学下棋:你不需要真的把每盘棋都下完,你可以在脑子里推演"如果我走这一步,对方会怎么走,然后我再怎么走"——这种"脑子里的推演"就是 model-based planning。

但是——你可能已经想到一个问题——模型如果学错了怎么办?在错误的模型上训练出来的策略,到真实环境里会不会也错?这就是 model-based RL 的核心矛盾:模型偏差(model bias)。后面我们会看到,Dyna、PETS、MBPO 这三个算法,本质上是在用三种不同的方式应对这个矛盾。

三大范式概览

在深入细节之前,我们先把 model-based RL 的三大主流范式列出来,给你一个全景:

范式核心思想代表算法适用场景
Dyna模型作为数据增强Dyna-Q离散动作,快速训练
PETS概率集成 + 轨迹采样PETS高精度控制,模型不确定性重要
MBPO短 horizon rolloutMBPO通用连续控制

让我们从最简单的 Dyna 开始。

模型作为数据增强

Sutton 在 1990 年提出的 Dyna 框架,是 model-based RL 最经典、最朴素的思路。它的想法简单到让人惊讶:模型就是一个额外的数据生成器。每次你和真实环境交互一次,拿到一条真实经验 ,你就用这条经验同时做两件事:

  1. 像往常一样用它做一次 model-free 更新(比如 Q-learning);
  2. 用它训练你的环境模型;
  3. 然后——关键来了——从模型里"想象"出 N 条假经验,用这些假经验再做 N 次 model-free 更新。

让我们看代码理解这个流程:

python
for step in range(total_steps):
    # 1. 真实交互
    a = policy.select(s)
    s_prime, r = env.step(a)
    replay_buffer.add(s, a, r, s_prime)

    # 2. 用真实数据更新 model-free 算法(如 Q-Learning)
    q_learning_update(replay_buffer.sample())

    # 3. 用真实数据训练环境模型
    model.train(s, a, r, s_prime)

    # 4. 用模型生成"假"数据,再做 N 次 Q-Learning 更新
    for _ in range(N):  # N = 10-100
        s_sim, a_sim = replay_buffer.sample_state_action()
        s_sim_next, r_sim = model.predict(s_sim, a_sim)
        q_learning_update(s_sim, a_sim, r_sim, s_sim_next)

看明白了吗?每次真实交互后,我们额外做 N 次"模拟"的 Q-learning 更新——这些更新用的不是真实环境,而是模型预测出来的数据。如果 N=10,那相当于每做 1 次真实交互,我们就做了 11 次 Q-learning 更新;理论上,样本效率就能提升约 N 倍。

这想法太美了,对吧?但等等——这里有个问题。

Dyna 的关键限制

让我们停下来想一下:上面的代码用的是确定性模型——直接预测下一状态 。但即使你用概率模型,有一个根本问题是绕不开的:在连续物理环境(比如 MuJoCo)里,如果你反复把模型的预测结果作为下一步的输入,误差会像滚雪球一样越积越大

为什么会这样?我们来做个数学分析。假设每一步模型预测的误差不超过 ——也就是预测状态和真实状态之间的距离 。再假设真实环境的动力学函数关于状态是 Lipschitz 连续的,Lipschitz 常数为

你可能会问:"Lipschitz 常数是什么?" 简单说,Lipschitz 常数 衡量的是"状态变一点点,下一状态会变多少"。如果 ,那状态差多少,下一状态就差多少;如果 ,误差会放大;如果 ,误差会自动缩小。对于像 MuJoCo 这样的物理环境, 通常接近 1 甚至略大于 1。

那么,在同一动作序列下,我们递推一下每一步的状态误差

我们来验证一下这个递推式对不对:第 步我们已经有误差 ,经过真实动力学,这个误差最多被放大 倍变成 ;然后我们自己的模型又额外引入最多 的单步预测误差——所以第 步的总误差上界就是两者相加。

步之后误差会累积到多大?我们可以把这个递推式展开:

让我们用具体数字算一下,这样你就有直觉了:

  • 情况 1:(误差自动收缩)。等比数列求和,当 很大时,和收敛到 。误差不会无限增长,最终被控制在 以内。这是最理想的情况。
  • 情况 2:(误差不放大也不缩小)。每一步加一个 步后误差就是 ——线性增长。rollout 100 步,误差就是单步误差的 100 倍。
  • 情况 3:(误差放大)。等比数列增长, 步时,和是 。单步误差如果是 0.01,50 步后误差就超过 11——这对于状态维度通常在几十量级的机器人控制来说,预测已经完全不准了。

这就是为什么简单的 Dyna 在像网格世界这样的简单离散环境里工作得很好,但在复杂连续控制环境里会出问题:rollout 越长,模型误差累积越严重,到后面模型预测出来的轨迹和真实轨迹已经完全是两回事了。用这样的假数据训练策略,策略很可能被带偏。

那怎么办呢?后续的工作(PETS、MBPO)都在解决同一个核心问题:"如何量化并应对模型误差?"

  • PETS 的思路:我知道模型不确定,那我就显式建模这种不确定性。用概率集成(多个模型一起预测)来表达"我对这个预测有多确信",规划的时候考虑这种不确定性,让策略对"模型可能错"保持鲁棒。
  • MBPO 的思路:既然长 rollout 误差爆炸,那我就不做长 rollout。只做很短的(比如 5 步)模型预测,然后立刻重置到真实状态,不让误差有机会累积太多。

我们先看 PETS。

概率集成轨迹采样

Probabilistic Ensembles with Trajectory Sampling(Chua et al. 2018),简称 PETS,有一个关键观察:模型的不确定性其实分两种,它们来源不同,应对方式也不同。

你可能会问:"模型不就是不准吗?不确定性还分种类?" 是的,分两种,而且这个区分非常重要:

  • 认知不确定性(epistemic uncertainty):这种不确定性来自数据不足。因为你没见过足够多类似 的情况,模型本身不知道会发生什么——就像一个新手司机第一次在雪天开车,他不确定会发生什么,不是因为下雪本身是随机的,而是因为他没经历过。这种不确定性可以通过更多数据消除
  • 偶然不确定性(aleatoric uncertainty):这种不确定性来自环境本身的随机性。即使你有无限多的数据,你也没法完美预测——就像掷骰子,不管你观察多少次,下一次掷出什么还是随机的。这种不确定性无法被更多数据消除,你只能建模它。

PETS 用两种不同的机制分别处理这两种不确定性:

  • 集成(ensemble)——也就是训练 个独立的模型——来表达认知不确定性。如果这 个模型的预测都一致,说明模型在这个区域很确定;如果它们预测差异很大,说明这里模型没见过、不确定。
  • 概率输出 ——也就是不是预测一个确定的 ,而是预测一个高斯分布的均值和方差——来表达偶然不确定性。方差大的地方,说明环境本身就随机。

模型架构

PETS 的模型是 个概率神经网络的集成,通常 就够了。我们来看代码结构:

python
class PEModel:
    def __init__(self, n_models=5):
        self.models = [ProbabilisticNN() for _ in range(n_models)]

    def predict(self, s, a):
        # 每个模型输出 (mean, var)
        means, vars = [], []
        for m in self.models:
            mu, sigma = m(s, a)
            means.append(mu); vars.append(sigma)
        return means, vars  # 集成散度 = epistemic uncertainty

每个 ProbabilisticNN 不直接输出下一状态,而是输出一个高斯分布的均值 和标准差 ——也就是假设

训练的时候,每个模型独立初始化、独立训练,用的都是真实交互数据,但可以用不同的 mini-batch 顺序、不同的初始化,让它们最终学到的模型略有不同。

Trajectory Sampling 策略

有了概率集成模型,怎么用它做规划呢?PETS 用 MPC(模型预测控制) 思想:每一步都重新规划未来 H 步的动作,但只执行第一步,然后走到下一状态再重新规划。这种"滚动优化"的思想能让策略不断根据最新的真实状态修正规划,不容易被模型误差带太远。

具体的规划算法用的是 CEM(Cross-Entropy Method,交叉熵方法)——这是一种简单但强大的采样式优化算法,特别适合连续动作空间的规划。我们来看代码:

python
def cem_planning(model, s, horizon=10, n_samples=500, n_iters=5):
    # 初始化动作分布
    action_mean = zeros(horizon, action_dim)
    action_var = ones(horizon, action_dim)

    for it in range(n_iters):
        # 1. 采样 N 条动作序列
        action_seqs = sample_normal(action_mean, action_var, n_samples)

        # 2. 用模型 rollout,每条序列用随机一个集成模型
        rewards = []
        for seq in action_seqs:
            model_id = random_int(0, K)
            s_pred = s
            total_r = 0
            for a in seq:
                s_pred, r = model[model_id].predict(s_pred, a)
                total_r += r
            rewards.append(total_r)

        # 3. 选 top 20% 的序列,更新分布
        elite = top_k_indices(rewards, k=0.2 * n_samples)
        action_mean = action_seqs[elite].mean(0)
        action_var = action_seqs[elite].var(0)

    return action_mean[0]  # 只执行第一步(MPC 思想)

这里有一个关键细节:第 2 步做模型 rollout 的时候,每条轨迹从头至尾用同一个随机选出来的集成模型,而不是每一步都随机换模型。这叫做 TS1(Trajectory Sampling with 1 model),为什么要这样做?因为如果每一步都随机换模型,你其实是在"平均模型"的动力学上做规划——但真实世界只有一个,不是五个模型的平均;固定用一个模型 rollout 整条轨迹,能更好地捕捉多模态的未来,让规划对模型不确定性更鲁棒。

CEM 的工作原理也很直观:

  • 一开始我们对"什么是好的动作序列"一无所知,所以用一个很宽的高斯分布(方差 1)来采样;
  • 采样出 500 条候选序列,用模型 rollout 看看哪条序列的预期总奖励高;
  • 选出奖励最高的前 20%(精英序列),用它们的均值和方差作为下一轮迭代的采样分布;
  • 重复 5 次,分布会逐渐收敛到"看起来最好"的动作序列区域。

这比梯度优化简单得多,而且不容易陷入局部最优——因为每次都有大量采样的探索。

PETS 的实验结果

PETS 在 MuJoCo 上首次让 model-based 算法达到了和 model-free 算法(比如 SAC)同等水平的性能,但采样步数减少了 10-50 倍。这是一个里程碑式的结果——第一次证明了 model-based 方法在连续控制基准上不是"玩具",确实能用。

但是——你应该能想到——PETS 也有代价:规划时计算量非常大。每选一个动作,要做 5 轮 CEM 迭代,每轮采样 500 条序列,每条序列 rollout 10 步——这就是 5 × 500 × 10 = 25,000 次模型预测,只为了选一个动作。如果是真实机器人控制,每一步控制可能需要 20ms,这样的规划开销在部署时是很大的负担。

有没有办法既能享受到 model-based 的样本效率,又不用像 PETS 那样每一步都做昂贵的规划?这就是 MBPO 要解决的问题。

模型策略迭代

Model-Based Policy Optimization(Janner et al. 2019),简称 MBPO,它的核心创新说穿了其实就是一句话:既然长 rollout 误差累积爆炸,那我就只做很短的模型 rollout

等等,这听起来是不是太简单了?Dyna 也可以做短 rollout 啊,MBPO 的贡献在哪?关键在于 MBPO 发现了一个很反直觉的结论:rollout 长度不需要很长——只要 1-5 步就够了——就能获得几乎所有 model-based 带来的样本效率提升,同时把模型误差的影响控制在可接受范围内

短 horizon rollout

让我们回到前面那个误差累积的公式。如果 (非常接近 1,略有放大),单步误差

  • rollout 1 步:误差
  • rollout 5 步:误差约 (还很小)
  • rollout 20 步:误差约 (开始变大了)
  • rollout 100 步:误差约 (状态本身可能也就这个量级,预测已经不准了)

看明白了吗?前几步误差增长其实很慢——只有当 rollout 长到一定程度后,误差才开始指数爆炸。MBPO 的策略就是:我只吃前几步误差很小的"安全区域",在误差还没来得及累积太多的时候,就"踩刹车"——重置到真实状态,再开始下一段模型 rollout

我们来看代码理解这个流程:

python
# 短 horizon rollout 与 模型误差可控
for rollout_step in range(K_short):  # K_short = 5
    a = policy(s_sim)
    s_sim, r = model.predict(s_sim, a)
    replay_buffer.add(s_sim, a, r, s_sim)
    # 关键:每 5 步必须"重置"到真实状态
    if rollout_step % K_short == 0:
        s_sim = real_env.state

注意这里的逻辑:不是从初始状态一直 rollout 到底,而是从真实数据中的某个状态(从 replay buffer 里采样出来的、智能体实际到过的状态)开始,只 rollout 5 步,然后就停下来,再换一个真实状态继续。这样每段模型轨迹的起点都是"准确的"(来自真实环境),最多只有 5 步的误差累积——误差被严格控制在很小的范围内。

MBPO 训练流程

把这些整合起来,MBPO 的训练流程其实是一个三步循环,我们用流程图看清楚:

┌────────────────────────────────────────────┐
│ 1. 用真实数据训练模型 M                     │
│    M.predict(s, a) → s', r                  │
├────────────────────────────────────────────┤
│ 2. 用 M 生成短 rollout(5 步)              │
│    起点:真实数据中的某个 s                  │
│    每步:a = policy(s), s' = M(s, a)        │
│    结果:(s, a, r, s') × 5 加入 replay      │
├────────────────────────────────────────────┤
│ 3. 在 replay buffer(混合真假)上 SAC 更新  │
└────────────────────────────────────────────┘

这个流程非常巧妙。你看,它没有像 PETS 那样做 MPC 规划——相反,它还是像 Dyna 一样,用模型生成数据,然后用一个标准的 model-free 算法(SAC)在 replay buffer 上训练。不同的是:

  1. 模型生成的数据不是 1 步,而是 5 步短 rollout;
  2. 每段 rollout 的起点都来自真实数据;
  3. 底层用 SAC 这样稳定的 off-policy 算法做策略优化。

更妙的是,MBPO 里模型 rollout 长度 不是固定的——它可以随着训练进行动态调整。刚开始模型很不准, 设成 1(只能做 1 步预测);随着模型越来越准, 可以慢慢增加到 5 甚至更长。这就像人学东西:一开始对世界规律没把握,只能推演一步;后来理解深了,可以推演好几步。

MBPO 的实验结果非常惊人:在 MuJoCo 上达到了和 model-free SAC 同等甚至更好的性能,但采样步数减少了 10-100 倍。而且因为它最终训练的是一个 SAC 策略,部署时不需要像 PETS 那样每步做昂贵的 CEM 规划——直接跑策略网络就行,和 model-free 部署成本一样。

Model-Based RL 三大算法对比

我们把 Dyna、PETS、MBPO 这三个里程碑式的算法放在一起对比,方便你在实战中选择:

算法模型类型规划方式样本效率计算成本
Dyna确定性1 步假数据~10×
PETS概率集成CEM MPC~50×
MBPO确定性短 rollout~100×

实战选择建议:

  • 快速实验、验证想法:选 Dyna。实现简单,行为稳定,不需要处理概率模型和规划,作为 baseline 很好。
  • 高精度控制、机器人操作:选 PETS。概率集成能很好地处理模型不确定性,MPC 闭环控制非常鲁棒,适合安全关键、精度要求高的场景——但要接受规划计算成本高。
  • 通用连续控制 benchmark:选 MBPO。样本效率最高,部署和 model-free 一样快,MuJoCo 全套环境都能 work,是目前 model-based 连续控制的强基线。
加餐:为什么不用长 rollout?MBPO 的理论分析

Janner 等人在论文里给出了一个关于模型偏差如何影响策略性能的理论界。大致结论是:如果模型预测误差在某个 TV 距离(total variation distance)度量下是 ,那么在模型里学到的策略 和在真实环境里的最优策略 之间的性能差距满足:

注意分母的 项——当 接近 1(我们通常用 0.99),分母很小,这意味着即使模型误差 很小,性能差距也可能被放大很多倍。

但是——如果我们只用短 rollout,相当于把有效 horizon 缩短了,这等价于用了一个更小的有效 ,分母就不会那么小,模型误差的影响也就被控制住了。这就是 MBPO 短 rollout 的理论依据。

本节总结

Model-Based RL 通过学习环境模型 来大幅提升样本效率,我们这一节讲了三代算法的演进:

  1. Dyna 把模型作为"额外数据生成器",每次真实交互后用模型生成 N 条假数据做额外更新,样本效率提升约 N 倍——但在连续控制中会遇到误差累积问题,长 rollout 可能让预测完全失效。
  2. PETS 正视模型不确定性:用概率集成分别建模认知不确定性(集成散度)和偶然不确定性(概率输出方差),配合 CEM 采样做 MPC 规划,首次让 model-based 在 MuJoCo 上达到 model-free 同等性能——代价是每步规划计算昂贵。
  3. MBPO 用短 horizon rollout(通常 5 步)巧妙绕开误差累积问题:每段模型预测都从真实状态出发,只走几步就重置,误差还没来得及爆炸;最终还是用 SAC 训练策略,部署时没有额外计算开销,样本效率达到 model-free 的 10-100 倍。

Dyna → PETS → MBPO 这条线,我们称之为"数据增强路线"——模型的角色是生成更多数据,最终策略还是用 model-free 的方式训练。但 model-based RL 还有另一条完全不同的旗舰路线——显式搜索 + 神经网络估值。这条路线从 AlphaGo 到 AlphaZero 到 MuZero 再到 Dreamer V3,代表了 model-based RL 的理论天花板,也直接启发了 LLM 时代的 Process Reward Model 搜索。这就是下一节要讲的内容。

下一节 9.4 搜索与世界模型,我们来看看:当你不仅有模型,还能在模型里做lookahead搜索,能达到什么样的性能上限?

现代强化学习实战课程