
1. 为什么“事后视角”能破解稀疏奖励的死局1.1 强化学习里的稀疏奖励到底是什么我最早接触 hindsight 这个词是读一篇讲人类决策偏差的文章“事后诸葛亮事前猪一样”——人类总是擅长在事情结束后解释一切却很难在事情开始前正确预判。后来啃强化学习论文看到 OpenAI 提出的 Hindsight Experience ReplayHER才意识到代码世界里同样充满这种“事后聪明”而且它还能真正派上用场成为大幅提升训练效率的关键手段。先说说稀疏奖励为什么惹人头疼。假设你训练一个机械臂去抓取桌面上的杯子动作空间可能是 4 维、7 维甚至更高一次成功的抓取需要关节角度、末端坐标、夹爪开合一系列动作精准配合。如果只在“成功抓住杯子”时才给 1 奖励其余所有探索都拿 0 分那么智能体面对的是一个几乎所有尝试都等于“无效信号”的环境。Deep Deterministic Policy GradientDDPG、TD3、SAC 这类常见算法靠的是用奖励信号估计 Q 值、更新策略但奖励全为 0 的时候Q 值网络根本没有梯度可言。网络输出的动作再怎么探索都像是闭着眼睛在迷宫里瞎摸走一百步和走一万步获得的信息几乎一样没区别全是零。我把一个简单的 2D 点目标环境丢给 DDPG 时印象极其深刻连续跑了 5000 个 episode成功率稳定在 0%。不是算法崩了是算法完全“躺平”了——因为所有尝试都拿不到正奖励critic 学不到任何有价值的东西actor 也只会输出一团接近随机的动作。很多刚上手强化学习的人在这个阶段就开始怀疑是自己的代码写错了实际上多半是奖励结构本身就没给算法留活路。1.2 常见解法为什么总是治标不治本面对稀疏奖励最本能的反应是“奖励塑形”reward shaping。既然成功太难那就给中间状态加点分数比如让机械臂离杯子每近 1 厘米就奖励 0.1。听着合理但落地时你会遇到一个经典麻烦你定义“靠近”的方式往往不是最优策略需要的“靠近”方式。机器人可能学出绕着杯子原地转圈的诡异行为因为那样也能持续刷分更麻烦的是人为设计的中间奖励很容易和真实目标冲突训练出来的策略在评测时华丽翻车。另一条路是内在好奇心curiosity-driven exploration让智能体对“没见过”的状态产生探索冲动。这个方法在游戏环境里效果不错但放在连续控制任务上它会导致智能体沉迷于学习控制机械臂“乱甩”这种高随机性行为而不是朝目标前进。因为“甩动”产生的状态变化方差大、预测误差高好奇心分数也高直接压过了任务信号。还有一种是课程学习curriculum learning先简单后难逐级提升任务难度。思路没问题但任务难度怎么定义、课程怎么自动编排又是一堆工程问题。我实际体验下来大多数场景里频繁调整课程反而把训练过程搞得更不稳定。HER 恰恰没有从这些方向下手。它反问了一个非常反直觉的问题既然这次尝试没有达到目标那我们为什么不把“实际达到的状态”当作目标重新解释这条经验呢把“失败”改写成了“另一种成功”经验立刻就有了学习价值。这就是 hindsight 四个字母背后的核心哲学与其纠结这次为什么没成功不如从已经发生的结果里反向挖掘训练信号。1.3 HER 的切入点失败也包含大量可学习信号把“事后”思想落到数据层面其实非常直白。假设环境给智能体下发的目标是 g比如杯子位于坐标 [0.5, 0.2, 0.1]智能体这次尝试最终停在状态 [0.45, 0.18, 0.09]。显然它没有完成任务奖励为 0这条 transition 在传统回放池里就是一条毫无价值的样本。但 HER 换个思路把这次 episode 的“目标”改写为 [0.45, 0.18, 0.09]也就是它实际达到的位置。从改写后的目标看这条 transition 的结局是“成功”的奖励变为 1done 标记变为 True。一条原本被丢弃的失败数据经过程序员的奋力一跃直接变成了一条标准的成功数据。这么做看起来像是在“修改标签刷成绩”但它的合理性和有效性在于一个深刻的道理对于一个连续任务智能体在探索过程中抵达过的每一个状态本身都可以视为“目标空间中的采样点”。目标空间也正是智能体需要学会的“技能空间”如果能学会到达 [0.45, 0.18, 0.09]那么下次面对相近目标时它就积累了优势。这个切入点有个很妙的好处它不需要改奖励函数、不需要设计课程、不需要额外估测好奇心误差。你需要做的只是让系统在存储经验时同时记录“目标”和“实际到达状态”然后在采样时把一部分样本的目标替换成后者重新计算奖励。操作轻、理论清晰、工程改动小这几乎是我见过性价比最高的稀疏奖励方案之一。2. HER 核心机制拆解目标重标记到底改了什么2.1 一条经验的完整生命周期是怎么划分的理解 HER 之前必须先把一条强化学习经验拆干净。常规做法里一条 transition 长这样(s, a, r, s, done)分别代表当前状态、动作、奖励、下一状态、是否终止。但在面向目标的任务里状态空间和观测空间通常被分割为两部分一部分是“和任务无关但描述系统自身状态”的观测 o例如关节角度、速度另一部分是“描述目标状态”的目标 g。智能体收到的完整观测是s concat(o, g)也就是系统状态拼接上目标任务。比如机械臂抓取任务中o 是机械臂所有关节角和末端坐标g 是物体目标位置2D 点目标任务中o 是当前点的坐标g 是期望点的坐标。环境给出的奖励函数 r(s, g) 通常是用距离阈值来判断的判断的是“当前状态 o 是否足够接近目标 g”。HER 对经验做的处理正在于一条 transition 在训练时并非只能使用它“当时”被定义好的目标。重新定义任意一个不同的目标 g公式r(s, g)就产出一条“新”的奖励done也会随之改变。目标重标记就是利用这个特性把原本失败结局下的奖励从 0 改写为 1。值得注意的是s 和 s 本身完全不变变的只是“这个状态对哪个目标而言是有价值的”。2.2 四种重标策略的细节对比HER 原论文里给出了四种为 transition 重新挑选目标的方式我分别展开说一下final 策略选取整条 episode 结束时到达的状态作为新目标。实现最简单每个 episode 只需要记录最后一个状态采样时把同一 episode 内所有 transition 的目标全部改写为这个最终状态。缺点是时间跨度太大episode 早期状态和最终状态之间可能隔着数量可观的步骤逐条计算出来的奖励多为 0数据利用率仍然偏低。random 策略从经验回放池里随机抽一个状态作为新目标。代码写起来极省事但随机目标往往和当前 transition 的真实轨迹跨度相差甚远训练信号被稀释得很严重。实测效果基本垫底。episode 策略从同一 episode 内任意采样一个未来状态作为新目标。它比 random 好一些因为至少目标和轨迹在同一个 episode 的上下文里存在实际的轨迹联系。future 策略从同一个 episode 内、且时间上晚于当前 transition 的未来状态中采样一个新目标。这个策略在实际任务里几乎总表现最优也是我日常实现里默认选择。原因很直观从当前状态到未来某个状态这段轨迹是真实发生过的意味着“在上一个状态施加了某个动作之后状态转移到了目标附近”。这个时序关系让智能体可以用真实动力学信息来学习“怎么接近目标”。如果从过去的状态采样逻辑上就变成要回到曾经离开的地方轨迹闭合并不可行。把四种策略放在一张表里差异一目了然策略新目标来源实现成本实际效果适用场景final同一 episode 最终状态低一般任务轨迹较短终点能代表目标random任意经验池状态最低较差简单探索任务可用作基线episode同一 episode 任意状态中较好轨迹明确、目标空间连续future同一 episode 且晚于当前的状态中最佳连续控制、机械臂抓取、导航2.3 为什么 future 策略效率最高从概率角度看future 策略把“当前状态通过真实动作序列过渡到未来状态”这一过程中蕴含的运动学信息直接注入训练。以 2D 点目标为例假设智能体在 t 时刻位于坐标 A执行动作 a 后 t1 时刻到达坐标 B。如果每次都用 B 当作新目标critic 学到的就是“在 A 施加 a确实能让系统更接近 B”这天然与运动技能一致。再对比 final 策略一条长度为 100 的 episode 里如果只把目标设为最终状态t1 时刻的 transition 与最终状态之间的路径有 99 步距离奖励仍为 0学习信号在长距离下被稀释。future 策略在时间上任意采样样本的时间跨度从 1 到 99 都有分布距离梯度自然更丰富。更微妙的是future 策略还天然提供了一个“自适应的难度课程”训练早期智能体运动能力差轨迹上状态散布范围大未来状态距离当前状态远目标跨度也大训练后期智能体逐渐学会控制轨迹越来越紧凑采样到的目标跨度自然变小学习重点转向“精调”和“接近”。我曾经在一个导航任务里把 future 替换成 final成功率从 87% 掉到 51%足以说明这个策略差异对最终效果的影响。2.4 HER 与 off-policy 算法的配合逻辑还要说一个关键前提HER 只能配合 off-policy 算法使用最经典的搭配就是 DDPG、TD3、SAC。原因在于 off-policy 算法维护一个经验回放池允许“经验被反复使用”而且允许我们在使用阶段修改经验。on-policy 算法如 PPO、TRPO 每次从环境采集一批数据用完就丢弃理论上也能做重标记但必须把重标后的样本重新用于策略更新这在实现上就和 on-policy 的框架拧着来。所以实际落地时尽量选择兼容回放池的算法。我在实际项目中用 DDPG HER 最多原因有三一是 DDPG 对连续动作空间的适配成熟actor-critic 结构清晰二是它的 critic 直接拟合 Q(s, g, a)天然把 g 作为网络输入的一部分重标目标可以直接替换输入无需改动网络结构三是 DDPG 代码简单部署和调试成本低。想追求更高性能和稳定性也可以换成 TD3两个 target critic 对 Q 值估计的压制更稳我在仿真环境里测试的结果是 TD3 HER 在样本效率上略优超参数也更敏感取舍需要自己做。3. 从零搭建 HER环境设计、缓存实现与训练整合3.1 自建一个 2D 点目标环境跑通最小闭环先说环境设计。为了验证 HER 的逻辑我习惯用 gym 风格的 2D 点目标任务做最小闭环。状态空间很简单一个点在平面上移动动作是二维速度增量目标也是一个二维坐标。观测 o 是当前点的坐标(x, y)目标 g 是期望坐标(gx, gy)。稀疏奖励定义为当且仅当点和目标距离小于阈值时返回 1否则返回 0。这个环境麻雀虽小但五脏俱全动态、目标、稀疏奖励、done 机制都和真实机械臂任务对偶。import numpy as np import gym from gym import spaces class PointGoalEnv(gym.Env): def __init__(self, threshold0.05): super().__init__() self.threshold threshold self.observation_space spaces.Box(low-1.0, high1.0, shape(4,), dtypenp.float32) self.action_space spaces.Box(low-0.5, high0.5, shape(2,), dtypenp.float32) self.current None self.goal None def reset(self): self.current np.random.uniform(-0.5, 0.5, size(2,)).astype(np.float32) self.goal np.random.uniform(-0.5, 0.5, size(2,)).astype(np.float32) return self._get_obs() def _get_obs(self): return np.concatenate([self.current, self.goal]).astype(np.float32) def step(self, action): self.current np.clip(self.current action, -1.0, 1.0) dist np.linalg.norm(self.current - self.goal) reward 1.0 if dist self.threshold else 0.0 done reward 1.0 return self._get_obs(), reward, done, {achieved_goal: self.current.copy()}注意这里观测维度是 4前两维是当前位置后两维是目标任务。info中单独返回achieved_goal这是 HER 能够工作的原料。很多刚上手的人只在reset或step返回值里保留原始观测而忽略achieved_goal结果后面实现重标时发现没有“实际到达状态”可用整个方案就哑火了。3.2 HER replay buffer 实现的两大关键点实现 HER buffer最核心的不是读样本、写样本而是保证重标的目标来自同一 episode 的时序上下文。我把存储结构设计成三层一个全局 buffer 存放所有 transition一个临时列表存放当前 episode 的 transition 序列以及一个“episode 索引表”记录每个 épisode 在全局 buffer 中的位置范围。采样时按比例切分一部分保持原始目标不动另一部分做 future 重标。重标时从同一个 episode 的后续状态里抽取achieved_goal替换原目标并重新计算 reward 和 done。class HERBuffer: def __init__(self, capacity, batch_size, her_ratio0.8): self.capacity capacity self.batch_size batch_size self.her_ratio her_ratio self.buffer [] self.episode_indices [] self.current_episode [] def add(self, transition): # transition: (obs, achieved_goal, action, reward, next_obs, done, original_goal) self.current_episode.append(transition) def end_episode(self): start len(self.buffer) self.buffer.extend(self.current_episode) end len(self.buffer) self.episode_indices.append((start, end)) self.current_episode [] if len(self.buffer) self.capacity: overflow len(self.buffer) - self.capacity self.buffer self.buffer[overflow:] self._rebuild_episode_indices() def _rebuild_episode_indices(self): # 实际工程中需要基于 episode_id 重建索引这里简化处理 self.episode_indices [] def sample(self): normal_n int(self.batch_size * (1 - self.her_ratio)) her_n self.batch_size - normal_n normal_samples np.random.choice(len(self.buffer), normal_n, replaceFalse) batch [] for idx in normal_samples: batch.append(self.buffer[idx]) for _ in range(her_n): t_idx np.random.choice(len(self.buffer)) trans self.buffer[t_idx] # 找到该 transition 所属 episode ep_start, ep_end self._find_episode(t_idx) # future 策略采样 t_idx 之后的状态 future_idx np.random.randint(t_idx 1, ep_end) if t_idx 1 ep_end else t_idx new_goal self.buffer[future_idx][achieved_goal] new_reward 1.0 if np.linalg.norm(trans[achieved_goal] - new_goal) self.threshold else 0.0 new_done new_reward 1.0 batch.append(( trans[obs], trans[achieved_goal], trans[action], new_reward, trans[next_obs], new_done, new_goal )) return batch3.3 与 DDPG 训练循环整合时的输入结构改动DDPG 模块本身不需要大改唯一要保证的是 actor 和 critic 都把“目标”作为网络输入的一部分。以 critic 为例输入是(obs, goal, action)输出是 Q 值估计。在 HER 的流程下obs 对应的原始 transition 里不存目标而是把goal单独传给网络。我在整合时把观测拼装重构成了obs concat(o, g)的格式让拼接发生在进入网络前这样端到端训练时只需确保 replay buffer 返回的 goal 替换到对应位置即可。训练循环伪代码如下for episode in range(total_episodes): obs env.reset() episode_transitions [] done False while not done: action actor.get_action(obs, noiseexploration_noise) next_obs, reward, done, info env.step(action) episode_transitions.append((obs, info[achieved_goal], action, reward, next_obs, done, obs[2:4])) obs next_obs for t in episode_transitions: her_buffer.add(t, episode_idepisode) her_buffer.end_episode() if len(her_buffer) warmup: for _ in range(train_steps): batch her_buffer.sample() critic_loss train_critic(batch) actor_loss train_actor(batch) update_target_networks(tau)我在训练时每 episode 只采集一条轨迹但train_steps会设置成几十甚至上百。因为 HER 的核心价值在于“每一条真实轨迹能产生大量重标样本”训练预算分配必须向重标采样倾斜。我最初设置成每 episode 只训练一次效果远不如每 episode 训练 50 次后来查文献发现 HER 原论文里对每个 episode 的训练次数就不少这个超参值得加大。3.4 奖励重算的关键距离阈值和 done 标记的联动重标完成的下一步是重算奖励这一步看起来简单却是很容易写错的细节。在原任务里reward 1.0 if distance threshold else 0.0重标后new_goal是实际到达的achieved_goal中的某个未来状态。理论上该 transition 的achieved_goal与new_goal的差距不是零——毕竟achieved_goal和未来状态是两个不同采样点的坐标。所以重算奖励时必须重新计算“当前状态到新目标”的距离而不是简单地把 reward 直接置为 1。如果设置new_reward 1.0而不管距离critic 就会产生大量“离目标很远却宣称成功”的虚假样本整个 Q 值函数被污染。正确的做法是重新调用环境里的距离函数compute_reward(achieved_goal, new_goal, threshold)如果距离小于阈值才给 1否则给 0。很多人最后训练发散查来查去发现就是这里少了一步重算。4. 实验对比从“完全学不动”到成功率 85% 的调参路线4.1 无 HER 基线5000 个 episode 训练曲线的死亡形态我在自己的 2D 点目标环境上做了完整对照实验。第一组是无 HER 的纯 DDPG输入完整观测concat(current, goal)奖励完全按稀疏定义执行。训练 5000 个 episode成功率曲线画出来就是一根直线钉在地上准确说是贴着零轴不动。不是偶尔飘一下是从头到尾完全没有正奖励出现。我当时的排查路径是这样的先怀疑是 Q 值网络没收敛把学习率从 1e-3 降调升调试了十组再怀疑是探索噪声不够把 OU noise 的 scale 从 0.1 拉到 0.5结果噪声加大后动作乱飞更不可能碰阈值最后把阈值从 0.05 放宽到 0.2算法才勉强能学到一点规律成功率爬到 15% 左右。但阈值放宽到 0.2 已经意味着任务本身的逼近难度大幅降低这在真实任务里完全不可接受。说白了无 HER 场景下算法根本没有从“零奖励地带”走出来的机制所有的调参都只是给这句结论换了个皮肤。4.2 加入 HER 之后曲线怎样动起来的第二组加上 HER其余超参完全不动。同样是 5000 个 episode训练曲线在第一阶段就出现了明显抬升大约 300 个 episode 左右成功率开始超过 10%1000 个 episode 达到 40%3000 个 episode 后稳定在 85% 左右。对比无 HER 的零曲线这个差距不是“好一点”而是“能不能训出来的问题”。我认为 HER 对曲线的关键贡献在于它改变了 Q 值函数的训练信号分布。重标之后的样本既有大量“接近成功”的正例也有“接近失败”的负例正负比例相对均衡critic 可以学到比较平滑的 Q 值地形。而没有 HER 时critic 面对的全是零奖励样本等价于在学一个常量函数actor 的梯度也跟着归零。HER 的另一个隐性质变是它把“任务目标”和“技能学习”解耦了智能体学的各种技能都附带在不同的目标标签下被反复使用目标空间的覆盖度显著提高。4.3 future、final、random、episode 四策略的对比表我在同一环境上把四种目标重标策略都跑了一遍超参完全一致结果放在下面策略训练 episode最终成功率曲线特点random500032%上升缓慢波动大final500054%中期有提升后期增速变缓episode500071%平稳提升方差较小future500086%提升最快最终成绩最高random 的 32% 低得有点出人意料。但细想合理随机从全局 buffer 里挑目标大部分目标与当前 transition 的轨迹无关联等价于盲目添加大量噪声标签。final 虽然比 random 高但正如前面所说它把早期状态和最终状态拉得太远学习被长距离稀释。future 的优势不是玄学而是来自“目标与当前状态之间的轨迹真实存在”这一事实它提供的全是可实现的过渡样本。4.4 样本效率提升背后还有一个隐形推手目标空间的覆盖度除了曲线好看HER 还能显著提高目标空间的探索覆盖度。常规 run 里环境在 reset 时随机生成目标但智能体因为总失败基本只在起点附近徘徊整个目标空间的大部分区域根本没被“尝试过”。HER 重标后经验池里会出现大量“从任意状态出发成功到达另一状态”的样本等于变相把目标空间的各个角落都采样了一遍。这相当于给智能体提供了一个天然的自适应课程训练早期它到处乱走乱撞所有乱撞出来的状态都变成“曾经成功过的目标”训练后期它学会精准控制覆盖度重的区域开始集中。这个覆盖度效果在连续动作控制里尤其重要。比如机械臂任务常规探索下绝大多数 episode 都停在初始构型附近目标空间几乎全空有 HER 后机械臂哪怕只是偶然摆过一个新颖的构型这条经验就会以“到达新构型”为目标被存入回放池。这种机制让探索效率看上去像是被外力推了一把每一条“垃圾轨迹”都能变成至少一条有效训练样本。5. 调参与落地时的经验教训这些坑我建议你提前绕开5.1 重标的目标必须是“可达状态”HER 要求重标后的目标必须是在当前环境下真实可达的状态最好是同一 episode 中实际到达过的achieved_goal。我见过有实现直接从整个 buffer 里随机挑一个状态当新目标而不考虑是否属于当前轨迹的邻近空间。这种写法在简单环境里碰巧还能跑但一旦环境动力学有非凸约束比如机械臂关节极限、障碍物随机目标很可能落在不可达区域critic 学的就是“如何飞过墙”这种物理上根本无解的任务训练必然发散。严格限制重标目标必须从同一 episode 的轨迹中采样是保证 HER 有效性的底线。5.2 奖励重算必须用目标距离函数不能直接给正奖励前面代码里已经强调过一次但这里还要展开说HER 对未来目标做重标记时current transition 的achieved_goal和 future state 并不严格相等中间差着一段真实距离。如果重算 reward 时直接写new_reward 1等于告诉 critic这个状态距离目标 0.3 也能拿满分。训练出来的 critic 会认为“距离目标很远”也有高 Q 值actor 自然没有动力把动作精确推到位。我在早期版本里犯过这个错误结果成功率曲线冲到 60% 后就再也上不去后来查了 OpenAI 的基线代码才发现问题出在这个细节上。5.3 episode 边界处理目标不能跨 episode 借用重标目标必须来自“当前 episode 的后续状态”而不是任意历史 episode 的状态。原因很直接轨迹连续性是一种物理事实约束不同 episode 之间不存在真实动力学关联。假如拿上一个 episode 的某个状态作为当前 transition 的新目标critic 和 actor 学到的映射关系是“在当前状态下执行 a就能到达那个状态”但真实环境并没有保证这一点因为跨 episode 的状态之间不存在路径关系。实现时我通常在每个 episode 开始时重置一个episode_id缓存当前 episode 的索引范围重标时严格限定在(t_idx 1, end_idx)里采样。5.4 her_ratio 不是越接近 1 越好her_ratio表示采样时重标样本占批次的比例。我最初理解为“重标越多越好”直接设为 0.98结果训练反而慢了。原因在于重标样本带有标签修改的“人造痕迹”比例过高会让 critic 长期只看虚假轨迹失去对真实目标分布的理解。经过网格调参我发现 0.6 到 0.8 之间最稳定留一部分原目标样本维持 critic 对真实任务的判断同时让足够多的重标样本提供丰富的训练信号。这个比例我还建议在训练过程中动态观察如果成功率曲线平台期来得早可以尝试降 ratio 让 critic 更贴近真实分布如果曲线爬升慢可以适当调高。5.5 探索噪声和重标策略的配合HER 不会取代探索噪声两者是互补关系。HER 负责“事后利用失败的尝试”探索噪声负责“在事前提供多样性的尝试”。没有噪声智能体永远走同一条路重标样本之间的多样性也很低噪声太大状态轨迹过于发散重标后的目标距离跨度太大critic 很难拟合。我在 DDPG 上用的是一阶高斯噪声方差 0.2配合 HER 效果不错OU 噪声我试过稳定性略好但需要额外调均值回归系数工程上略重。TD3 用户可以直接沿用它的平滑噪声机制不需要专门改动。5.6 我发现很有用的监控指标训练时不要只盯成功率还应该监控一个容易被忽略的指标重标样本的平均目标距离。它等于每个重标样本的「当前 transition 实际达到状态」到「新目标状态」之间的距离平滑处理后的趋势能直观反映智能体对目标空间覆盖的均匀程度。训练早期这个值通常大且波动说明轨迹跳跃性强后期逐渐收敛说明智能体的行为越来越可控。如果这个指标始终不下降说明探索噪声过大或 critic 还没拟合好需要先停在这里排查。这个指标帮我排查过好几次“训练假死”的问题比单纯看 loss 靠谱得多。6. 关于 HER 更适合哪些任务以及我最后的几点体会HER 不是万灵药它有一个隐含前提目标本身必须能从状态信息里显式提取出来。也就是说环境至少要能提供一个achieved_goal概念比如机器人坐标、物体位置、积木摆放姿态。如果任务目标是抽象的比如“让对话更自然”HER 就无法直接应用这时要么把目标降维成可量化的嵌入特征要么考虑别的方案。再就是任务描述必须满足“目标空间连续”的特性离散目标空间虽然也能重标但信息密度差很多。我在实际项目中配置 HER 时通常把它当作一个“低成本必选组件”而不是一个“高级黑科技”。先加一个 DDPG/TD3 做底座然后把 HER buffer 接进去cost 方面只增加了一次重标计算和一次 reward 重算代码量不超过 100 行但换来的是从“训不出来”到“稳定收敛”质的改变。对于仿真环境的任务迭代这也是我优先推荐的一个起点在你花大量时间调奖励塑形、设计课程之前先用 HER 把基线建立起来。额外补充一个低成本的扩展方向如果你使用目标条件策略可以进一步把“目标编码器”也纳入网络用自编码器或对比学习把目标状态映射为低维向量再交给 HER 重标。这样做可以缓解高维状态下重标的计算量也让目标空间更平滑。我在一个 3D 推箱子任务里试过这个方法比直接拼接原始状态的效果稳定不少。最后分享一句我经常对同事说的话如果你发现智能体永远学不会一个稀疏奖励任务别急着怀疑优化器先问一句——你有没有把那些“失败”的经历重新解释成“成功”的经验来训练HER 的核心就是这么一件事但它在工程里的价值怎么强调都不为过。这个思路一旦打通很多看起来无从下手的任务都会突然变得有迹可循。