☰
强化学习稀疏奖励难题:事后经验回放(HER)核心原理与工程实践
2026/10/5 0:33:52 网站建设 项目流程

1. 稀疏奖励为什么是强化学习的头号杀手

先说一个我最早做机械臂抓取仿真时反复遇到的场景:环境里有一个目标点,机械臂需要把物体推到指定位置。任务定义很明确,代码逻辑也没问题,但训练从第一步就陷入死局——智能体收到的奖励永远是 0,直到它偶然把物体推到目标附近。可问题在于,没有梯度的空间里,随机动作偶尔碰到目标的概率几乎等于零。

这个现象在强化学习里的学名叫稀疏奖励问题(sparse reward problem)。奖励信号在绝大多数时间步里都是 0,环境不给任何关于“你走得对不对”的反馈,只有最终的那一下成功才给出 +1。算法层面看,策略梯度依赖奖励计算优势函数,Q 学习依赖 TD 误差更新价值网络,奖励全是 0 的时候,价值函数梯度也为 0,模型参数原地踏步。换句话说,误差信号从哪里来?没有误差信号,优化就是一个空转的过程。

你可能觉得,那加大探索噪声不就行了?让动作更随机一些,总有一次能撞到目标。理论上可以,实际上非常不可靠。机械臂的动作空间假设是 4 维连续空间,每维都是实数,目标位置对末端执行器的要求是极其精确的——不是“大概方向对”,而是位置、速度几乎同时正确才能成功。在这样高维连续空间里用随机策略碰出一次成功,概率按指数缩小,训练一万个 episode 都等不到一次正样本。而强化学习恰恰是需要盘点“历史教训”的学习方式,连续一万次失败,最后全是被丢弃的无效数据,学习过程自然无从谈起。

工程师们想了很多办法绕开这个问题。最常见的是 reward shaping,人为构造一个中间奖励,比如“物体离目标越近奖励越大”。听上去简单,但这相当于人类把解法塞进环境,设计不好很容易让智能体钻空子——我曾经见过一个智能体为了拿到“移动惩罚尽量小”的奖励,干脆原地不动装死。另一种是课程学习,从简单的初始位置开始训练,然后逐步加大难度,但课程难度的自动控制本身又是一个难题。还有 exploration bonus,鼓励智能体去没去过的地方,但在很多精细操作任务上,单纯的新奇性驱动并不能带来有效的操作技能。

这些方法能缓解问题,但都没有触及一个根本矛盾:**智能体完成任务靠的是一次“侥幸成功”,但真正的学习信号其实藏在每一次失败的过程里。**假如把失败的数据也用起来,是不是就能凭空多出成千上万条可供学习的经验?这正是 hindsight——事后经验——这个名字背后最核心的思路。我第一次听到这个概念是在 2017 年 OpenAI 发表那篇《Hindsight Experience Replay》论文时,看完最大感受是:思路顺理成章,但为什么之前没人想到。

2. 事后经验回放的核心思想:把“失败”改写为“成功”

要理解 HER,得先把强化学习里的“目标”这个概念单独拿出来批评一通。常规的 goal-conditioned RL 设定下,一条 transition 由四元组构成:当前状态 s、动作 a、奖励 r、下一状态 s‘。在稀疏奖励任务里,奖励由“是否达到目标 g”决定,要么 0 要么 1。比如抓取任务,goal 是物体最终位置,agent 移动物体到指定点得 1,否则得 0。

问题在于,**一旦 episode 结束而目标没有达成,这条轨迹的信息就被浪费了。**可事实上,这条轨迹并不是毫无意义的——物体确实被移动了,机械臂确实执行了一串动作,这串动作如果真的以物体最终到达的那个位置作为目标,那它就是一个完美的成功示范。

HER 的思路就一句话:**重新给这段经历定义一个目标,把轨迹原本要达成的 goal g 替换成轨迹实际到达的终点 g‘,再按照新的目标重新计算奖励。**比如机械臂没能把物体推到 (0.5, 0.5),但物体最后落在 (0.3, 0.7),那我就假装这次任务的目标本来就是 (0.3, 0.7),回放时按照“目标是否等于 (0.3, 0.7)”来判定奖励。物体最终的位置恰好就是 (0.3, 0.7),所以这次回放得到的是奖励 1,是一条成功经验。

你说这是造假也行,但这种造假是提炼真相。关键在于:虽然这条轨迹没能完成原目标,但它是从某个初始状态出发、通过一串真实动作到达新状态 G’ 的物理上可复现的过程。用强化学习的语言说,这提供了一条“状态-动作对能产生某个结果”的因果证据。当智能体以后面对相似状态、需要达到相似目标时,它可以参考这段经历,知道哪条路“走得通”。

这个道理很多人第一遍听觉得像抖机灵,但实际操作之后会发现它极其强大。我拿一个简单的模拟环境验证过:环境是一条一维线段,智能体从 0 出发,目标是移动到 10,但只能向左或向右走一步,随机策略下到达 10 的概率极低。普通 DQN 训练两千个 episode,Q 值几乎不涨。HER 改写目标后,每个 episode 里至少有一步的“事后目标”在当前位置附近,Q 网络的监督信号密度瞬间从千分之一提升到接近百分之百。两千个 episode 跑完,成功率曲线直接起飞。

当然,HER 不是随便用在任何 RL 算法上都有效,它有一个硬性前提:**必须配合 off-policy 算法使用。**DDPG、DQN、SAC 这类有经验回放缓冲区的算法可以存下历史 transition 并反复采样;而 on-policy 算法如 PPO、A2C,每轮都丢弃旧数据,HER 制造的“伪造成功经验”还没来得及被学习就见光死了。所以你在论文里看到 HER 通常是 HER+DDPG、HER+SAC 的组合,几乎不会看到 HER+PPO,因为范式上就不成立。

3. 实现层面的四件事:目标定义、存储结构、采样策略与重标记时机

把 HER 落地到代码,会有好多细节比论文里说的复杂。我把实现拆成四件事,逐一过一遍,这对想做实验的人有价值。

3.1 目标函数与观测设计:把 goal 写进 state

HER 的第一个前提是策略必须是 goal-conditioned,也就是策略的输入不能只有观测 s,得有 (s, g) 或者把目标拼进观测里。目标的形式可以是目标状态(goal statefull),比如“物体最终要到达的位置坐标”,也可以是描述任务的向量。实操上我建议先确认你环境的观测空间里是否天然包含目标信息,如果没有,就把 target 向量和当前观测拼接起来,得到一个维度加大的新观测。

这里有个容易忽略的点:**不仅当前状态需要包含目标,重标记之后的目标也必须能拼进状态用于价值网络输入。**所以在设计包装函数时,最好把 transition 里存的数据结构统一封装成 (obs, act, rew, next_obs, goal) 五元组,而不是只存原始 obs。重标记时只需要替换 goal 字段、重算 reward,再相应地更新拼接后的 obs 和 next_obs,否则你的网络输入和目标对不上。

奖励函数我记得写成二值形式最省心:goal 达成给 1,否则给 0;或者距离小于某个阈值给 0,否则给 -1,这就是稀疏奖励的标准形态。用连续距离做奖励会让整个问题退化成普通的稠密奖励问题,HER 的优势反而不明显了。

3.2 四类目标重标记策略:future / final / episode / random

论文里最重要的一个技术贡献是研究了“用什么目标来重标记效果最好”。我把四种策略列在表里,可以根据任务性质去选:

策略操作效果
final用轨迹终点作为所有 transition 的新目标最简单,强烈依赖轨迹终点多样性
random从 buffer 中随机挑目标目标多样性高但偏“无关样本”较多
future对当前 transition 之后的某个未来状态作为目标兼顾可达性与时序关系,常为默认选择
episode从整条轨迹中均匀采样目标中等效果,多样性稳定

我的习惯是优先尝试 future,设置 k=4,也就是每个 transition 重标记 4 个不同的 future 目标,然后把它们一并存入 buffer。这样做既保证了目标分布在状态空间内的覆盖面,又不会像 random 那样引入太多完全超出当前轨迹可达范围的目标。final 策略在任务简单、终点状态模式单一的时候很高效,但一旦轨迹终点分布复杂,它会让目标分布过于集中,网络很快过拟合到那几个频繁出现的终点上。

3.3 重标记时机与 replay buffer 的设计

重标记的目标是“轨迹真实达到的状态”,所以在 episode 结束之前,我们并不知道未来会发生什么。这意味着重标记只能在一个 episode 跑完之后进行,而不是每步在线进行。我踩过的坑是把重标记放到 replay buffer 层面边存边改,结果因为“future 状态还没发生”,把未来信息泄漏到目标任务里,评估成功率虚高。正确的做法是按 episode 为单位先缓存原始 transition 序列,episode 结束后整条轨迹做一次重标记,再逐条塞进全局 buffer。

buffer 的存储结构也值得留意。HER 论文里默认用的是非均匀采样:重标记样本相对普通样本可以多存一些,但不宜疯狂膨胀比例。一个通用的做法是把原始轨迹和重标记轨迹按 1:4 的比例混合存入。我试过 1:10,效果没明显提升,反而因为伪造样本过多、真实样本被稀释,在训练后期成功率反而出现平台期。别把自己骗了,回放数据里也得保留足够多的“真实失败案例”。

3.4 HER-DDPG 核心伪代码

凑理论不如看代码。下面这段是 HER 与 DDPG 结合的框架性伪代码,结构上可以直接迁移到 SAC 或 TD3:

# 伪代码:HER + DDPG 核心循环 def train_her(env, agent, num_episodes, k=4): replay_buffer = [] for episode in range(num_episodes): episode_transitions = [] obs = env.reset() goal = env.get_goal() done = False while not done: action = agent.select_action(obs, goal, noise=True) next_obs, reward, done = env.step(action) # 原始 transition 先按原目标存起来 episode_transitions.append({ "obs": obs, "action": action, "reward": reward, "next_obs": next_obs, "goal": goal, "done": done }) obs = next_obs # episode 结束后的重标记阶段 final_state = episode_transitions[-1]["next_obs"] for transition in episode_transitions: # 原始样本 replay_buffer.append(transition) # future 策略:选当前之后的若干状态作为新目标 future_states = sample_future_states(episode_transitions, transition, k) for new_goal in future_states: new_reward = compute_reward(transition["next_obs"], new_goal) replay_buffer.append({ "obs": concat(transition["obs"], new_goal), "action": transition["action"], "reward": new_reward, "next_obs": concat(transition["next_obs"], new_goal), "goal": new_goal, "done": transition["done"] }) # 从 buffer 采样更新 agent for _ in range(num_updates): batch = sample(replay_buffer, batch_size) agent.update(batch)

注意两个细节:一是sample_future_states的实现要保证只采样当前 transition 之后的时间步,避免用“过去的状态”当作“未来已达成”的目标,这种时间顺序错误会造成虚假学习信号;二是concat是可选项,如果你的 agent 本来就接收 goal 作为额外条件输入,那就可以省掉拼接,直接用 conditioned policy。

3.5 评测指标:别盯着 reward 曲线

用 HER 训练之后,我发现衡量进度的指标和普通 RL 任务不太一样。稀疏奖励任务的 loss 曲线或者平均 reward 曲线不具备参考意义,因为 episode 开始阶段绝大多数回合奖励是 0,后期一个回合成功拿到 1,平均值变化非常突兀且不稳定。我更习惯统计成功率:每个评估周期跑 50-100 个 episode,计算目标达成比例。成功率曲线才能真正反映学习进展,而且便于和论文里的对照实验比较。如果你只盯着 TensorBoard 里的 mean reward,很可能会误以为 HER 训练没效果,其实它只是把“成功经验”分散到更多 transition 里,reward 均值并没有想象中光滑。

4. 为什么 HER 能带来数量级的学习加速:我的实验观察

理论上 HER 的道理说得通,但它加速学习的效果到底有多显著,最好用实验说话。我复现了一个经典的 Bit-flip 环境实验:状态和目标是 n 维二进制向量,每一步可以翻转一位,只有当状态变成和 goal 完全一致时奖励为 1,否则为 0。这是一个教科书级的稀疏奖励任务,维度越高越难。

在 n=15 时,普通 DQN 基本上是在碰运气。因为状态空间有 2 的 15 次方那么多个点,随机翻转能恰好碰上目标点的概率微乎其微,训练一万个 episode 成功率纹丝不动。而 HER 的做法是:假设轨迹最后停在了 s‘,那就把这段轨迹的目标改写成 s’ 本身,回放搜到的每条经验都变成“从某状态翻转到另一状态”的正样本。Q 网络因此能学到“相邻状态之间满足一步可达”这样的局部规律,不需要跳到全局目标也能积累价值信号。只要局部价值传播对了,全局策略就能像涟漪一样扩散,最终从起点找到通往目标的路径。

速度对比非常明显,HER 让这个任务变成了数百个 episode 内就能看到成功率爬升的问题。我对比过 HER 与普通的经验回放(ER),在同一环境、同一网络结构、同一超参数下,成功率到达 80% 的 episode 数量差了至少一个数量级。这说明重标记本质上是给算法加了一层“免费课程”:普通 ER 只能学习真实发生的稀疏成功事件,而 HER 把每个时间步都转化为“目标-结局配对”的稠密信号,相当于课程自动从近处开始,随着轨迹终点分布的变化逐步逼近远处目标。

对于连续控制任务,我观察到的是另一种形态的加速。比如二指机械臂推动滑块到目标位置的任务,不使用 HER 的 DDPG 在 50 万步时成功率仍然接近 0,而 HER 版本在 20 万步时成功率就能稳定到 80% 以上。区别在于普通 DDPG 的价值网络从没见过成功样本,而 HER 版本的价值网络虽然也从未见过真正成功,但它见过“从任意位置出发把物体推到当前位置”的这种局部成功。局部成功积累多了,网络对哪些动作能改变物体状态形成了清晰认知,后续再面对真实目标时,它只需要在这个认知基础上做一步规划,而不是从头搜索整个状态空间。这一层因果结构的学习,正是“事后经验”最妙的地方。

不过也要警惕另一面:HER 制造的成功样本毕竟是假的,如果网络只会盲目模仿“到达当前位置”这类目标,真实任务需要长距离移动时,它可能停留在局部最优。所以后面很多工作都在 HER 的基础上加入额外的目标筛选机制,而不是无脑重标记。我个人在实践中发现,在最终评估阶段适当减少重标记比例、增加真实成功样本比例,往往能改善最终策略的泛化性。

5. 实战踩坑记录:HER 不是银弹

HER 很强大,但绝不是一个开了就能用的开关。这几年我在不同环境里尝试过 HER,踩过不少坑,总结成几条最值得看的经验。

5.1 太稀疏也不行:仍然需要“偶然成功的一次”

HER 的原理决定了它的学习信号来源是轨迹终点本身。如果任务的环境随机性过大,或者动作噪声把智能体完全推向无关状态,那么轨迹终点可能根本没有任何规律可言,重标记出来的目标集合也毫无结构。举个例子,如果机械臂每步动作都叠加了方差极大的噪声,轨迹终点更像是一堆随机点,那“把目标改成终点”并不能给策略提供可靠的因果信息——因为同样的起点,下一条轨迹终点可能差得很远。

所以 HER 实际适用的场景是:在给定初始状态下,动作与结局之间存在一定可复现性(哪怕很微弱)。如果动作噪声大到一个 episode 的结局完全随机,那 HER 也不会有奇效。这种情况下我的做法是先调低探索噪声、让随机策略至少能形成一点短程可预测性,再叠加 HER,成功率才会起来。

5.2 目标分布与初始状态分布错配

HER 的重标记目标来自轨迹终点,而轨迹终点分布受初始状态分布影响。如果你的训练环境初始状态分布单一(比如机械臂总是从同一个位置出发),那么轨迹终点大多聚在一个小区域,重标记目标也困在这个区域,策略学到的是“如何把物体推到那一片区域”,一旦测试时初始状态或目标位置远离这片区域,策略就失灵。

解决思路是增加训练时初始状态的随机性,目标位置的采样也尽量覆盖整个可行空间。我在抓取任务里做得比较多的是把初始物体位置和 goal 位置都从整个台面上均匀采样,这样轨迹终点才会散开,重标记的目标也才能覆盖桌面各处,最终策略的泛化性才会接近完整任务空间。

5.3 replay buffer 的目标分布偏移

重标记样本占 buffer 的比例很关键。前面说过我喜欢 1:4,但实际任务里这个比例要跟着训练阶段调。训练早期,真实成功样本几乎没有,可以适当提高重标记比例,让网络尽快学到基础运动学;训练中后期,真实成功样本增多,如果重标记样本还占大头,网络会一直被“从当前位置到当前位置”的低难度目标占据,学习不到更高级的策略。我在后期通常把重标记比例调低到 1:1,甚至 1:2,同时提高真实成功样本的采样权重。

这背后是目标分布和目标难度平衡的问题。重标记样本容易但偏简单,真实样本难但稀少,两者需要动态平衡,而不是一个固定比例走到底。

5.4 网络容量与表征能力瓶颈

HER 加速的是学习信号密度,而不是表征能力。当任务的目标空间非常复杂(例如目标是图像、是自然语言描述),拼接 goal 作为网络输入的容量要求就会骤然上升。我试过用 HER 训练一个以目标图片为条件的策略,起初以为算法效果会和向量目标一样好,结果价值网络完全无法从高维图像中提取可控特征,训练陷入停滞。这个问题的解决依赖高质量的 encoder 或者预训练的视觉表征,不是 HER 本身能解决的事。

如果你的目标是图像或多模态信息,我的建议是先训练一个 decoder 把目标压缩成低维 embedding,再和状态拼接喂给策略网络,而不是直接把原始高维目标塞给价值网络。HER 只管重标记,不管表征,把它强行当成万能钥匙只会失望。

5.5 重标记目标与动作时间步错位

最后提醒一个比较隐蔽的坑:重标记采样 future 状态时,务必注意时间步关系。future 策略要求在 transition 的时间点之后采样新目标,但如果实现过程中搞错了索引,可能把“过去状态”采了进来,这会让目标超过实际可达范围,造成价值函数乱讲。这个 bug 不会直接报错,但它会让成功率曲线产生奇怪的周期性波动。遇到这种情况,先检查sample_future_states的索引切片是不是严格小于当前 transition 的索引。

6. 向外扩展:HER 和周边方法的组合思路

HER 不是一个孤立的算法,把它当作一个通用“经验增强”模块之后,它的用处比论文里的 benchmark 大得多。

6.1 与课程学习的配合

课程学习的难点在于难度指标的设计,而 HER 的重标记目标天然构成了一条难度从低到高的自动课程。早期重标记目标集中且简单,策略只需要学会小幅动作控制;随着训练推进,轨迹终点逐渐外扩,目标分布自然逼近真实目标分布。不过如果想要让课程更高效,也可以在 HER 基础上主动加一层难度过滤:只保留那些距离原目标中等距离的重标记样本,比如距离在目标半径的 2-5 倍区间,避掉过于简单和过于困难的样本。这个技巧对复杂任务的价值在于让价值函数聚焦在“跳一跳够得着”的目标上,学习效率再上一层楼。

6.2 多目标与稀疏奖励下的分层RL

在很多真正连续控制任务里,我们面对的不是单一目标,而是一系列子目标。比如做一杯咖啡,涉及抓杯子、倒水、拿勺子等多个子任务。直接把整条长轨迹打成一个 HER 目标往往过于粗糙。我见过一种做法是:把任务拆成子目标链,每个子目标单独训练一个 goal-conditioned 策略,再用上层策略选择当前子目标。HER 在这里的作用是让每个子目标模块在稀疏奖励下也能快速收敛,整体流水线因此可行得多。这个组合思路本质上利用了 HER 对局部因果结构的快速提取能力。

6.3 与对比学习、表示学习的结合

在表征学习的框架下,HER 的重标记过程天然产出大量“同状态不同目标”的对比样本:同一段经历,不同目标下成功或失败,这组对比对学习判别性表征很有帮助。我在实验里试过把 HER 重标记的样本额外喂给一个 contrastive head,用来学习“当前状态离目标差多少”的距离表征,之后再用这个表征作为 reward 函数,效果比手工造距离函数好不少。这也算是 HER 在生成式经验之外的另一层价值:免费的辅助监督信号。

回头来看,HER 之所以成为一个常青的 baseline,核心原因是它抓住了强化学习里一个最朴素却最容易被忽略的事实:**失败轨迹和成功轨迹的物理运动规律是一样的,差别只在目标定义上。**把目标写成“已经发生的事”,失败也能变成教材。这个思想后来也被吸收进大量后续算法里,比如 goal-conditioned imitation learning、自动课程选择,乃至一些离线强化学习的工作。如果你在做稀疏奖励任务,开头第一件事值得先试试——给 replay buffer 里加一点“事后聪明”。

最后分享一个我做实验时的小习惯:重标记目标不是越多越好,早期一个 transition 配 4 个 future 目标确实香,但训练后期我会把 k 降到 2,再把真实经验的比例拉上来。这个动作让我在好几个任务里避开了“训练后期平台期”的尴尬。你可以先按自己的任务试,如果发现后期成功率不上不下,往往是伪造样本比例压过了真实结构,适当降 k、升真实占比,通常能救回来。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询