LECTURE 02

行为的监督学习:行为克隆为什么会失败

把「学会开车」写成一个图像分类问题,只需要五分钟。但这五分钟里悄悄丢掉了监督学习最核心的 i.i.d. 假设——本讲把这个代价精确算成 $O(\epsilon H^2)$。

讲师:Sergey Levine UC Berkeley 原始材料:lec-2.pdf(39 页)

0. 本讲导读

上一讲我们讨论了「为什么要做深度强化学习」:为什么手工设计控制器在真实世界里不可扩展,为什么表示学习和决策制定必须放在同一个框架里解决。这一讲开始动真格——我们要造出本课程的第一个可运行的算法。

而这个算法出人意料地朴素:让人类演示一遍,然后用监督学习去拟合人类的动作。这就是行为克隆(behavioral cloning, BC),也叫模仿学习(imitation learning)最基础的形式。它甚至不需要奖励函数 $r(s,a)$,不需要价值函数,不需要与环境交互——一个标准的图像分类/回归训练脚本就能跑。

本讲真正的价值不在于「介绍 BC 这个算法」,而在于回答这样一串问题,它们构成了 Levine 讲课里典型的动机链条:

  • 把控制问题写成监督学习,到底丢了什么? 监督学习的一切理论保证都建立在「训练和测试数据独立同分布(i.i.d.)」上。而在控制问题里,策略自己的输出会改变它下一步看到的输入。这个反馈回路一旦存在,i.i.d. 假设就彻底失效。
  • 失效有多严重? 这是本讲的技术核心。我们会一步不漏地推出:如果策略在训练分布上犯错概率不超过 $\epsilon$,那么在长度为 $H$ 的任务上,期望犯错总数的最坏情况上界是 $O(\epsilon H^2)$ —— 注意是 $H$ 的二次方,而不是监督学习里天真预期的 $\epsilon H$。
  • 那为什么现实中 BC 又经常能用? 1989 年的 ALVINN、2016 年 NVIDIA 的端到端自动驾驶、今天的机器人 VLA 模型,全都是行为克隆。理论说不行,实践说行,矛盾在哪?答案藏在「数据是怎么收集的」里。
  • 怎么从根上修好它? DAgger(Dataset Aggregation) 的核心思想只有一句话:既然是 $p_{\text{data}}$ 和 $p_{\pi_\theta}$ 对不上,与其想办法让策略去迁就数据,不如让数据去迁就策略。

与后续课程的关系:下一讲会继续深挖模仿学习——DAgger 的工程变体、非马尔可夫策略(历史信息)带来的因果混淆(causal confusion)、以及人类演示天然的多模态性该怎么用扩散策略(diffusion policy)、动作分块(action chunking)之类的手段建模。再往后进入真正的强化学习时,你会发现本讲的分布漂移分析像幽灵一样反复出现:off-policy 修正、TRPO 的信任域、offline RL 的分布外动作,本质上都是同一个 $p_{\text{train}} \neq p_{\text{test}}$ 的问题在不同场景下的变形。

核心结论
  • BC 就是在演示数据上做最大似然:$\displaystyle\max_\theta \sum_{i}\sum_{t}\log \pi_\theta(a_t^{(i)}|o_t^{(i)})$。它是监督学习,不是强化学习。
  • 控制问题打破了 i.i.d. 假设:策略的动作决定了它将来会遇到什么状态,因此误差会累积、会自我放大,而不是像监督学习那样独立地平均掉。
  • 最坏情况下期望犯错次数是 $O(\epsilon H^2)$;直觉是「每一步都可能第一次跌出数据分布,一旦跌出去,剩下的 $H-t$ 步全废」,$\sum_t (H-t) \sim H^2/2$。
  • $O(\epsilon H^2)$ 是最坏情况界,现实中往往没这么糟,因为真实系统通常可以从错误中恢复。但——「能恢复」不等于「BC 学得会恢复」,除非数据里就有恢复行为。
  • 由此产生一个反直觉的悖论:演示数据里含有更多(小)错误和纠正,BC 的效果反而更好。完美无瑕的专家演示是糟糕的 BC 数据。
  • NVIDIA 端到端驾驶能成功的关键不是网络,而是左中右三摄像头 + 人工修正转向角——这是在用数据增强人为合成「偏离车道后如何回正」的样本。
  • DAgger 通过「跑策略 → 让专家给策略访问到的状态打标签 → 聚合进数据集 → 重训」的循环,使 $p_{\text{data}} \to p_{\pi_\theta}$,把误差界从 $O(\epsilon H^2)$ 降到 $O(\epsilon H)$。它的代价是需要一个随叫随到的交互式专家。

1. 记号:从 $p_\theta(y|x)$ 到 $\pi_\theta(a_t|o_t)$

先从一件你已经会的事情开始。给定一张车载前视摄像头拍到的图片 $\mathbf{x}$,我们想输出图中物体的类别 $y$(比如「car」)。标准做法是训练一个神经网络输出条件分布 $p_\theta(y|\mathbf{x})$,然后在带标注的数据集 $\{(\mathbf{x}^{(i)}, y^{(i)})\}_{i=1}^{N}$ 上做最大似然估计(maximum likelihood estimation, MLE):

$$ \theta^\star = \argmax_\theta \sum_{i=1}^{N} \log p_\theta(y^{(i)}|\mathbf{x}^{(i)}) $$

这就是监督学习。交叉熵损失、Adam、数据增强、早停——整套工具链你都熟悉。

监督学习:从图像 x 经过神经网络得到标签 y 的条件分布,在数据集上做最大似然
标准监督学习的三件套:输入 $\mathbf{x}$(一张前视图像)、参数为 $\theta$ 的神经网络输出条件分布 $p_\theta(y|\mathbf{x})$、输出 $y$(这里是「car」的检测框)。下方的圆柱代表带标注数据集 $\{(\mathbf{x}^{(i)},y^{(i)})\}_{i=1}^N$,箭头指向的目标函数就是最大似然。整张图之后会被原封不动地「改标签」变成模仿学习——这正是 Levine 想让你注意到的:从形式上看,两者一模一样。

1.1 只改标签,不改结构

现在把这张图上的符号换掉,什么都不改:让输出 $y$ 不再是物体类别,而是此刻应该打多少方向盘、踩多深油门。于是同一个网络就成了一个「驾驶员」。

把监督学习的记号换成控制记号:观测 o_t、动作 a_t、策略 π_θ(a_t|o_t),下方标出底层状态 s_t
换记号之后:输入叫观测(observation)$\mathbf{o}_t$,输出叫动作(action)$\mathbf{a}_t$,中间的网络叫策略(policy)$\pi_\theta(\mathbf{a}_t|\mathbf{o}_t)$。下标 $t$ 提示我们这是一个时间序列上的决策,不是孤立的一次预测。图最下方额外画出了状态 $\mathbf{s}_t$:一个包含所有车辆位置、速度的向量;观测 $\mathbf{o}_t$ 只是从这个状态渲染出来的一张图片(注意图中那辆被前车挡住的白色小车——它在 $\mathbf{s}_t$ 里有条目,在 $\mathbf{o}_t$ 里却看不见)。

本课程通用的记号,从这里开始固定下来:

符号名称含义
$\mathbf{s}_t$状态(state)系统在 $t$ 时刻的完整物理描述,满足马尔可夫性
$\mathbf{o}_t$观测(observation)智能体实际看到的东西,由 $\mathbf{s}_t$ 生成,可能不足以还原 $\mathbf{s}_t$
$\mathbf{a}_t$动作(action)$t$ 时刻输出的控制量,离散或连续
$\pi_\theta(\mathbf{a}_t|\mathbf{o}_t)$策略(policy)参数为 $\theta$ 的条件动作分布;完全可观测时写作 $\pi_\theta(\mathbf{a}_t|\mathbf{s}_t)$
$p(\mathbf{s}_{t+1}|\mathbf{s}_t,\mathbf{a}_t)$转移概率(dynamics)环境的动力学,模仿学习中不需要知道
$p(\mathbf{o}_t|\mathbf{s}_t)$观测模型状态如何生成观测,同样不需要知道
$\tau$轨迹(trajectory)$(\mathbf{o}_1,\mathbf{a}_1,\ldots,\mathbf{o}_H,\mathbf{a}_H)$,$H$ 是时域(horizon)
$\pi^\star$专家策略产生演示数据的那个(通常是人类)策略
$r(\mathbf{s},\mathbf{a}),\gamma,Q^\pi,V^\pi$奖励、折扣、值函数本讲用不到——BC 的迷人之处正在于此

1.2 状态与观测:马尔可夫性到底在说什么

$\mathbf{s}$ 和 $\mathbf{o}$ 的区别是本课程反复踩坑的地方,必须一次讲清。

图模型:s_1→s_2→s_3→s_4 的状态链,每个 s 生成 o,每个 o 经策略生成 a,并标注马尔可夫性
控制问题的图模型。底下一行是状态链 $\mathbf{s}_1 \to \mathbf{s}_2 \to \mathbf{s}_3 \to \mathbf{s}_4$,边上标着转移概率 $p(\mathbf{s}_{t+1}|\mathbf{s}_t,\mathbf{a}_t)$;每个状态通过 $p(\mathbf{o}_t|\mathbf{s}_t)$ 向上生成观测;每个观测通过策略 $\pi_\theta(\mathbf{a}_t|\mathbf{o}_t)$ 生成动作;动作又斜向下影响下一个状态。粗箭头指出的关键性质写在下面:马尔可夫性 $\mathbf{s}_{t+1} \perp \mathbf{s}_{t-1} \mid \mathbf{s}_t$。

马尔可夫性(Markov property)说的是:给定当前状态 $\mathbf{s}_t$,未来 $\mathbf{s}_{t+1}$ 与过去 $\mathbf{s}_{t-1}$ 条件独立。用大白话讲:知道了现在,过去就再也提供不了任何额外信息。这是「状态」这个词的定义性质——如果一个量不满足它,它就不配叫状态。

而观测没有这个性质。看图里那辆被卡车挡住的小汽车:在 $\mathbf{s}_t$ 里它的坐标和速度都在,但 $\mathbf{o}_t$(一张图片)里它被完全遮挡了。此刻如果你只看 $\mathbf{o}_t$,你会以为右车道是空的;但如果你还记得 $\mathbf{o}_{t-1}$——那时它还没被挡住——你就知道那儿有辆车。过去的观测对预测未来是有用的,所以观测不满足马尔可夫性。

注意

这一条有个非常实际的推论:如果策略只吃单帧观测 $\pi_\theta(\mathbf{a}_t|\mathbf{o}_t)$,那么在部分可观测的环境里,最优策略可能根本不在这个函数类里——不管你的网络多大、数据多多,你都学不到最优。想要理论上的最优性,要么保证 $\mathbf{o}_t = \mathbf{s}_t$(完全可观测),要么让策略吃整段历史 $\pi_\theta(\mathbf{a}_t|\mathbf{o}_{1:t})$。后者会带来自己的麻烦(因果混淆),下一讲细说。

部分可观测 vs 完全可观测两种图模型的对比,以及各自需要建模的分布
上半:部分可观测(partially observed)情形,策略是 $\pi_\theta(\mathbf{a}_t|\mathbf{o}_t)$,此外还有 $p(\mathbf{o}_t|\mathbf{s}_t)$ 和 $p(\mathbf{s}_{t+1}|\mathbf{s}_t,\mathbf{a}_t)$ 两个分布——右侧的大括号标注「typically don't need to know this」,即模仿学习(乃至绝大部分 model-free RL)完全不需要知道它们,它们只在幕后决定数据长什么样。下半:完全可观测(fully observed)情形,$\mathbf{o}_t = \mathbf{s}_t$,图模型塌缩成一条 $\mathbf{s}$ 链,策略写作 $\pi_\theta(\mathbf{a}_t|\mathbf{s}_t)$。本讲第 5 节的理论分析都在这个更简单的设定下做。

1.3 演示数据与行为克隆的目标函数

数据从哪来?让一个人去开车,把他每一时刻看到的画面和他打的方向盘都记录下来。一次完整的记录叫一条演示轨迹(demonstration trajectory),数据集就是 $N$ 条这样的轨迹:

$$ \mathcal{D} = \Big\{ \big(\mathbf{o}_1^{(i)}, \mathbf{a}_1^{(i)}, \ldots, \mathbf{o}_H^{(i)}, \mathbf{a}_H^{(i)}\big) \Big\}_{i=1}^{N} $$

然后——把它当成一堆 $(\mathbf{o},\mathbf{a})$ 的散装样本对,忘掉它们的时间顺序,直接跑最大似然:

$$ \theta^\star = \argmax_\theta \sum_{i=1}^{N} \sum_{t=1}^{H} \log \pi_\theta\big(\mathbf{a}_t^{(i)} \big| \mathbf{o}_t^{(i)}\big) $$

这个式子就是行为克隆。请仔细体会「忘掉时间顺序」这五个字——它是本讲后面所有麻烦的源头。我们把一个序贯决策问题当成了 $N \times H$ 个互不相干的分类/回归问题来处理,等于默认了这些样本是 i.i.d. 的。它们当然不是。

演示轨迹数据集与行为克隆的最大似然目标函数
把前面的监督学习图完全套用到控制上:左下角是数据(演示轨迹),右下角是目标函数(行为克隆)。与第一张图对比,你会发现唯一的变化是把 $\sum_i$ 变成了 $\sum_i \sum_t$——多出来的这个对时间的求和,看上去只是「样本更多了」,实际上偷偷取消了 i.i.d. 假设。
常见误区

「BC 是强化学习的一种」——不是。BC 里没有奖励函数,没有探索,没有与环境的交互,也没有任何时序信用分配(credit assignment)。它是百分之百的监督学习,只不过被应用在了一个监督学习假设不成立的场景上。之所以把它放在深度 RL 课的第二讲,恰恰是为了让你看清:不做 RL 的代价是什么。

2. 行为克隆算法:完整的两步

算法本身简单到可以写在一张便签上:

行为克隆算法
  1. 收集数据:请一个人(或任何已有的好控制器)来做演示,记录 $\mathcal{D} = \{(\mathbf{o}_1^{(i)}, \mathbf{a}_1^{(i)}, \ldots, \mathbf{o}_H^{(i)}, \mathbf{a}_H^{(i)})\}_{i=1}^{N}$。
  2. 跑监督学习:用你最喜欢的神经网络,在这些数据上最大化 $\sum_{i}\sum_{t}\log \pi_\theta(\mathbf{a}_t^{(i)}|\mathbf{o}_t^{(i)})$。
行为克隆的两步流程,以及从观测经编码器得到动作分布参数再采样的网络结构
上半是算法两步,右上角红框圈出的就是全部的训练目标——注意它和普通分类任务的交叉熵损失在代码层面没有任何区别。下半是网络结构:观测 $\mathbf{o}_t$(图像)先过一个编码器(encoder)(ViT、ResNet 之类),输出动作分布的参数,再从这个分布里采样得到实际执行的动作 $\mathbf{a}_t$。请注意策略输出的是分布而不是单个动作——这个设计在处理人类演示的多模态性时至关重要。

2.1 历史插曲:1989 年的 ALVINN

这个想法一点都不新。1989 年,CMU 的 Dean Pomerleau 做了 ALVINN(Autonomous Land Vehicle In a Neural Network):一个只有 5 个隐藏单元、输入是 $30\times 32$ 灰度「视网膜」、输出 30 个转向方向单元的全连接网络,装在一辆改装军用卡车上,学人类司机开车。

ALVINN 1989:改装卡车、网络结构图(30x32 输入、5 个隐藏单元、30 个输出)、人类演示驾驶的照片
ALVINN 的网络结构(中)在今天看来小得可笑:$30 \times 32 = 960$ 个输入像素、5 个隐藏单元、30 个输出单元,一共不到 5000 个参数。但它的结构与今天最先进的机器人 VLA 模型完全同构:图像进 → 编码 → 动作出,端到端监督训练。中间隔着的 35 年改变的是模型容量和数据规模,不是范式。

Levine 讲这段历史是有目的的:让你意识到 BC 的问题不是「模型不够大」。同样的范式在 5000 参数和 50 亿参数上都能跑,也都会遭遇同一个结构性缺陷。这个缺陷不在模型里,在问题的设定里。

2.2 动作分布怎么参数化

「输出一个分布」在具体实现上分两种情况。

离散动作用 softmax 输出 logits,连续动作用高斯分布输出均值和协方差
上半是通用结构(编码器 → 分布参数 → 采样)。下半分两路:离散动作(LLM 的 token、Atari 的按键)时网络输出 $A$ 个 logits $f_1(\mathbf{o}_t),\ldots,f_A(\mathbf{o}_t)$,再经 softmax 归一化;连续动作(方向盘转角)时网络输出高斯分布的参数 $\mu(\mathbf{o}_t)$ 和 $\Sigma(\mathbf{o}_t)$。黄色提示框说:更复杂的动作分布表示方法(混合高斯、隐变量模型、扩散模型、自回归离散化)以后会专门讲。

离散动作。网络输出 $A$ 维 logits 向量,用 softmax 转成概率:

$$ p(a_t = j \mid \mathbf{o}_t) = \frac{\exp\big(f_j(\mathbf{o}_t)\big)}{\sum_{i=1}^{A} \exp\big(f_i(\mathbf{o}_t)\big)} $$

取对数似然就是标准的交叉熵损失。这跟做图像分类一模一样。顺便说一句:大语言模型的下一 token 预测,形式上就是一个离散动作空间上的行为克隆——观测是上文,动作是下一个 token,演示数据是人类写的文本。这个类比在本课后面讲 RLHF 时会再次出现。

连续动作。最简单的做法是输出一个多元高斯的参数:

$$ p(\mathbf{a}_t|\mathbf{o}_t) = \mathcal{N}\big(\mathbf{a}_t \,;\, \mu(\mathbf{o}_t), \Sigma(\mathbf{o}_t)\big) $$

在 $\Sigma(\mathbf{o}_t) = \mathbf{I}$ 的特殊情况下,负对数似然退化为

$$ -\log p(\mathbf{a}_t|\mathbf{o}_t) = \tfrac{1}{2}\big\|\mathbf{a}_t - \mu(\mathbf{o}_t)\big\|^2 + \text{const} $$

也就是普通的均方误差回归。这解释了为什么很多 BC 实现直接就是 MSE loss——它是「固定单位方差高斯 + 最大似然」的等价形式。

直觉

为什么非要输出分布,不能直接回归一个动作?两个理由。其一,训练目标的统一性:MLE 框架下离散和连续可以用同一套语言描述,后面接策略梯度时也能无缝衔接。其二,也是更重要的,人类演示天然是多模态的:面对路中间一棵树,绕左边和绕右边都对,MSE 回归会输出两者的平均值——直直撞上去。单峰高斯其实也躲不开这个问题(它的均值同样是平均值),所以才需要更强的分布族。这是下一讲的主线之一。

2.3 一份能跑的最小实现

下面是完整的 BC 训练循环(PyTorch),连续动作用对角高斯,离散动作只需把最后两行换成交叉熵。

import torch, torch.nn as nn

class GaussianPolicy(nn.Module):
    """pi_theta(a|o):观测 -> 对角高斯的 (mu, log_std)。"""
    def __init__(self, obs_dim, act_dim, hidden=256):
        super().__init__()
        self.trunk = nn.Sequential(
            nn.Linear(obs_dim, hidden), nn.ReLU(),
            nn.Linear(hidden, hidden), nn.ReLU(),
        )
        self.mu_head = nn.Linear(hidden, act_dim)
        # log_std 与观测无关(state-independent),是最常用的简化
        self.log_std = nn.Parameter(torch.zeros(act_dim))

    def dist(self, obs):
        h = self.trunk(obs)
        mu = self.mu_head(h)
        std = self.log_std.clamp(-5.0, 2.0).exp()
        return torch.distributions.Normal(mu, std)

    def log_prob(self, obs, act):
        # 各维度独立,log p(a|o) = sum_j log p(a_j|o)
        return self.dist(obs).log_prob(act).sum(dim=-1)

    @torch.no_grad()
    def act(self, obs, deterministic=False):
        d = self.dist(obs)
        return d.mean if deterministic else d.sample()


def behavior_cloning(obs_all, act_all, obs_dim, act_dim,
                     epochs=50, batch_size=256, lr=1e-3):
    """obs_all: (N*H, obs_dim)  act_all: (N*H, act_dim)
    注意这里把所有轨迹的所有时间步「打散」成了一个大池子,
    并且每个 epoch 都随机打乱 —— 这正是在假装样本是 i.i.d. 的。"""
    policy = GaussianPolicy(obs_dim, act_dim)
    opt = torch.optim.Adam(policy.parameters(), lr=lr)
    n = obs_all.shape[0]
    for ep in range(epochs):
        perm = torch.randperm(n)
        total = 0.0
        for i in range(0, n, batch_size):
            idx = perm[i:i + batch_size]
            o, a = obs_all[idx], act_all[idx]
            loss = -policy.log_prob(o, a).mean()   # 负对数似然
            opt.zero_grad(); loss.backward(); opt.step()
            total += loss.item() * len(idx)
        print(f"epoch {ep:3d}  NLL = {total / n:.4f}")
    return policy

请特别留意 behavior_cloning 里那句 torch.randperm(n)。它把所有轨迹、所有时间步的数据彻底打散重排——这是监督学习的标准操作,也正是我们主动抹掉时序结构、假装数据 i.i.d. 的那一行代码。整个第 4、5 节要付的账,就是从这里欠下的。

3. 它到底行不行?

3.1 不行

拿一个理想化的实验来看:训练数据是一条黑色轨迹,我们在上面做 BC,然后把学到的策略放回环境里跑,画出它的期望轨迹(红色)。

训练轨迹(黑)与 BC 策略实际执行的期望轨迹(红)在三维图上逐渐分离
横轴是时间,纵轴(斜向那根)是状态 $\mathbf{s}$。黑线是训练用的演示轨迹,红线是学到的策略实际跑出来的期望轨迹。开始时两者几乎重合,因为初始状态在数据分布里;但每一步的微小误差都把红线推离黑线一点点,而推离之后策略进入了它没见过的状态,误差反而更大,于是偏差越滚越大,最后红线彻底飞走。这张图是整个第 4、5 节的直观来源,Levine 在讲义里反复回到它。

注意这张图里失败的模式:不是随机抖动,是单向发散。这跟监督学习中「测试误差比训练误差高一点」的图景完全不同。误差在这里不是被平均掉,而是被积分起来。

3.2 行

然后 Levine 立刻放了 2016 年 NVIDIA 的演示视频:一辆车在锥桶阵里稳稳地开,用的正是纯粹的端到端行为克隆(Bojarski 等人)。这构成了一个必须解释的矛盾。

NVIDIA 端到端自动驾驶演示:一辆车在锥桶阵中自主行驶
NVIDIA 的 end-to-end 驾驶系统:单目摄像头输入,CNN 直接输出转向指令,没有任何显式的车道检测、路径规划或控制器。训练数据就是人类司机开车的录像。它确实能开,而且能连续开几十公里。所以问题不是「BC 行不行」,而是「BC 在什么条件下行」。

3.3 为什么那个能行?

答案不在网络结构里,在数据采集装置里。

NVIDIA 的训练流程图:左中右三个摄像头 + 随机平移旋转 + 转向角修正,以及车顶视角的三摄像头示意
NVIDIA 论文的训练流程图。关键在最左边:车上装了三个摄像头(left / center / right)。中央摄像头的图像配上人类真实的方向盘角度;左侧摄像头的图像被配上「稍微右打一点」的方向盘角度,右侧摄像头配上「稍微左打一点」——这就是绿色框 "Adjust for shift and rotation" 在做的事。此外还有 "Random shift and rotation" 做进一步的图像级数据增强。下方的示意图画得更直白:一辆车,三个视锥,三个箭头分别指向左偏、直行、右偏对应的修正方向。
核心结论

三摄像头技巧的本质,是用极低的成本人工合成了「偏离中心线之后如何回正」的训练样本。人类司机开得很好,所以真实数据里几乎没有「车快压线了」的状态;而左右摄像头恰恰模拟了车横向偏移之后的视角,配上的修正转向角则给出了正确的纠偏动作。换句话说:他们没有改算法,他们改了数据分布,把策略执行时可能遇到的「偏离态」提前塞进了训练集。这与本讲后面 DAgger 的思想完全一致,只是用一种廉价的、离线的方式近似实现。

顺着这条线,可以给出一份「让 BC 变得可用」的想法清单(第 8 节会逐条展开):

本讲的要点总结:BC 不保证有效、原因是 i.i.d. 假设不成立、以及四类应对办法
Levine 的中场总结,也是本讲的路线图:(1) 通过行为克隆做模仿学习没有任何有效性保证;(2) 这跟监督学习不一样,原因是 i.i.d. 假设不成立;(3) 我们可以把「为什么」形式化,做一点理论;(4) 应对办法有四类——改算法(DAgger)、用强到几乎不犯错的大模型、聪明地采集与增强数据、以及用多任务学习。右侧的配图分别对应发散轨迹图、走钢丝(最坏情况)、三摄像头、RT-1 这类大模型、以及多目标导航。

4. 分布漂移:问题的名字

先给这个现象一个准确的名字。

分布漂移的定义:训练时 x 服从 p_train,测试时服从 p_test,两者不等;配图是各国不同样式的出口标志
分布漂移(distributional shift)的一般定义:我们在 $\mathbf{x} \sim p_{\text{train}}(\mathbf{x})$ 上训练 $p_\theta(y|\mathbf{x})$,却在 $\mathbf{x} \sim p_{\text{test}}(\mathbf{x})$ 上测试它,而 $p_{\text{test}}(\mathbf{x}) \neq p_{\text{train}}(\mathbf{x})$。右侧的配图是各种「出口 / EXIT」标志:绿底白字、红底白字、中文的「出站」、日文的「非出口」——如果你的训练集只有美式红色 EXIT 灯箱,遇到中文标牌时模型的行为完全不可预测。底部那句话是这一讲最好的类比:「想象你复习了一学期数学,考场上发到手的却是一张古希腊文学试卷。」

分布漂移在监督学习里也存在(跨域泛化、OOD 检测都在处理它),但那里它是一个外生的、偶然的麻烦:数据集收得不好、部署环境变了。而在控制问题里,它是内生的、必然的——

核心结论

行为克隆的分布漂移是策略自己造成的。训练分布 $p_{\text{data}}(\mathbf{o}_t)$ 是由专家 $\pi^\star$ 与环境交互产生的状态分布;测试分布 $p_{\pi_\theta}(\mathbf{o}_t)$ 是由学到的策略 $\pi_\theta$ 与环境交互产生的状态分布。只要 $\pi_\theta \neq \pi^\star$(永远如此),这两个分布就必然不同。你无法通过「多收集点数据」来消除它,因为问题不在数据的量,而在数据的生成机制。

BC 下的分布漂移:黑线标注 p_data(o_t),红线标注 p_πθ(o_t),左下写训练目标,右下写测试分布不等于训练分布
把发散轨迹图和分布漂移的定义合并起来看。黑线是 $p_{\text{data}}(\mathbf{o}_t)$,红线是 $p_{\pi_\theta}(\mathbf{o}_t)$。左下角是我们实际优化的目标:$\max_\theta \E_{\mathbf{o}_t \sim p_{\text{data}}(\mathbf{o}_t)}[\log \pi_\theta(\mathbf{a}_t|\mathbf{o}_t)]$;右下角是我们真正关心的测试条件:策略在 $p_{\pi_\theta}(\mathbf{o}_t)$ 下的表现。这两个期望的下标不一样,这就是全部问题所在。

写成一行:我们优化的是

$$ \max_\theta\ \E_{\mathbf{o}_t \sim p_{\text{data}}(\mathbf{o}_t)}\big[\log \pi_\theta(\mathbf{a}_t|\mathbf{o}_t)\big] \qquad\text{但我们想要的是在}\ p_{\pi_\theta}(\mathbf{o}_t)\ \text{下表现好} $$

而且 $p_{\text{data}}(\mathbf{o}_t) \neq p_{\pi_\theta}(\mathbf{o}_t)$。更糟的是,$p_{\pi_\theta}$ 依赖于 $\theta$,所以每次你更新参数,测试分布就跟着变——这是一个移动的靶子。

直觉:一个具体的失败故事

你训练一个开车策略。人类司机永远把车开在车道正中,所以数据里 99.9% 的画面都是「车在正中」。你的策略学得很好,在训练分布上犯错率只有 0.1%。上路后第 37 帧,它多打了 0.5 度方向盘,车偏离中线 5 厘米。这个「偏离 5 厘米」的画面在训练集里一次都没出现过,网络在这个输入上的输出没有任何保证——假设它又多打了 1 度。现在偏离 15 厘米,这个画面离训练分布更远了……第 200 帧的时候车已经在对向车道上,而这个画面对网络来说完全是「古希腊文学试卷」。

车内视角:车轻微偏左后,绿色箭头表示正确的纠偏方向,粉色/黄色箭头表示错误的动作
这张车内视角图是理解后面理论的钥匙。车已经稍微偏离了道路中心,此时正确的动作(绿色箭头)是往回打;但因为专家从来没偏离过,训练数据里没有这个状态,策略给出的可能是粉色或黄色箭头那样的错误动作,让偏差继续扩大。「犯了一个错」和「进入了一个没见过的状态」在控制问题里是同一件事——这正是误差累积的机制。

5. 到底能有多糟:$O(\epsilon H^2)$ 的完整推导

这一节是本讲的技术核心。我们要把上面的直觉变成一个定量的、可以讨论的界。

5.1 先说清楚理论能给什么、不能给什么

我们想知道的三个问题,以及理论能给和不能给的东西
我们想知道三件事:(1) 模仿学习是不是真的比监督学习更糟?(2) 数据变多,问题会自己消失吗?(3) 是不是某些控制问题上会格外糟?下方是 Levine 对理论作用的诚实评价——理论能给的:对各种权衡(数据量、时域长度)的直觉,以及「最坏能坏到什么程度」;理论不能给的:一个实用的「它一定行/一定不行」的证明,也无法刻画典型行为。

请把这段话记牢。下面推出的 $O(\epsilon H^2)$ 是最坏情况上界,不是对现实的预测。它的价值在于告诉你「误差随时域二次增长」这个标度关系,以及问题的结构性来源。第 6 节会专门讨论它有多悲观。

5.2 设定:代价函数与犯错概率

为简单起见,全部在完全可观测设定下讨论($\mathbf{o}_t = \mathbf{s}_t$)。假设数据由一个好策略 $\pi^\star(\mathbf{s}_t)$ 产生,它是确定性的:在状态 $\mathbf{s}$ 上,正确动作就是 $\pi^\star(\mathbf{s})$。定义 0-1 代价:

$$ c(\mathbf{s}_t,\mathbf{a}_t) = \begin{cases} 0 & \text{if } \mathbf{a}_t = \pi^\star(\mathbf{s}_t) \\ 1 & \text{otherwise} \end{cases} $$

也就是说:每犯一次错,付出 1 单位代价。这是一个很粗糙的代价函数(它认为「稍微打偏一点」和「一头撞上去」一样糟),但正因为粗糙,它给出的界才是最坏情况的界。

0-1 代价函数的定义,以及在策略下取期望后等于犯错概率
代价函数的定义(左)与它在策略下的期望(下)。关键的一步是右下角:对 $\mathbf{a}_t \sim \pi_\theta(\mathbf{a}_t|\mathbf{s}_t)$ 取期望,得到 $\sum_{\mathbf{a}_t}\pi_\theta(\mathbf{a}_t|\mathbf{s}_t)c(\mathbf{s}_t,\mathbf{a}_t) = \pi_\theta\big(\mathbf{a}_t \neq \pi^\star(\mathbf{s}_t)\big|\mathbf{s}_t\big)$——因为 $c$ 是 0-1 的,求和只留下所有「错误动作」的概率之和,也就是「在状态 $\mathbf{s}_t$ 上犯错的概率」。这个恒等式是后面所有推导的基本砖块。

把这一步写全:

$$ \E_{\mathbf{a}_t \sim \pi_\theta(\mathbf{a}_t|\mathbf{s}_t)}\big[c(\mathbf{s}_t,\mathbf{a}_t)\big] = \sum_{\mathbf{a}_t} \pi_\theta(\mathbf{a}_t|\mathbf{s}_t)\, c(\mathbf{s}_t,\mathbf{a}_t) = \sum_{\mathbf{a}_t \neq \pi^\star(\mathbf{s}_t)} \pi_\theta(\mathbf{a}_t|\mathbf{s}_t) = \pi_\theta\big(\mathbf{a}_t \neq \pi^\star(\mathbf{s}_t) \,\big|\, \mathbf{s}_t\big) $$

5.3 我们要界定的量:期望犯错总数

整条轨迹上的总代价,就是把每个时刻的期望代价加起来。注意状态要从策略自己诱导的分布 $p_{\pi_\theta}(\mathbf{s}_t)$ 里采:

$$ J(\pi_\theta) \;=\; \sum_{t=1}^{H} \E_{\mathbf{s}_t \sim p_{\pi_\theta}(\mathbf{s}_t),\ \mathbf{a}_t \sim \pi_\theta(\mathbf{a}_t|\mathbf{s}_t)}\big[c(\mathbf{s}_t,\mathbf{a}_t)\big] $$
期望总代价的求和式,标注状态分布依赖于过去的动作;右侧画出策略状态分布随时间不断变宽
左侧是期望犯错总数的定义式,箭头特别提醒:状态分布 $p_{\pi_\theta}(\mathbf{s}_t)$ 依赖于过去所有的动作——这就是 i.i.d. 假设失效的数学形式。黄色框指出这个求和就是「期望犯错总次数」。右侧的图非常关键:随着时间推移,红色椭圆(策略诱导的状态分布 $p_{\pi_\theta}(\mathbf{s}_1), p_{\pi_\theta}(\mathbf{s}_{10}), p_{\pi_\theta}(\mathbf{s}_{25}),\ldots$)不断变宽、并偏离黑色的训练轨迹。下方的问题就是本节要回答的:犯错总数随时域 $H$ 如何标度?
常见误区

「训练误差 $\epsilon$,跑 $H$ 步,那期望犯错就是 $\epsilon H$ 呗。」——这个推理默认了每一步的状态都还在训练分布里。而事实是:第一次犯错就把你踢出了训练分布,从那以后 $\epsilon$ 这个数字对你不再有任何约束力。下面的推导就是在算这个「踢出去」的代价。

5.4 第一版:最坏情况的直观论证

先做一个更强、更不现实的假设,好把直觉建立起来:

$$ \pi_\theta\big(\mathbf{a} \neq \pi^\star(\mathbf{s}) \,\big|\, \mathbf{s}\big) \le \epsilon \qquad \text{对所有 } \mathbf{s} \in \mathcal{D}_{\text{train}} $$

注意这里是「对训练集里的每一个状态,犯错概率都不超过 $\epsilon$」,这比「平均犯错概率不超过 $\epsilon$」强得多。即便如此,结论仍然很糟。

最坏情况:走钢丝的人,以及一条被红色(掉下去)包围的窄通道网格;求和式给出 εH 后接 H 项每项 O(εH) 得到 O(εH²)
最坏情况的两个图示。走钢丝的人:只要偏离一步就掉下去,再也回不来。右边的网格世界更精确:中间一行绿色箭头是唯一的正确通道,上下全是红色的「死亡格」——只要走错一步,你就永远离开了训练分布,剩下的所有步都会犯错。下方的推导:第 $t$ 步的期望代价上界是 $O(\epsilon H)$ 级别,一共 $H$ 项,所以总和是 $O(\epsilon H^2)$。

逐步展开这个论证。考虑第 $t$ 步:

  • 如果前 $t-1$ 步一次都没犯错(概率至少 $(1-\epsilon)^{t-1}$),那么此刻你还在训练分布上,第 $t$ 步的犯错概率 $\le \epsilon$,而且往后的每一步依然受 $\epsilon$ 约束。
  • 如果犯过至少一次错(概率 $\le 1-(1-\epsilon)^{t-1}$),你已经不在训练分布里了,最坏情况下剩下的每一步都犯错,代价为 1。

于是,「第一次犯错发生在第 $t$ 步」这个事件的概率大约是 $\epsilon$(乘上前面都没错的概率,$\le\epsilon$),而一旦在第 $t$ 步首次犯错,后续 $H-t$ 步全部作废,贡献代价 $H-t$。把所有可能的首错时刻加起来:

$$ \E[\text{总犯错数}] \;\lesssim\; \sum_{t=1}^{H} \epsilon \cdot (H - t) \;=\; \epsilon \cdot \frac{H(H-1)}{2} \;=\; O(\epsilon H^2) $$

这就是幻灯片上「$H$ 个项,每项 $O(\epsilon H)$,合计 $O(\epsilon H^2)$」的含义。

直觉:为什么是平方

两个 $H$ 来自两个不同的地方,把它们分开看就不神秘了。第一个 $H$:轨迹有 $H$ 步,每一步都是一次「可能第一次跌出分布」的机会。第二个 $H$:每一次跌出去,损失的不是 1 步,而是剩余的所有步,平均是 $H/2$ 步。机会数 $\times$ 每次机会的损失 $=H \times H/2$,再乘上每次跌出去的概率 $\epsilon$,就是 $\epsilon H^2/2$。
对比监督学习:那里也有 $H$ 个样本,每个样本犯错代价是 1,所以是 $\epsilon H$。差别只在于「一次错误的后果会不会波及未来」。

5.5 一个具体数值:为什么 99.9% 的准确率救不了你

假设你训练出一个非常好的驾驶策略,在训练分布上每一步的犯错概率只有 $\epsilon = 10^{-3}$(千分之一,按 10 Hz 控制频率算,相当于平均每 100 秒才失误一次,听起来相当靠谱)。

时域 $H$(步)监督学习式预期 $\epsilon H$最坏情况界 $\epsilon H^2/2$解读
10(1 秒)0.010.05几乎察觉不到差别
100(10 秒)0.15已经差 50 倍
1000(100 秒)1500界已经超过 $H$ 的一半,完全失去意义
10000(约 17 分钟)10$5\times 10^4$(截断为 $H$)界饱和:等价于「几乎每一步都错」

这张表说明三件事。第一,短时域任务上 BC 很好用——这解释了为什么「抓取一个物体」这类几秒钟的任务用 BC 效果不错。第二,长时域任务上界迅速退化到平凡(犯错数不可能超过 $H$,所以界一旦超过 $H$ 就没信息量了)。第三,也是最重要的:要想在 $H$ 变大时保持性能,$\epsilon$ 必须以 $1/H^2$ 的速度下降,而泛化误差通常只能随数据量 $N$ 以 $O(1/\sqrt{N})$ 或 $O(1/N)$ 下降。这就回答了幻灯片上的第二个问题:问题不会随着数据变多而自动消失,只会变得更贵。

6. 更一般的分析:用总变差距离做完整证明

上一节的假设「对训练集里每一个状态犯错概率都 $\le\epsilon$」太强了:真实的监督学习只能保证平均误差小。这一节把假设换成更弱、更现实的版本,重新做一遍推导——结论仍然是 $O(\epsilon H^2)$,而且这次是严格的。

6.1 更弱的假设

$$ \E_{\mathbf{s}_t \sim p_{\text{train}}(\mathbf{s}_t)}\Big[\pi_\theta\big(\mathbf{a}_t \neq \pi^\star(\mathbf{s}_t)\big|\mathbf{s}_t\big)\Big] \;\le\; \epsilon $$

用话说:「如果我们从训练分布里采一个状态,策略不太可能犯错。」这正是监督学习的泛化保证所能给出的东西——它对个别的、罕见的困难状态不作任何承诺。

6.2 一个有用的分解

核心技巧是把策略诱导的状态分布 $p_{\pi_\theta}(\mathbf{s}_t)$ 按「到 $t$ 时刻为止有没有犯过错」分成两块:

$$ p_{\pi_\theta}(\mathbf{s}_t) \;=\; \underbrace{(1-\epsilon)^t}_{\text{一次都没犯错的概率}} p_{\text{train}}(\mathbf{s}_t) \;+\; \underbrace{\big(1-(1-\epsilon)^t\big)}_{\text{至少犯过一次错}} p_{\text{mistake}}(\mathbf{s}_t) $$
更弱的假设(训练分布下的期望犯错率不超过 ε),以及状态分布按是否犯过错的二分分解
上半是弱化后的假设,下面那句话是它的口语翻译。下半是关键的分解式:$(1-\epsilon)^t$ 是「前 $t$ 步一次错都没犯」的概率,此时策略的行为与专家完全一致,状态分布就是 $p_{\text{train}}$;剩下的概率质量落在 $p_{\text{mistake}}$ 上——这是某个我们完全不知道、也不需要知道的分布(图中标注 "some other distribution")。分析的巧妙之处正在于:我们不需要知道 $p_{\text{mistake}}$ 长什么样,只需要用「任何两个概率分布之间的总变差距离不超过 1」来兜底。
注意

严格来说 $(1-\epsilon)^t$ 只是「没犯错概率」的一个下界(因为一旦离开训练分布,犯错率就不再受 $\epsilon$ 约束,可能更高),而 $p_{\text{mistake}}$ 是把所有其它情况打包进去的记号。这个分解是构造性的、略显粗糙的,但它足以支撑我们要的上界。Levine 在课上明确说这是「a bit of theory」,目的是拿到标度关系,不是写一篇理论论文。真正严谨的版本见 Ross & Bagnell 的 DAgger 论文。

6.3 两个分布差多远:总变差距离

引入总变差距离(total variation divergence):

$$ D_{\mathrm{TV}}(p,q) \;=\; \frac{1}{2}\sum_{x} \big|p(x) - q(x)\big| \;\le\; 1 $$

「$\le 1$」是它最重要的性质:无论两个分布差得多离谱,TV 距离最多是 1(当两者支撑集完全不相交时取到)。这就是我们用来给 $p_{\text{mistake}}$ 兜底的工具。

计算 p_train 与 p_πθ 之间的总变差距离,通过配凑消去 p_train 项,最后用 (1-ε)^t ≥ 1-εt 得到 ≤ εt
推导 $D_{\mathrm{TV}}(p_{\text{train}}, p_{\pi_\theta}) \le \epsilon t$ 的全过程。中间那个红色斜杠划掉的配凑是关键一招:把左边孤零零的 $p_{\text{train}}(\mathbf{s}_t)$ 拆成 $(1-\epsilon)^t p_{\text{train}}(\mathbf{s}_t) + (1-(1-\epsilon)^t)p_{\text{train}}(\mathbf{s}_t)$,这样第一项就和 $p_{\pi_\theta}$ 展开式里的第一项精确抵消,只剩下带公因子的第二项。左下角标出用到的不等式 $(1-\epsilon)^t \ge 1-\epsilon t$(对 $\epsilon \in [0,1]$ 成立,即伯努利不等式)。

把这几步全部写出来。

推导:$D_{\mathrm{TV}}(p_{\text{train}}, p_{\pi_\theta}) \le \epsilon t$

第一步,按定义展开,并把 $p_{\pi_\theta}$ 用分解式代入:

$$ D_{\mathrm{TV}} = \frac{1}{2}\sum_{\mathbf{s}_t}\big|p_{\text{train}}(\mathbf{s}_t) - p_{\pi_\theta}(\mathbf{s}_t)\big| = \frac{1}{2}\sum_{\mathbf{s}_t}\Big|p_{\text{train}}(\mathbf{s}_t) - (1-\epsilon)^t p_{\text{train}}(\mathbf{s}_t) - \big(1-(1-\epsilon)^t\big)p_{\text{mistake}}(\mathbf{s}_t)\Big| $$

第二步(配凑),注意到恒等式 $p_{\text{train}} = (1-\epsilon)^t p_{\text{train}} + \big(1-(1-\epsilon)^t\big)p_{\text{train}}$,把它代入上式最左边那一项,$(1-\epsilon)^t p_{\text{train}}$ 与后面的同类项抵消:

$$ = \frac{1}{2}\sum_{\mathbf{s}_t}\Big|\big(1-(1-\epsilon)^t\big)p_{\text{train}}(\mathbf{s}_t) - \big(1-(1-\epsilon)^t\big)p_{\text{mistake}}(\mathbf{s}_t)\Big| = \big(1-(1-\epsilon)^t\big)\cdot \frac{1}{2}\sum_{\mathbf{s}_t}\big|p_{\text{train}}(\mathbf{s}_t) - p_{\text{mistake}}(\mathbf{s}_t)\big| $$

第三步,右边那个求和就是 $D_{\mathrm{TV}}(p_{\text{train}}, p_{\text{mistake}}) \le 1$,直接扔掉(这就是「不需要知道 $p_{\text{mistake}}$」的地方):

$$ \le\ 1-(1-\epsilon)^t $$

第四步,用伯努利不等式 $(1-\epsilon)^t \ge 1 - \epsilon t$($\epsilon\in[0,1]$,对 $t\ge 1$ 的整数成立,可对 $t$ 归纳证明),得到 $1-(1-\epsilon)^t \le \epsilon t$:

$$ D_{\mathrm{TV}}(p_{\text{train}}, p_{\pi_\theta}) \;\le\; \epsilon t $$

这个中间结论本身就很有信息量:策略的状态分布与训练分布的偏离,随时间线性增长,斜率是 $\epsilon$。$t$ 越大偏得越远,这是「误差累积」最直接的数学表述。

6.4 从分布距离到代价

现在回到我们真正关心的量——期望犯错总数。

期望总代价的逐行变形:展开期望、加减 p_train、用绝对值放缩、拆成两个括号
把期望总代价一行一行地变形。第一行是定义;第二行把对 $\mathbf{s}_t$ 的期望写成显式求和;第三行是关键的加减同一项技巧:$p_{\pi_\theta} = p_{\text{train}} + (p_{\pi_\theta} - p_{\text{train}})$;第四行把差值项放大成绝对值($x \le |x|$);第五行把求和拆成两个方括号——左边是「假如状态来自训练分布会犯多少错」,右边是「分布偏移额外带来多少错」。这个「主项 + 偏移项」的拆分模式,在后面讲 TRPO 的性能差界(performance difference lemma)时会原样重现。
推导:$O(\epsilon H^2)$ 上界

第一步,把对状态的期望写成求和:

$$ \sum_{t=1}^{H} \E_{\mathbf{s}_t \sim p_{\pi_\theta}(\mathbf{s}_t)}\Big[\E_{\mathbf{a}_t\sim\pi_\theta}\big[c(\mathbf{s}_t,\mathbf{a}_t)\big]\Big] = \sum_{t=1}^{H}\sum_{\mathbf{s}_t} p_{\pi_\theta}(\mathbf{s}_t)\,\E_{\mathbf{a}_t\sim\pi_\theta(\mathbf{a}_t|\mathbf{s}_t)}\big[c(\mathbf{s}_t,\mathbf{a}_t)\big] $$

第二步,加减 $p_{\text{train}}(\mathbf{s}_t)$:

$$ = \sum_{t=1}^{H}\sum_{\mathbf{s}_t} \Big(p_{\text{train}}(\mathbf{s}_t) + p_{\pi_\theta}(\mathbf{s}_t) - p_{\text{train}}(\mathbf{s}_t)\Big)\,\E_{\mathbf{a}_t\sim\pi_\theta}\big[c\big] $$

第三步,因为 $\E[c] \ge 0$,把差值放大成绝对值只会让式子变大:

$$ \le \sum_{t=1}^{H}\sum_{\mathbf{s}_t} \Big(p_{\text{train}}(\mathbf{s}_t) + \big|p_{\pi_\theta}(\mathbf{s}_t) - p_{\text{train}}(\mathbf{s}_t)\big|\Big)\,\E_{\mathbf{a}_t\sim\pi_\theta}\big[c\big] $$

第四步,拆成两块:

$$ = \sum_{t=1}^{H}\left[\underbrace{\sum_{\mathbf{s}_t} p_{\text{train}}(\mathbf{s}_t)\E_{\mathbf{a}_t\sim\pi_\theta}[c]}_{(\mathrm{A})}\right] + \left[\underbrace{\sum_{\mathbf{s}_t}\big|p_{\pi_\theta}(\mathbf{s}_t) - p_{\text{train}}(\mathbf{s}_t)\big|\,\E_{\mathbf{a}_t\sim\pi_\theta}[c]}_{(\mathrm{B})}\right] $$

第五步,界定 (A)。它恰好就是 $\E_{\mathbf{s}_t\sim p_{\text{train}}}\big[\pi_\theta(\mathbf{a}_t\neq\pi^\star(\mathbf{s}_t)|\mathbf{s}_t)\big]$,正是我们的假设,所以 $(\mathrm{A}) \le \epsilon$。

第六步,界定 (B)。把它拆成两个因子:$\E_{\mathbf{a}_t}[c] \le 1$(0-1 代价的上界),而剩下的求和 $\sum_{\mathbf{s}_t}|p_{\pi_\theta}-p_{\text{train}}| = 2D_{\mathrm{TV}}(p_{\pi_\theta},p_{\text{train}}) \le 2\epsilon t$(用上一小节的结论)。所以 $(\mathrm{B}) \le 2\epsilon t$。

第七步,合并求和。

$$ J(\pi_\theta) \;\le\; \sum_{t=1}^{H}\big(\epsilon + 2\epsilon t\big) \;=\; \epsilon H + 2\epsilon\cdot\frac{H(H+1)}{2} \;=\; \epsilon H^2 + 2\epsilon H \;=\; O(\epsilon H^2) $$
最终结果:两个方括号分别被界定为 ε 和 2εt(其中 ≤1 的因子单列),求和得到 O(εH²),黄色框强调误差随时域二次增长
收尾页。左边方括号下的大括号标注 $\E_{\mathbf{s}_t\sim p_{\text{train}}}[\pi_\theta(\mathbf{a}_t\neq\pi^\star(\mathbf{s}_t)|\mathbf{s}_t)]\le\epsilon$(即假设本身);右边方括号被拆成两个大括号:分布差的求和 $=2D_{\mathrm{TV}}(p_{\pi_\theta},p_{\text{train}})\le 2\epsilon t$,代价期望 $\le 1$。合起来 $\sum_{t=1}^H \epsilon + 2\epsilon t = O(\epsilon H^2)$。黄色框:「这很糟糕,因为误差随时域二次增长。」页脚给出了严格版本的出处:Ross 等人的 "A Reduction of Imitation Learning and Structured Prediction to No-Regret Online Learning"。
核心结论:回答开头的三个问题
  • 比监督学习更糟吗? 是。监督学习是 $O(\epsilon H)$($H$ 个独立样本各犯 $\epsilon$ 的错),模仿学习最坏是 $O(\epsilon H^2)$。多出来的那个 $H$ 完全来自「动作会改变未来的输入分布」。
  • 数据变多问题会消失吗? 不会自动消失。更多数据只能压小 $\epsilon$,压不掉 $H^2$ 这个因子;要在时域翻倍时维持同样的性能,你需要 $\epsilon$ 降到 1/4,这在样本复杂度上是极其昂贵的。
  • 某些控制问题更糟吗? 是。$H$ 越长、越是「一步错步步错」的窄通道型任务(走钢丝、精细装配),界越紧、现实也越接近最坏情况。

7. 这个界有多悲观?以及一个反直觉的悖论

拿到一个 $O(\epsilon H^2)$ 的界之后,正确的态度不是「所以 BC 没救了」,而是去问:这个最坏情况在现实中有多典型?

为什么这个界很悲观:现实中通常能从错误中恢复;但模仿学习不一定学得会恢复;代价曲面图上策略仍能收敛回低代价区域
三块内容。左上的走钢丝和中上的红色窄通道网格提醒你上一节的界是在什么假设下取到的——那是「一步错、永不回头」的世界。中间那句话:现实中我们通常能从错误中恢复(车压线了可以打回来,机器人抓空了可以重抓)。但右上角紧接着泼冷水:「这并不意味着模仿学习能让我们学会怎么恢复!」下方的彩色代价曲面图画出了一个「宽容」的问题:代价面有一个宽阔的低谷(蓝色),策略偏离后仍会被拉回来,红线和黑线不会发散。黄色框是本讲最反直觉的一句话:「一个悖论:如果演示数据里有更多错误(以及随后的纠正),模仿学习反而效果更好!」

7.1 为什么最坏情况通常不会发生

$O(\epsilon H^2)$ 的推导里有一个隐含的最坏假设:一旦离开训练分布,就再也回不来($p_{\text{mistake}}$ 与 $p_{\text{train}}$ 完全不相交,TV 距离取到上界 1)。真实的物理系统很少这么残酷:

  • 大多数控制问题有吸引子结构:车道保持任务里,即使方向盘打偏几度,路面几何和后续的正确动作也会把你拉回车道中心;机械臂的位置误差在下一步就能被纠正。
  • 动力学往往是耗散的、稳定的:小扰动会衰减而不是放大。走钢丝之所以是最坏情况的完美隐喻,正因为它是罕见的不稳定系统。
  • 状态分布的重叠往往并不小:车偏离 5 厘米时看到的画面,与在中心线上看到的画面在特征空间里非常接近,网络的泛化能力本身就提供了一定的鲁棒性。

7.2 但「能恢复」不等于「学得会恢复」

这是 Levine 特别强调的一点,也是许多人第一次读这套材料时漏掉的。系统物理上可以从偏离态恢复,与策略知道怎么恢复,是两件完全不同的事。而 BC 学不到恢复行为的原因非常直接:演示数据里没有恢复行为。

一个优秀的人类司机从不压线,所以数据集里 $p_{\text{train}}$ 的支撑集根本不包含「车已经压线」这个状态;网络在这个输入上的输出是纯粹的外插,没有任何监督信号约束过它。就算真实世界允许你打方向盘回正,策略也不知道这件事。

直觉:那个悖论怎么解

假设有两位司机来采数据:
司机 A:技术完美,全程车在正中,方向盘几乎不动。数据里 $\epsilon$ 可以训得极小,但状态分布是一根极细的线。
司机 B:技术一般,经常偏个十几厘米,然后打回来。数据里有噪声,训练误差 $\epsilon$ 更大,但状态分布是一条宽带,并且带上的每个偏离态都配着正确的纠偏动作。
用 B 的数据训出来的策略,在真机上几乎总是表现更好。为什么?因为 BC 的失败模式不是「动作精度不够」,而是「跌出分布后不知所措」。B 的数据把 $p_{\text{train}}$ 撑宽了,使得策略执行时的漂移仍然落在训练分布内;而且它示范了漂移之后该怎么办。用理论的语言说:牺牲一点 $\epsilon$,换取 $p_{\text{mistake}}$ 与 $p_{\text{train}}$ 的大幅重叠,从而让 $D_{\mathrm{TV}}$ 那一项不再随 $t$ 线性增长。

这个洞见有非常具体的工程后果,在今天的机器人数据采集里是常识:

  • 主动注入噪声:让演示者在带噪声的遥操作下工作(或对专家动作加小扰动),迫使他不断做微观纠正,这些纠正就成了训练信号。DART(Laskey 等人,2017)就是把这个想法系统化的方法。
  • 合成偏离态:NVIDIA 的三摄像头就是最经典的例子——不改变演示者的行为,而是用几何变换伪造偏离视角,再解析地推算出对应的修正动作。
  • 不要过滤掉「不完美」的演示:直觉上你会想只保留最漂亮的那些轨迹,但对 BC 来说,含有小失误 + 纠正的轨迹是宝贵的,不该扔。
常见误区

「既然噪声有好处,那我把动作标签随机扰动一下当数据增强就行了。」——不行。关键不在于动作噪声本身,而在于「偏离态 → 正确的纠偏动作」这个配对必须是真实的。给动作标签加噪声只会把正确标签变成错误标签,纯粹损害性能。正确的做法是让状态偏离(通过扰动执行、通过几何变换伪造观测),然后为偏离后的状态获取正确的标签。

8. DAgger:从根上修好分布漂移

8.1 换一个方向想

问题是 $p_{\text{data}}(\mathbf{o}_t) \neq p_{\pi_\theta}(\mathbf{o}_t)$。要修好它,可以从两端下手:

  • 改 $p_{\pi_\theta}$:让策略尽量别偏离数据分布。这需要更强的模型、更好的表示、更多数据——本质上是在把 $\epsilon$ 往小里压。有用,但正如第 5 节算过的,代价随 $H$ 二次增长。
  • 改 $p_{\text{data}}$:让训练数据来自策略自己会访问到的分布。这才是 DAgger 的思路。
回到发散轨迹图,底部问:我们能让 p_data(o_t) 等于 p_πθ(o_t) 吗?
再次回到那张发散轨迹图,但这次问题变了:「我们能让 $p_{\text{data}}(\mathbf{o}_t) = p_{\pi_\theta}(\mathbf{o}_t)$ 吗?」注意问的不是「能不能让红线贴回黑线」,而是「能不能让黑线跑到红线上去」——把训练数据挪到策略实际会去的地方。这个视角切换是本讲后半程的转折点。
DAgger 的一句话

与其绞尽脑汁让 $p_{\pi_\theta}(\mathbf{o}_t)$ 变聪明,不如让 $p_{\text{data}}(\mathbf{o}_t)$ 变聪明——直接从 $p_{\pi_\theta}$ 里采数据。怎么采?把策略放到环境里跑就是了。唯一缺的是标签 $\mathbf{a}_t$:这些状态上正确的动作是什么?去问专家。

8.2 算法

DAgger 算法四步:训练策略、跑策略收集观测、请人标注、聚合数据集,循环
DAgger(Dataset Aggregation,Ross 等人 2011)的完整算法框。上方三行是动机链:能否让 $p_{\text{data}}=p_{\pi_\theta}$?想法是别在 $p_{\pi_\theta}$ 上耍聪明,在 $p_{\text{data}}$ 上耍聪明;目标是从 $p_{\pi_\theta}(\mathbf{o}_t)$ 而不是 $p_{\text{data}}(\mathbf{o}_t)$ 收集训练数据;怎么做?把 $\pi_\theta$ 跑起来就行——但需要标签 $\mathbf{a}_t$!下方绿色循环箭头标出四个步骤。
DAgger 算法
  1. 在人类数据 $\mathcal{D} = \{\mathbf{o}_1,\mathbf{a}_1,\ldots,\mathbf{o}_N,\mathbf{a}_N\}$ 上训练 $\pi_\theta(\mathbf{a}_t|\mathbf{o}_t)$;
  2. 运行 $\pi_\theta(\mathbf{a}_t|\mathbf{o}_t)$ 与环境交互,得到只有观测、没有标签的数据集 $\mathcal{D}_\pi = \{\mathbf{o}_1,\ldots,\mathbf{o}_M\}$;
  3. 请人类为 $\mathcal{D}_\pi$ 中的每个观测标注正确动作 $\mathbf{a}_t$;
  4. 聚合:$\mathcal{D} \leftarrow \mathcal{D} \cup \mathcal{D}_\pi$,回到第 1 步。

为什么这样就修好了?因为随着迭代进行,$\mathcal{D}$ 里越来越大的比例来自 $p_{\pi_\theta}$ 本身,训练分布逐步收敛到策略的执行分布。当 $p_{\text{data}} \to p_{\pi_\theta}$ 时,第 6 节推导里那个 $2D_{\mathrm{TV}} \le 2\epsilon t$ 的偏移项趋近于 0,只剩下主项 $\sum_t \epsilon = \epsilon H$。误差界从 $O(\epsilon H^2)$ 回到了监督学习的 $O(\epsilon H)$——这是 Ross 等人论文的核心定理(严格版本用 no-regret 在线学习的框架给出,且要求专家可查询的次数随迭代增长)。

推导:为什么 DAgger 消掉了一个 $H$

回看第 6 节最后的拆分 $J(\pi_\theta) \le \sum_{t=1}^{H}\big[(\mathrm{A}) + (\mathrm{B})\big]$,其中 $(\mathrm{A})\le\epsilon$ 是「训练分布上的固有误差」,$(\mathrm{B})\le 2D_{\mathrm{TV}}(p_{\pi_\theta},p_{\text{train}})$ 是「分布偏移的额外代价」。BC 的问题在于 $(\mathrm{B})$ 随 $t$ 线性增长,求和后给出 $H^2$。而 DAgger 在收敛时满足 $p_{\text{train}} = p_{\pi_\theta}$,于是

$$ D_{\mathrm{TV}}(p_{\pi_\theta},p_{\text{train}}) = 0 \quad\Longrightarrow\quad J(\pi_\theta) \le \sum_{t=1}^{H}\epsilon = \epsilon H $$

换句话说,DAgger 不是让策略变准了($\epsilon$ 没变),而是让「训练分布」和「测试分布」重新对齐,从而恢复了 i.i.d. 假设。这是它与「换个更大的模型」在性质上的根本区别。

DAgger 在无人机林间飞行任务上的演示画面
Ross 等人原论文的经典演示:一架小型无人机在树林里自主飞行避障。第一轮 BC 的策略很快撞树;每一轮 DAgger 之后,人类操作员对策略飞出来的画面重新标注「这里应该往哪打」,几轮迭代后策略就能稳定穿林。画面底部那个蓝色条形是操作员标注的转向指令。

8.3 DAgger 的真正麻烦:第 3 步

DAgger 四步中第 3 步被红框圈出,下方画着车把观测发给人、人给出动作
红框圈出的第 3 步——「请人类为 $\mathcal{D}_\pi$ 标注动作」——是整个算法的阿喀琉斯之踵。下方的示意图说明这件事有多别扭:车把它看到的画面 $\mathbf{o}_t$ 发给人,人要脱离驾驶情境、面对一张静态截图,说出「此刻我会打多少度方向盘」。

这一步在实践中有三个层面的困难:

困难说明后果
需要交互式专家不能只用一批离线演示数据,专家必须在训练循环里随叫随到大幅抬高数据成本;很多场景(历史数据、他人采集的数据集)根本无法应用
脱离情境标注很难人类的控制能力是闭环、连续、有本体感觉的。给一张静态图片说「打 7.3 度方向盘」,人根本给不准标签质量差,噪声大;对精细操作(机器人力控)几乎不可能标
要标的状态很危险/很怪DAgger 特意去采策略犯错后的状态——那可能是「车已经在对向车道」真机上直接跑未训练好的策略有安全风险;早期迭代尤其危险

8.4 工程上更常用的变体:人类接管

DAgger 常见变体:跑策略、人在某时刻接管、只记录人类干预期间的样本;两个机器人实验画面
实践中最常见的 DAgger 变体(有时叫 HG-DAgger 或 interactive imitation / 专家干预式学习):1. 用人类数据训 $\pi_\theta$;2. 跑 $\pi_\theta$;3. 在某个时刻请人类接管(take over);4. 只保存人类干预期间的 $(\mathbf{o}_t,\mathbf{u}_t)$ 样本,加入数据集。下方两张图是真实机器人系统:左边(蓝框)是精密装配任务里 RL 策略与专家干预交替;右边(绿框)是双臂机器人在「autonomous」标签下自主执行。右上角黄色框留下的问题非常尖锐:「这样还能保证修好分布漂移吗?」

这个变体在人机工效上好太多:人类不需要对着截图猜,而是直接接过控制权继续开,标签是他在真实闭环情境下的自然操作,质量高得多。今天绝大多数机器人公司的数据飞轮就是这么转的。

注意:它还保证修好分布漂移吗?

严格来说——不完全保证。原始 DAgger 要求对策略访问到的每一个状态都获得专家标注,这样训练分布才真正等于 $p_{\pi_\theta}$。而接管变体只在人类觉得该干预的时刻之后才记录数据,于是:

  • 数据集偏向「危险/困难状态 + 人类救场动作」,而策略正常运行时访问的大量普通状态没有新增标注,两个分布仍不相同;
  • 人类什么时候接管带有很强的主观性,这引入了一个不受控的采样偏置;
  • 接管瞬间往往伴随控制权切换的动力学不连续,那一段数据可能本身就有噪声。

但在工程上它通常仍然有效,因为它精确地补上了最需要补的那部分数据——策略即将失败的地方。这是理论保证与实用性之间一次典型的交换,Levine 把这个问题留给听众思考,本身就是在提醒你:算法的理论保证依赖于它的每一个前提条件,改了前提就得重新想。

8.5 DAgger 的最小实现

def dagger(env, expert, obs_dim, act_dim, n_iters=10, rollouts_per_iter=20):
    """expert(obs) -> 正确动作;在仿真里通常是一个已有的控制器,
    在真机上就是「请人类标注 / 接管」这一步。"""
    obs_buf, act_buf = [], []

    # 第 0 轮:纯 BC,用专家自己跑出来的数据
    for _ in range(rollouts_per_iter):
        o, done = env.reset(), False
        while not done:
            a = expert(o)                    # 专家演示
            obs_buf.append(o); act_buf.append(a)
            o, _, done, _ = env.step(a)      # 环境由专家动作驱动

    policy = None
    for it in range(n_iters):
        # 1. 在聚合后的数据集上重新训练(每轮从头训,避免早期数据的过拟合遗留)
        policy = behavior_cloning(torch.stack(obs_buf), torch.stack(act_buf),
                                  obs_dim, act_dim)

        # 2&3. 跑「学生」策略采状态,但标签来自专家 —— 这两行是 DAgger 的全部秘密
        for _ in range(rollouts_per_iter):
            o, done = env.reset(), False
            while not done:
                a_student = policy.act(o, deterministic=True)
                a_expert  = expert(o)        # 专家对学生访问到的状态给出正确动作
                obs_buf.append(o); act_buf.append(a_expert)
                o, _, done, _ = env.step(a_student)   # 注意:环境由「学生」驱动!
        # 4. 聚合已经在上面的 append 里完成了
        print(f"DAgger iter {it}: dataset size = {len(obs_buf)}")
    return policy

请对照两处细节。第一,内层循环里 env.step(a_student) 用的是学生的动作,而 act_buf.append(a_expert) 存的是专家的动作——状态由学生的分布产生,标签由专家提供,这一行错位就是 DAgger 的全部内容。第二,每轮都在聚合后的完整数据集上重训,而不是只用新数据微调;「Aggregation」这个名字就是从这里来的,它保证了策略不会在迭代中遗忘早期的好行为(对应 no-regret 在线学习里的 Follow-the-Leader)。

常见的实用变体还有 $\beta$-混合:第 $i$ 轮用 $\pi_i = \beta_i \pi^\star + (1-\beta_i)\pi_\theta$ 去采数据,$\beta_i$ 从 1 递减到 0。早期主要由专家驾驶(安全、状态不至于太离谱),后期完全交给学生。原论文推荐 $\beta_i$ 指数衰减,并证明只要 $\frac{1}{N}\sum_i \beta_i \to 0$,no-regret 保证依然成立。

9. 不改算法,怎么让 BC 好用

DAgger 需要交互式专家,这个前提在很多场景下无法满足(你手上只有一批别人采好的离线数据)。那么在不改算法的前提下,还有哪些手段?Levine 给出的清单有四条,逐条展开。

9.1 让模型强到几乎不犯错

既然界是 $O(\epsilon H^2)$,把 $\epsilon$ 压到足够小当然也管用。这条路线在今天的机器人基础模型(RT-1、RT-2、Octo、$\pi_0$ 一类)上被推到了极致:几十亿参数、上千小时的多机器人数据、强大的视觉语言预训练。

但要看清这条路的两个前提。其一,$\epsilon$ 必须以 $1/H^2$ 的速度下降才能维持性能,所以模型规模换来的收益是被时域平方稀释的;这解释了为什么大模型在「拿起杯子」这种几秒钟的任务上表现惊艳,在「整理整个厨房」这种几分钟的长程任务上仍然会崩。其二,拟合专家分布本身也很难——人类演示是多模态且非马尔可夫的,用单峰高斯去拟合会得到「两个正确动作的平均值」这种最糟的结果。这正是下一讲要用扩散策略、动作分块等手段解决的问题。

9.2 聪明地采集与增强数据

这是投入产出比最高的一条,也是第 3 节 NVIDIA 案例和第 7 节悖论的直接推论。核心目标只有一个:让 $p_{\text{train}}$ 覆盖策略执行时会漂到的区域,并在那些区域提供正确的纠偏标签。

手段怎么做为什么有效
多摄像头装左/中/右三个相机,左相机图像配「右打一点」的标签,右相机配「左打一点」零成本合成偏离视角 + 解析地推出正确纠正动作,直接把 $p_{\text{train}}$ 撑宽
几何增强对图像做随机平移/旋转,并对动作标签做相应的修正同上,但要求你知道「视角变换 ↔ 动作修正」的对应关系
注入噪声演示在遥操作链路上加扰动,逼演示者不断做微观纠正(DART)真实的「偏离 → 纠正」配对,标签质量最高
刻意示范失败与恢复让演示者故意把机器人放到别扭的位姿,再演示怎么救回来直接补齐 $p_{\text{mistake}}$ 上的标签,是 DAgger 的离线近似
保留不完美轨迹不要只挑最漂亮的演示训练见第 7 节的悖论:小失误 + 纠正是宝贵信号
常见误区

把图像增强(随机裁剪、颜色抖动)当作解决分布漂移的手段。普通的图像增强只提升观测层面的鲁棒性(对光照、纹理变化不敏感),完全没有触及状态层面的分布漂移。关键区别在于:三摄像头技巧同时修改了动作标签,而随机颜色抖动不会。凡是不改标签的增强,都不能生成新的「纠偏样本」。

9.3 历史信息与序列模型

回到第 1 节的部分可观测问题:若 $\mathbf{o}_t$ 不满足马尔可夫性,单帧策略 $\pi_\theta(\mathbf{a}_t|\mathbf{o}_t)$ 在原理上就学不到最优行为。自然的补救是让策略读入整段历史:

$$ \pi_\theta\big(\mathbf{a}_t \,\big|\, \mathbf{o}_1,\mathbf{o}_2,\ldots,\mathbf{o}_t\big) $$

实现上有三种常见做法:帧堆叠(把最近 $k$ 帧沿通道维拼起来,DQN 打 Atari 就是这么干的,简单粗暴但只能看到固定长度的过去)、循环网络(LSTM/GRU 维护一个隐状态,理论上能记住任意长的历史)、以及今天的主流Transformer(把观测序列当 token 序列,用因果注意力,还能顺便处理语言指令)。

注意:历史信息不是免费的

喂进历史会引入一个隐蔽而致命的新问题——因果混淆(causal confusion)。经典例子:车里有个刹车指示灯,司机踩刹车时它会亮。如果策略能看到当前帧的指示灯,它会学到「灯亮 → 刹车」这条相关性极强但因果方向完全颠倒的规则,而不去学「前方有行人 → 刹车」。更普遍地,历史里包含上一步自己的动作的痕迹,而演示数据中动作在时间上高度自相关,于是策略会退化成「重复上一个动作」的惯性预测器——在训练集上损失极低,一上线就完全不响应环境。
反直觉的结论:信息更多的策略,在 BC 下反而可能表现更差。下一讲会详细讨论这个现象及其缓解手段。

9.4 多任务学习

最后一条乍看很奇怪:同时学多个任务,每个任务反而学得更好。

设想训练一个导航策略。方案 A:只收集「从各处到达目标点 $\mathbf{p}_1$」的演示。方案 B:收集「到达 $\mathbf{p}_1$」「到达 $\mathbf{p}_2$」「到达 $\mathbf{p}_3$」……的演示,并把目标点作为条件输入,学一个目标条件策略(goal-conditioned policy)$\pi_\theta(\mathbf{a}_t|\mathbf{o}_t, \mathbf{g})$。

方案 B 更好,理由与第 7 节的悖论同源:去往 $\mathbf{p}_2$ 的轨迹会经过许多「对 $\mathbf{p}_1$ 任务来说属于偏离态」的状态。这些状态在方案 A 的数据里根本不存在,在方案 B 里却被别的任务顺带覆盖了。多任务数据以一种「免费」的方式把状态分布撑宽了——从 $\mathbf{p}_2$ 任务的演示里,策略学会了在那片区域该怎么动,这些知识可以迁移到 $\mathbf{p}_1$ 任务上偏离后的恢复。

这个思路还有一个更激进的版本:把任何一条轨迹的终点事后标记成「目标」,于是所有数据都变成成功的演示。这就是 hindsight relabeling / goal relabeling 的想法,本课后面讲 goal-conditioned RL 时会正式展开。

直觉:四条路其实是同一条

把这四条办法放在第 6 节的界 $J \le \sum_t [(\mathrm{A}) + (\mathrm{B})]$ 上看,它们的分工一目了然:
「更强的模型」压的是 $(\mathrm{A})$(训练分布上的固有误差 $\epsilon$);
「聪明的数据」「多任务」「DAgger」压的都是 $(\mathrm{B})$(分布偏移项 $D_{\mathrm{TV}}$)——只是手段不同:DAgger 用交互式专家精确对齐,数据增强用几何先验近似合成,多任务用别的任务的数据顺带覆盖。
「历史信息」则是在修正一个更基础的问题:当 $\mathbf{o}_t$ 不是状态时,$\epsilon$ 存在一个不可消除的下界,再多数据也压不下去。
理解了这个分类,你以后看到任何一篇「改进 BC」的论文,都能立刻定位它在攻哪一项。

本讲小结

一页速查:

概念一句话关键式子
状态 vs 观测$\mathbf{s}_t$ 满足马尔可夫性,$\mathbf{o}_t$ 一般不满足$\mathbf{s}_{t+1}\perp\mathbf{s}_{t-1}\mid\mathbf{s}_t$
行为克隆把演示数据打散当 i.i.d. 样本做最大似然$\argmax_\theta\sum_i\sum_t\log\pi_\theta(\mathbf{a}_t^{(i)}|\mathbf{o}_t^{(i)})$
动作分布离散用 softmax logits;连续用高斯,$\Sigma=\mathbf{I}$ 时退化为 MSE$-\log p = \tfrac12\|\mathbf{a}_t-\mu(\mathbf{o}_t)\|^2 + C$
分布漂移训练分布由专家产生,测试分布由学生产生,二者必然不同$p_{\text{data}}(\mathbf{o}_t)\neq p_{\pi_\theta}(\mathbf{o}_t)$
0-1 代价动作与专家不一致就记 1 分$\E_{\mathbf{a}_t\sim\pi_\theta}[c] = \pi_\theta(\mathbf{a}_t\neq\pi^\star(\mathbf{s}_t)|\mathbf{s}_t)$
分布分解按「有没有犯过错」把 $p_{\pi_\theta}$ 拆成两块$p_{\pi_\theta}=(1-\epsilon)^t p_{\text{train}} + (1-(1-\epsilon)^t)p_{\text{mistake}}$
TV 界分布偏离随时间线性增长$D_{\mathrm{TV}}(p_{\text{train}},p_{\pi_\theta})\le 1-(1-\epsilon)^t\le\epsilon t$
BC 误差界最坏情况随时域二次增长$J(\pi_\theta)\le\sum_{t=1}^{H}(\epsilon+2\epsilon t)=O(\epsilon H^2)$
DAgger让数据去迁就策略:跑学生、专家标注、聚合、重训$p_{\text{train}}\to p_{\pi_\theta}\Rightarrow J\le\epsilon H$
恢复悖论演示里有更多小错误 + 纠正,BC 反而更好牺牲 $\epsilon$ 换 $D_{\mathrm{TV}}$

要点清单:

  • 行为克隆不是强化学习,它是被用在了 i.i.d. 假设不成立的场景上的监督学习;它没有任何有效性保证。
  • 失败的机制是误差累积:犯一个错就进入没见过的状态,在那里犯错概率不再受训练误差约束,于是发散。「犯错」与「跌出分布」在控制问题里是同一件事。
  • 最坏情况上界 $O(\epsilon H^2)$,两个 $H$ 分别来自「有 $H$ 次跌出去的机会」和「每次跌出去平均损失 $H/2$ 步」。
  • 推导的主线:0-1 代价 $\to$ 犯错概率 $\to$ 按是否犯错分解状态分布 $\to$ 用 TV 距离界定偏移($\le\epsilon t$)$\to$「主项 + 偏移项」拆分 $\to$ 求和得 $O(\epsilon H^2)$。这个「主项 + 分布偏移项」的套路后面会反复出现。
  • 这是最坏情况界。现实中系统往往能从错误中恢复,所以 BC 常常能用;但系统能恢复 ≠ 策略学得会恢复,除非数据里有恢复行为。
  • DAgger 是唯一从根上解决问题的方法(把界降回 $O(\epsilon H)$),代价是需要交互式专家;工程上常用「人类接管」变体,人机工效好但牺牲了部分理论保证。
  • 不改算法的四条路:更强的模型(压 $\epsilon$)、更聪明的数据采集与增强(压 $D_{\mathrm{TV}}$)、历史/序列模型(应对部分可观测,但小心因果混淆)、多任务学习(用别的任务免费撑宽状态分布)。
  • 下一讲继续:DAgger 的深入变体、非马尔可夫策略的因果混淆、以及人类演示多模态性的建模(混合密度、隐变量模型、扩散策略、自回归离散化)。

延伸阅读

本讲直接引用

让 BC 变得可用

现代的 BC:大模型与多模态动作