
1. 先搞清楚hindsight这个词在强化学习里到底指什么Hindsight 这个英文单词平时翻译成“事后聪明”多少带点贬义——事后诸葛亮嘛。但在强化学习领域它却是一个核心算法、一种让智能体从失败里挖出学习信号的关键机制Hindsight Experience Replay简称 HER。我第一次在 FetchReach 环境上跑通 HER 时的反应是原来失败的经验可以这样重新利用。如果你刚接触强化学习大概率会遇到这样一个困境搭好了 DDPG 或 SAC环境也配好了但 agent 训练了几十万步成功率还是零。问题多半出在奖励太稀疏——比如机械臂抓取物体只有“抓住”才给 reward其余所有探索都得不到任何反馈。HER 就是专门针对这类目标达成型任务设计的它通过重写经验池里失败样本的目标让算法从“没抓到”里学到“怎么接近目标一点”从而解决稀疏奖励带来的冷启动问题。这篇文章的目标读者是两类人一是刚入门强化学习、想在机器人控制或策略规划任务里跑通稀疏奖励算法的同学二是已经在用 off-policy 算法DDPG、SAC、TD3但训练效果不理想、想找一个通用加速手段的工程师。我会把 HER 的原理、代码实现、超参调优和实际踩坑都讲透让你看完能直接上手复现。2. 核心算法机制拆解目标重标注Goal Relabeling2.1 从普通经验回放到事后经验回放先理解传统经验回放Experience Replay干了什么agent 与环境交互产生一条条转移样本(状态, 动作, 奖励, 下一状态)把这些样本存进 buffer训练时随机采样小批量打破时间相关性让离线数据能被反复利用。这个机制本身不产生新知识只是让旧数据更高效地被用来更新网络。HER 在思路上往前迈了一大步它不只复用经验还改变经验里记录的目标字段。假设一个机械臂的任务是抓住红色方块某次 rollout 中它没有抓到红色方块但碰到了旁边的蓝色方块。在普通经验回放中这条轨迹的奖励全为 -1或 0是纯粹的负样本对学习“如何抓红色方块”几乎没贡献。在 HER 中我们会额外生成一组“改写了目标”的样本把这条轨迹的目标从“红色方块”改成“蓝色方块”。改写之后这些原本失败的转移就变成了“成功经验”——因为 agent 确实到达了蓝色方块。然后把这组改写后的样本一起丢进经验池。这样算法就能从一次失败的尝试中学到“如何朝某个可达目标移动”的有效策略。直觉上这像是给学生批改卷子原题是“证明费马大定理”学生不会但他证明了“勾股定理成立”。老师不会说这题零分而是告诉他你至少证明了勾股定理这个能力是有价值的。下一次遇到类似问题时他会更有意识地调用这个中间能力。HER 的核心哲学就是这样每个失败都隐含着一个已经实现的新目标把这个新目标显式写进经验里学习信号就出现了。2.2 目标条件化 MDP 与奖励函数的重塑HER 适用的任务必须能形式化为 goal-conditioned MDP。与普通 MDP 的区别在于环境里多了一个目标变量g状态转移变成(s_t, g, a_t) - s_{t1}奖励函数也变成r(s_t, a_t, g)。每个 episode 开始时会随机采样一个 goalagent 的目标就是在 episode 结束时让状态满足这个 goal。以机械臂抓取为例状态s包含机械臂关节角度、末端位置和物体位置goalg是希望物体到达的目标位置。奖励函数一般写成稀疏形式r 1如果 || 物体当前位置 - g || 阈值 r 0否则这种稀疏奖励带来的问题是在探索初期agent 完全碰不到成功状态所有奖励都是 0梯度信号接近于无。策略网络只能靠随机探索瞎撞训练极其缓慢。HER 用目标重标注天然解决了奖励信号缺失的问题把一次 episode 中实际到达的某个状态设为新目标g在这条轨迹末尾新目标必然被满足所以最后一步的奖励是成功奖励。看起来只是“改了一个字段”实际效果是给整条轨迹注入了稀疏但真实的学习信号。这个信号不像 reward shaping 那样依赖人工设计势函数它是从环境真实反馈中提取的不会引入误导性偏好。2.3 重标注目标的数学直觉与实现伪代码重标注目标的具体实现并不复杂。假设某条 episode 的真实目标为g轨迹长度T每一步的状态、动作、奖励、下一状态都记录在案。HER 会生成若干条“虚拟轨迹”每条虚拟轨迹与原始轨迹共享所有状态和动作序列只把 reward 重新计算一遍并把目标改为从当前 episode 中实际访问过的某个状态中提取的目标。常用的提取方式有四种final取轨迹最后一步的状态目标、random从轨迹中随机选一个状态、future从当前时刻 k 步之后的状态中随机选、episode从当前 episode 任意状态中随机选。实验中最常用的是future它保留了时间上的因果顺序让重标注后的轨迹看起来更自然。伪代码可以这样写采集一条 episode真实目标为 g 把原始样本 (s_t, a_t, r_t, s_{t1}, g) 存入 buffer for t 0...T-1: g 从该 episode 的 t1...T 状态中随机抽取一个目标 根据稀疏奖励函数重新计算 r_t 把 (s_t, a_t, r_t, s_{t1}, g) 存入 buffer这里有个关键细节重标注不改变动作和状态转移只改变目标和奖励。因为策略的目标条件是“看到目标、输出动作”更换目标字段后同一段状态转移就可以用于学习不同的目标策略。这就是为什么 HER 能大幅提升样本效率——一条轨迹被一条变多条而且每条都有明确的学习方向。3. 动手实现 HER从环境搭建到训练脚本3.1 环境选择与目标化处理我在实际项目中用得最多的是 OpenAI Gym 里的 Fetch 系列环境尤其是FetchReach-v1和FetchPush-v1。前者是“机械臂末端到达目标点”非常直观适合验证算法实现后者是“推动物体到目标点”涉及物体动力学难度上了一个台阶。如果你手头没有这些环境也可以用自定义的二维点导航任务状态是坐标(x, y)目标是目标点(gx, gy)奖励是距离小于阈值则成功。这类简单任务能帮你快速定位算法 bug别一上来就上真实机器人或重型仿真。把普通环境改造成 goal-conditioned 环境需要关注几个接口reset()返回初始状态和随机采样的 goalstep(action)返回下一状态、稀疏奖励、done 标志和额外信息compute_reward(achieved_goal, desired_goal, info)单独抽出来方便 HER 在重标注时重算奖励。建议把“状态向量”拆成observation和desired_goal两个部分这样重标注只需要替换desired_goal字段不需要动observation。3.2 PyTorch 实现要点网络结构、buffer 与重采样逻辑我用的策略网络结构是三层 MLP输入是状态和目标拼接后的向量输出层根据算法不同有所区别。DDPG 的话输出连续动作SAC/TD3 则额外输出 Q 网络。激活函数用 ReLU最后一层用 tanh 把动作限制在 [-1, 1] 之间。关键在于状态和目标必须做归一化。Fetch 环境的观测数值范围差别很大关节角度和物体坐标不在一个量级直接拼起来会让网络训练极不稳定。最简单的做法是用环境的observation_space.high和low做 min-max 归一化把输入压缩到 [0, 1] 左右。经验回放 buffer 需要支持“为每条样本额外存储 achieved goal”。我一般用namedtuple或者字典来存(obs, achieved_goal, action, next_obs, next_achieved_goal, reward, done, desired_goal)。普通的 DQN 和 DDPG buffer 只存(s, a, r, s, done)HER 多出的字段就是用来做重标注的原料。重标注逻辑放在“采样小批量”时执行而不是在数据存入 buffer 时执行这个顺序很重要。每一轮采样先从 buffer 里随机抽一批真实样本这批样本中有一定比例比如 50%是原始样本剩余比例的样本经过重标注处理。这样做的好处是每个 batch 同时包含真实目标和虚拟目标的样本策略网络既学到真实任务目标也从虚拟目标中学到合理的动作分布。下面是一个简化版的重标注采样函数方便你理解def sample_batch_with_her(buffer, batch_size, replay_k4): # 从 buffer 随机抽取真实经验 real_batch buffer.sample(batch_size) her_batch [] for item in real_batch: # 30% 概率保留原始目标70% 概率重标注 if np.random.random() 0.3: her_batch.append(item) continue # 从该样本所属 episode 的未来状态中选一个新目标 sample_episode episode_buffer[item.episode_id] future_idx np.random.randint(item.timestep 1, len(sample_episode)) new_goal sample_episode[future_idx].achieved_goal new_reward env.compute_reward( item.next_achieved_goal, new_goal, None ) her_batch.append(item._replace(desired_goalnew_goal, rewardnew_reward)) return her_batch注意看_replace方法我保留了原始样本的状态、动作、下一状态只替换了desired_goal和reward。这就是 HER 的全部魔法。当然真实工程里还要处理 episode 边界、done 标志等细节但核心逻辑就是这么简单。3.3 训练配置和超参数参考k 值、future 概率与 buffer 大小HER 论文里最核心的超参数是k它表示“每个真实样本额外生成多少个重标注样本”。论文里的默认值是 4也就是每个真实经验对应 4 个虚拟经验buffer 容量自然也要相应扩大。k越大经验池中虚拟目标的占比越高算法越激进样本效率更高但也可能引入过多噪声导致策略偏向于那些“容易实现的目标”而忽略真实目标。另一个关键超参是重标注策略的选择和概率。我实测下来future策略效果最好因为它保证新目标在该样本之后的时间步确实被达到过不存在“虚构目标”的问题。重标注概率一般设为 0.8 或 0.5不要把 100% 的样本都重标注留一部分真实目标样本让算法记住原始任务是什么。你可以在训练开始时设置较大的重标注概率后期逐步降低让策略从“广泛探索各种可达目标”过渡到“聚焦真实目标”。我用得比较顺手的超参组合如下超参数推荐值说明replay_k4每个真实样本额外生成 4 个虚拟样本batch_size256 ~ 1024大 batch 有助于稳定 Q 网络训练buffer_size1e6Fetch 环境训练步数多buffer 要大重标注目标策略future从 t1 之后的状态中随机选重标注概率0.5 ~ 0.8不要 100% 重标注actor/critic 学习率1e-3 / 1e-3Adam 优化器必要时调低 critic 学习率探索噪声0.2 高斯噪声DDPG 场景下训练后期可衰减到 0.05训练步数1e6 ~ 2e6FetchReach 约 1e6 步即可收敛FetchPickAndPlace 需要更多这些参数不是万能公式但作为起点非常好用。如果你发现训练不收敛优先调整批量大小和重标注概率其次是学习率和探索噪声。后面我会专门讲几个典型的调参失败案例。4. 训练坑点与调试心得实操中一定要避开的雷区4.1 为什么成功率总是零目标空间与状态空间不匹配我刚开始把 HER 应用到自定义环境时遇到了一个很隐蔽的问题环境的目标空间采用的是“相对坐标”即目标点是相对于机械臂基座的偏移量而状态空间里的物体位置是绝对坐标。HER 重标注时从轨迹中提取的是绝对坐标然后直接替换掉相对坐标目标这就导致虚拟样本里的 goal 和 observation 在语义上错位整个训练瞬间崩塌。这种问题非常难排查因为代码逻辑完全正确loss 甚至会下降但 rollout 成功率始终是零。我当时的排查手段是把重标注后的样本打印出来人工检查 goal 和 achieved_goal 之间的数值关系。如果 reward 计算明明显示“成功”但目标是相对坐标、状态是绝对坐标几乎可以断定是空间不匹配。解决办法很简单统一用绝对坐标作为 goal 的表示或者在重标注时应用与初始采样时相同的坐标变换。另一个常见问题是done标志设置不当。在 goal-conditioned 任务里不要用“失败即终止”的逻辑。比如机械臂推动物体如果物体掉出桌子就终止 episode那么 HER 重标注时目标会被设置成某个掉出桌子的位置这显然是无意义的。正确做法是每个 episode 固定最大步数所有未成功的轨迹自然终止让算法有足够多“接近但未完成”的样本可学习。4.2 评估指标不能只看 loss怎么衡量 HER 的真实效果在稀疏奖励任务中actor 和 critic 的 loss 曲线几乎没有参考价值——它们可能缓慢下降但策略的成功率依然是零。原因在于 off-policy 算法训练时Q 函数在稀疏奖励下很难准确估计远距离状态的价值。所以我强烈建议每隔固定步数做一次实测 rollout统计成功率并把这个指标作为训练是否有效的唯一判据。FetchReach 环境达到 80% 以上成功率通常需要 60 万到 100 万步如果 100 万步后仍是零成功率说明问题不在训练时长而是某个环节有 bug。我常用的评估方式是关闭所有探索噪声固定初始状态和随机种子连续跑 50 个 episode统计成功比例。这些评估 episode 不计入训练 buffer避免干扰样本分布。同时记录“平均最小距离”这个辅助指标即整个 episode 中物体与目标的最近距离。这个指标即使在没有成功样本时也能反映策略是否在进步——比如从“平均距离 1.0”降到“平均距离 0.2”说明策略确实在学会靠近目标只是还差最后一步。这个指标对训练初期的判断非常有帮助。4.3 从 HER 到后续扩展你还能往哪个方向走HER 本身是一个框架不是最终形态它有非常多扩展方向。比较经典的是把 HER 与优先级经验回放结合让“虚拟目标与当前目标差异大”的样本有更高的采样权重加速对难目标的覆盖。另一个方向是目标生成与课程学习由于 HER 重标注的目标都来自真实轨迹目标分布与当前策略能力强相关策略变强后“可触达目标”会越来越多相当于自动形成课程。你可以在此基础上加入目标分布建模用 VAE 或能量模型学习一个适合当前策略的目标分布进一步加快训练。如果做多智能体或分层强化学习HER 的思想也很有用上层策略负责选择子目标下层策略负责实现子目标子目标是否达成可以用重标注来提供中间奖励。此外近几年的研究还尝试把 Hindsight 思想引入离线强化学习解决离线数据中奖励稀疏的问题通过重标注构造更稠密的监督信号。可以说理解了 HER你就掌握了一个能反复复用的思想武器而不只是一个算法实现。4.4 几个容易踩但很少被提及的细节最后分享几个我在工程里反复踩过的坑。第一重标注时不要把 done 标志也一并复制。原始轨迹中最后一步的 done 是因为 episode 结束而不是因为成功。如果把 done 复制到虚拟样本里Q 网络会学到“到达任何重标注目标都会终止”的错误信号。正确做法是只有在重标注目标确实在最后一步被满足时才把 done 设为 True否则设为 False。第二actor 网络的更新频率要低于 critic。HER 的虚拟样本让 critic 的学习信号更密集但 actor 如果更新太频繁会放大 Q 函数的近似误差。我一般设定 actor 每更新 2 次 critic 才更新 1 次或者在 actor 更新时加入梯度裁剪。第三注意随机种子。HER 对探索噪声和初始状态分布非常敏感同一个超参组合换一个随机种子可能成功率从 90% 掉到 50%。我习惯固定 5 个种子跑多次实验取中位数作为最终结果而不是单次实验的最高分。这四个点看起来是小问题但在实际训练中往往决定了你调三天还是调三周。