TimeLimit 不是终止:bootstrap 要看 terminated
用 Gymnasium 的 terminated/truncated 分离重置条件与价值边界,并处理 replay、GAE 和自动重置环境里的最后观测。

机器人仿真每 步由 TimeLimit 截断。旧训练循环把 terminated or truncated 合成 done 存进 replay,DQN 就把所有第 步都当成吸收终态,目标值在时间边界出现一条不该有的断崖。episode 确实要 reset,但价值函数不一定该停止 bootstrap——这是两个不同问题。
Gymnasium 的五元组返回值把它们拆开:
next_obs, reward, terminated, truncated, info = env.step(action)
episode_ended = terminated or truncatedterminated=True 表示到达 MDP 定义的终态,例如成功或碰撞;truncated=True 通常表示 MDP 外部的时间限制切断了采样。一步 TD 目标应使用
因此真正终止时不 bootstrap,时间截断时仍使用最后状态的价值。两种情况都要 reset 环境,但不能共用同一个 mask。
replay 里保留两个标志
最直接的循环是:
next_obs, reward, terminated, truncated, info = env.step(action)
replay.add(
obs=obs,
action=action,
reward=reward,
next_obs=next_obs,
terminated=terminated,
truncated=truncated,
)
if terminated or truncated:
obs, info = env.reset()
else:
obs = next_obs采样 batch 后,DQN 目标只用 terminated 关掉下一状态值:
with torch.no_grad():
next_q = target_net(next_obs).amax(dim=-1)
target = reward + gamma * (~terminated).float() * next_qtruncated 仍然值得存:它用于 episode 统计、rollout 边界和排查时间上限是否过短。若只存合并后的 done,训练结束后已经无法恢复正确语义。
GAE 需要两个 mask
固定长度 rollout 在截断点结束时,TD residual 仍应使用最后观测的价值:
但反向递推 advantage 时,不能穿过 reset 把下一个 episode 接上来。因此实现里通常还需要一个 trace continuation mask:
也就是说,截断点“用最后状态 bootstrap,但不把新 episode 的 advantage 串回来”。只留一个 done 变量很难同时表达这两件事。
自动 reset 时最容易取错状态
普通单环境按上面的顺序手动 reset,next_obs 就是被截断轨迹的最后观测。向量环境或自动重置 wrapper 可能在返回时已经把 observation 换成新 episode 的初始观测,并把真正的最后观测放进 info 的 final-observation 字段。若拿重置后的 observation 计算 ,公式写对了,数据仍然是错的。
不同 Gymnasium 版本与 vector autoreset 模式对 final observation 的字段和时机有差异,接入时要对当前运行版本做一次打印测试:构造一个两三步必截断的环境,逐项打印 observation、terminated、truncated 和 info,确认 replay 中截断 transition 的 next_obs 是重置前的最后状态。
一个不依赖环境的数值检查
假设奖励为 ,折扣为 ,最后状态价值为 。终止目标应为 ,截断目标应为 :
import torch
reward = torch.tensor([1.0, 1.0])
next_value = torch.tensor([10.0, 10.0])
terminated = torch.tensor([True, False])
target = reward + 0.9 * (~terminated).float() * next_value
torch.testing.assert_close(target, torch.tensor([1.0, 10.0]))随后再跑短环境,检查时间上限前后 value target 的均值是否出现人为跳变。修正 mask 后学习曲线不一定立刻变好,但边界处的 target 应符合上面的手算结果。
还有一个例外:如果固定时限本来就是任务定义的一部分,例如棋局只允许剩余 步,那么“剩余时间”必须进入 observation,使状态保持马尔可夫性;到时限可被定义为真正 termination。不能看到步数上限就机械地标成 truncation。判断标准不是 episode 为什么停了,而是这个边界是否属于智能体正在求解的 MDP。
相关
也可以看看
johan's blog