Rollout 误差累积

一句话定位:分析多步想象 rollout 过程中模型误差如何随时间步累积,以及由此导致的分布偏移(distribution shift)问题,是世界模型规划能力的核心瓶颈。


前置依赖

  • RSSM 基础(先验采样、确定性转移)
  • 想象 rollout 基本流程
  • 强化学习基础(值函数估计、策略梯度)
  • KL 散度与变分推断

核心问题

在多步想象 rollout 中,我们使用世界模型生成的虚拟轨迹进行规划和策略学习。然而,世界模型不是真实环境的完美表征——它存在两类误差:

  1. 认知误差(Epistemic Uncertainty):由于训练数据不足,模型对某些状态区域不熟悉
  2. 偶然误差(Aleatoric Uncertainty):由于环境本身的随机性,即使完美模型也无法完全消除

当使用模型生成的多步轨迹进行策略学习时,这些误差会随时间步累积放大,导致:

  • 预测的隐状态越来越偏离真实隐状态
  • 基于错误隐状态做出的决策越来越差
  • 规划的奖励越来越高,但真实奖励越来越低(过度乐观

这种”模型自我欺骗”的现象称为分布偏移(Distribution Shift)规划陷阱(Planning Trap)


数学分析

A. 单步误差模型

设真实环境动态为 ,世界模型为

为真实隐状态, 为模型预测的隐状态。

单步误差

假设误差主要由两部分组成:

  1. 转移误差 — 转移函数的偏差
  2. 观测误差 — 编码器的偏差

B. 误差累积的线性分析

假设单步误差服从线性增长的模型:

单步误差传播

其中 是转移函数的 Lipschitz 常数, 是单步误差。

递推展开

关键观察

  1. 指数级增长:如果 ,误差以指数级增长
  2. 初始误差放大:初始隐状态的误差会被 放大
  3. 累积效应:每个时间步的误差都对最终误差有贡献

C. 非线性误差分析

在实际中,转移函数 通常是非线性的(GRU/LSTM)。误差增长通常是超线性的,因为:

  1. 自引用放大:错误的隐状态导致错误的动作,错误的动作又加剧隐状态误差
  2. 不确定性放大:误差较大时,模型的不确定性也增大,导致采样多样性降低
  3. 吸引盆收缩:错误累积使轨迹进入模型从未见过的状态区域(ood)

数学描述

其中 是误差传播矩阵的最大特征值, 是噪声项。

D. 分布偏移的量化

隐状态分布偏移

当使用先验 rollout 时,采样的 是基于模型的预测分布,与真实后验 逐渐偏离。

规划陷阱的数学描述

策略优化的目标是:

但真实累积奖励为:

两者之间的差距随 rollout 长度 增大:

其中 增长,可能是超线性甚至指数级。


误差来源分解

A. 观测重建误差

来源:编码器-解码器对 无法完美重建观测。

数学表示

影响

  • 模型学习的隐状态空间与真实隐状态空间存在系统性偏差
  • 解码器输出与真实观测存在重构误差
  • 这个误差会在每一步传递给转移函数

B. 转移函数误差

来源:转移网络 无法完美拟合真实动态。

数学表示

影响

  • 同一隐状态-动作对,模型预测的下一隐状态与真实值有偏差
  • 偏差随 rollout 累积

C. 先验-后验不一致误差

来源:训练时使用后验 ,推理时使用先验

数学表示

影响

  • 推理时采样的 分布与训练时不同
  • 模型预测的奖励可能过度乐观(先验比后验更确定)

D. 奖励预测误差

来源:奖励预测网络 不准确。

数学表示

影响

  • 策略优化基于错误的奖励信号
  • 即使隐状态准确,奖励预测误差也会误导策略学习

对抗误差累积的方法

A. 策略约束(Policy Regularization)

限制策略过于依赖模型预测的不准确区域:

其中 是参考策略(如随机策略或保守策略)。

作用:防止策略在模型预测的不准确区域过度优化。

B. Ensembling(集成模型)

训练多个独立的世界模型,通过集成减少误差:

优势

  • 减少单模型的预测方差
  • 通过模型间的分歧估计不确定性
  • 抑制过度自信的预测

不确定性估计

C. Dropout 作为不确定性估计

在推理时保留 dropout,多次采样获得预测方差:

# 启用 dropout
model.train()  # 或 model.eval() with dropout
 
# 多次采样
for i in range(N):
    z_t = model.prior(h_prev, a_t)
    # forward pass
    predictions.append(output)
 
# 估计不确定性
uncertainty = torch.var(torch.stack(predictions), dim=0)

D. 短 rollout + 重新规划(Receding Horizon)

限制每步 rollout 长度 ,并在每步后用真实观测重新对齐:

数学保证:若 足够小,误差累积在可控范围内。

MPC 形式

  1. 预测
  2. 执行第一步
  3. 获得真实观测,重新预测
  4. 重复

E. 重新填充(Replay Buffer)

使用真实环境交互的数据定期重新训练模型,减少分布偏移:

# 定期与环境交互
for step in range(n_env_steps):
    action = policy_net(h_t)
    real_reward, next_obs = env.step(action)
    buffer.add(h_t, action, real_reward, next_obs)
    h_t = encoder(next_obs)
 
# 用真实数据微调模型
for epoch in range(n_epochs):
    batch = buffer.sample()
    model.train_step(batch)

F. KL 正则化 rollout

在 rollout 时添加 KL 项约束先验分布不要过于偏离后验分布:

这确保推理时的先验分布与训练时的后验分布保持一致。


模型结构图

误差累积示意图

真实环境:          世界模型预测:
                   │
o_0 ──────► h_0 ──┼──► Encoder ──► h_0 ──► 先验采样 ──► z_0
                   │        │                        │
                   │        │                        ▼
                   │        │                   h_1 = f(h_0, z_0, a_0)
                   │        │                        │
                   │        │                        ▼
a_0 ───────────────┼────────┴─── Policy π(h_0) ──► a_0
                   │                                    │
                   │                                    │ 真实环境交互
                   │                                    ▼
                   │                              o_1 (真实)
                   │                                    │
                   │         误差累积 ◄─────────────────┘
                   │                                    │
                   │      Decoder ◄── h_1                │
                   │         │                          │
                   │         ▼                          ▼
                   │    o_hat_1                      h_1(真实)
                   │         │                          │
                   │         │ 差距越来越大               │
                   ▼         ▼                          ▼
              策略优化 ◄── 奖励预测                   a_1(次优)
                          r_hat

分布偏移可视化

时间步 1:     p(h_1)          p_θ(h_1)
              ████████████    ████████████    (重叠度高)

时间步 10:    p(h_10)         p_θ(h_10)
              ████████        ████████████████   (开始偏移)

时间步 50:    p(h_50)         p_θ(h_50)
              ████            ████████████████████   (严重偏移)

时间步 100:   p(h_100)        p_θ(h_100)
              ██             ███████████████████████ (几乎无重叠)

数学推导

A. 误差累积 Bound 的推导

设真实转移函数为 (隐式),模型转移函数为

假设

  1. -Lipschitz 的
  2. 初始误差
  3. 采样误差 (先验 vs 真后验)
  4. 动作误差

单步误差边界

其中 是转移函数的固有误差。

递推展开

展开:

关键结论

  • 如果 (转移函数膨胀),误差指数增长
  • 如果 (转移函数收缩),误差收敛到稳态
  • 如果 (等距映射),误差线性增长

B. 规划陷阱的数学形式

策略学习目标:

真实环境中的期望回报:

两者差距:

其中 随 rollout 长度 增长。

更紧的界(假设奖励误差有界):


与前后内容的衔接

  • 前置内容:想象 rollout 是误差累积发生的舞台;RSSM 的先验-后验不一致是误差来源之一
  • 后续发展:多步预测与时间一致性进一步讨论如何保持长时序预测的一致性;ensemble models 和 uncertainty 建模是对抗误差累积的主要手段
  • 核心联系:误差累积是制约世界模型规划能力的核心瓶颈,理解误差来源和累积机制是设计更鲁棒算法的前提

可复现实现要点

A. 误差追踪工具

class ErrorTracker:
    """追踪 rollout 过程中的误差累积"""
    
    def __init__(self, model):
        self.model = model
        self.reset()
    
    def reset(self):
        self.h_errors = []  # 隐状态误差
        self.r_errors = []  # 奖励预测误差
        self.kl_deviations = []  # 先验-后验偏差
    
    def compute_errors(self, real_h, pred_h, real_r, pred_r):
        h_error = torch.norm(real_h - pred_h, dim=-1).mean()
        r_error = torch.abs(real_r - pred_r).mean()
        return h_error.item(), r_error.item()
    
    def track_rollout(self, real_obs_seq, pred_h_seq, pred_r_seq):
        """追踪一条 rollout 的误差"""
        self.reset()
        
        for t in range(len(pred_h_seq) - 1):
            real_h_t = self.model.encoder(real_obs_seq[:, t])
            pred_h_t = pred_h_seq[t]
            
            # 隐状态误差
            h_err = torch.norm(real_h_t - pred_h_t, dim=-1).mean()
            self.h_errors.append(h_err.item())
            
            # 奖励误差
            if t < len(pred_r_seq):
                r_err = torch.abs(self.real_rewards[t] - pred_r_seq[t]).mean()
                self.r_errors.append(r_err.item())
        
        return self.get_summary()
    
    def get_summary(self):
        return {
            'mean_h_error': np.mean(self.h_errors),
            'final_h_error': self.h_errors[-1] if self.h_errors else 0,
            'error_growth_rate': (self.h_errors[-1] / (self.h_errors[0] + 1e-6)) 
                                 if len(self.h_errors) > 1 else 1.0,
            'mean_r_error': np.mean(self.r_errors) if self.r_errors else 0,
        }

B. Ensemble 模型实现

class EnsembleRSSM(nn.ModuleList):
    """RSSM 集成模型"""
    
    def __init__(self, n_models, hidden_dim, action_dim, latent_dim):
        super().__init__()
        # 创建多个独立的 RSSM 模型
        for i in range(n_models):
            self.append(RSSM(hidden_dim, action_dim, latent_dim))
    
    def forward(self, h_prev, action, model_idx=None):
        """前向传播,可指定模型索引或使用平均"""
        if model_idx is not None:
            return self[model_idx].forward(h_prev, action)
        
        # 集成预测:平均所有模型的预测
        predictions = []
        for model in self:
            p_mu, p_sigma = model.prior(h_prev, action)
            z = model.reparameterize(p_mu, p_sigma)
            h = model.forward(h_prev, z, action)
            predictions.append(h)
        
        # 返回平均值
        return torch.stack(predictions).mean(dim=0)
    
    def estimate_uncertainty(self, h_prev, action, n_samples=10):
        """估计不确定性(通过模型间方差)"""
        predictions = []
        
        # 随机选择 n_samples 个模型
        selected_idx = np.random.choice(len(self), n_samples, replace=False)
        
        for idx in selected_idx:
            model = self[idx]
            p_mu, p_sigma = model.prior(h_prev, action)
            z = model.reparameterize(p_mu, p_sigma)
            h = model.forward(h_prev, z, action)
            predictions.append(h)
        
        predictions = torch.stack(predictions)
        mean = predictions.mean(dim=0)
        variance = predictions.var(dim=0)
        
        return mean, variance

C. 短 rollout + 重新规划示例

def mpc_with_replanning(model, policy_net, h_0, env, horizon=15, n_replan=1):
    """
    短 horizon 重新规划 MPC
    
    每 n_replan 步重新规划一次
    """
    h_t = h_0
    total_reward = 0
    
    t = 0
    while t < max_steps:
        if t % n_replan == 0:
            # 重新规划
            action_seq = plan_horizon(model, policy_net, h_t, horizon)
            action = action_seq[0]
        else:
            action = action_seq[t % n_replan]
        
        # 执行动作
        real_reward, next_obs = env.step(action)
        total_reward += real_reward
        
        # 更新隐状态(使用真实观测)
        h_t = model.encoder(next_obs)
        
        t += 1
        
        if env.done:
            break
    
    return total_reward

D. 关键实现细节

不确定性aware 的策略采样

def uncertainty_aware_policy(model, h_t, action_dist, uncertainty_threshold):
    """在高度不确定的状态区域使用更保守的策略"""
    # 估计当前状态的不确定性
    _, variance = model.estimate_uncertainty(h_t, action_dist.mean())
    uncertainty = variance.mean()
    
    if uncertainty > uncertainty_threshold:
        # 使用更保守的策略(减小动作幅度)
        action_scale = uncertainty_threshold / (uncertainty + 1e-6)
        action = action_dist.mean() * action_scale
    else:
        action = action_dist.mean()
    
    return action

章节摘要

Rollout 误差累积是基于世界模型的规划方法面临的核心挑战。多步想象 rollout 过程中,模型误差会以指数级或超线性方式累积,导致预测的隐状态和奖励与真实值严重偏离。

误差来源

  1. 观测重建误差(编码器-解码器)
  2. 转移函数误差(模型不完美)
  3. 先验-后验不一致(训练-推理差异)
  4. 奖励预测误差

误差累积数学

  • 若转移函数 Lipschitz 常数 ,误差指数增长

对抗方法

  1. 策略约束(避免过度优化)
  2. Ensemble 模型(集成减少方差)
  3. Dropout 不确定性估计
  4. 短 horizon + 重新规划(控制误差累积范围)
  5. Replay buffer(用真实数据纠正偏移)
  6. KL 正则化(保持先验-后验一致)

理解误差累积机制是设计鲁棒世界模型和有效规划算法的关键。


关键词

误差累积、分布偏移、规划陷阱、模型误差、Lipschitz 常数、指数增长、Ensemble 模型、不确定性估计、短 horizon 重规划、Replay buffer、策略约束、KL 正则化、认知误差、偶然误差、误差传播、过度乐观、分布偏移