Rollout 误差累积
一句话定位:分析多步想象 rollout 过程中模型误差如何随时间步累积,以及由此导致的分布偏移(distribution shift)问题,是世界模型规划能力的核心瓶颈。
前置依赖
- RSSM 基础(先验采样、确定性转移)
- 想象 rollout 基本流程
- 强化学习基础(值函数估计、策略梯度)
- KL 散度与变分推断
核心问题
在多步想象 rollout 中,我们使用世界模型生成的虚拟轨迹进行规划和策略学习。然而,世界模型不是真实环境的完美表征——它存在两类误差:
- 认知误差(Epistemic Uncertainty):由于训练数据不足,模型对某些状态区域不熟悉
- 偶然误差(Aleatoric Uncertainty):由于环境本身的随机性,即使完美模型也无法完全消除
当使用模型生成的多步轨迹进行策略学习时,这些误差会随时间步累积放大,导致:
- 预测的隐状态越来越偏离真实隐状态
- 基于错误隐状态做出的决策越来越差
- 规划的奖励越来越高,但真实奖励越来越低(过度乐观)
这种”模型自我欺骗”的现象称为分布偏移(Distribution Shift)或规划陷阱(Planning Trap)。
数学分析
A. 单步误差模型
设真实环境动态为
令
单步误差:
假设误差主要由两部分组成:
- 转移误差:
— 转移函数的偏差 - 观测误差:
— 编码器的偏差
B. 误差累积的线性分析
假设单步误差服从线性增长的模型:
单步误差传播:
其中
递推展开:
关键观察:
- 指数级增长:如果
,误差以指数级增长 - 初始误差放大:初始隐状态的误差会被
放大 - 累积效应:每个时间步的误差都对最终误差有贡献
C. 非线性误差分析
在实际中,转移函数
- 自引用放大:错误的隐状态导致错误的动作,错误的动作又加剧隐状态误差
- 不确定性放大:误差较大时,模型的不确定性也增大,导致采样多样性降低
- 吸引盆收缩:错误累积使轨迹进入模型从未见过的状态区域(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 形式:
- 预测
步 - 执行第一步
- 获得真实观测,重新预测
- 重复
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 的推导
设真实转移函数为
假设:
和 是 -Lipschitz 的- 初始误差
- 采样误差
(先验 vs 真后验) - 动作误差
单步误差边界:
其中
递推展开:
令
展开:
关键结论:
- 如果
(转移函数膨胀),误差指数增长 - 如果
(转移函数收缩),误差收敛到稳态 - 如果
(等距映射),误差线性增长
B. 规划陷阱的数学形式
策略学习目标:
真实环境中的期望回报:
两者差距:
其中
更紧的界(假设奖励误差有界):
令
与前后内容的衔接
- 前置内容:想象 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, varianceC. 短 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_rewardD. 关键实现细节
不确定性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 过程中,模型误差会以指数级或超线性方式累积,导致预测的隐状态和奖励与真实值严重偏离。
误差来源:
- 观测重建误差(编码器-解码器)
- 转移函数误差(模型不完美)
- 先验-后验不一致(训练-推理差异)
- 奖励预测误差
误差累积数学:
- 若转移函数 Lipschitz 常数
,误差指数增长
对抗方法:
- 策略约束(避免过度优化)
- Ensemble 模型(集成减少方差)
- Dropout 不确定性估计
- 短 horizon + 重新规划(控制误差累积范围)
- Replay buffer(用真实数据纠正偏移)
- KL 正则化(保持先验-后验一致)
理解误差累积机制是设计鲁棒世界模型和有效规划算法的关键。
关键词
误差累积、分布偏移、规划陷阱、模型误差、Lipschitz 常数、指数增长、Ensemble 模型、不确定性估计、短 horizon 重规划、Replay buffer、策略约束、KL 正则化、认知误差、偶然误差、误差传播、过度乐观、分布偏移