恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
HER经验回放:破解稀疏奖励的强化学习数据增强术
首页
资讯中心
/
HER经验回放:破解稀疏奖励的强化学习数据增强术
HER经验回放:破解稀疏奖励的强化学习数据增强术
发布时间:2026/10/3 4:56:42
“hindsight”这个词英文原意是“后见之明、事后聪明”。放在强化学习Reinforcement Learning, RL的语境里它代表一种反直觉的训练思路如果智能体没能完成任务那就把它实际到达的状态“追认”为新的目标任务再让智能体明白自己其实完成了一个目标。这就是Hindsight Experience ReplayHER——经验回放中的“后见之明”。这篇文章要解决的痛点很具体在稀疏奖励环境下智能体拿不到任何中间反馈随机探索很难撞到目标训练效率低到让人怀疑人生。HER通过在经验回放阶段对目标进行重标注把“失败的轨迹”变成“成功的样本”大幅提升数据利用率。它不改变策略算法的核心结构而是作为一套数据增强管线直接配到DQN、DDPG、SAC这类off-policy算法上就能用。这篇文章适合两类人一是刚入门的强化学习研究者或工程师想搞懂HER为什么有效、怎么实现二是已经在跑多目标或机器人控制任务被稀疏奖励折磨得想放弃需要一套能落地的调参方案。我会从原理拆到代码再补上实际踩坑记录保证你看完能直接在自己的项目里抄作业。1. 稀疏奖励为什么难搞先看一个“拧瓶盖”的例子1.1 从“拿不到分”到“学不下去”的恶性循环想象一下你让一个机械臂学习拧开一瓶矿泉水的瓶盖。如果仅仅在瓶盖完全拧开那一刻给奖励1分其余时间全部0分会发生什么机械臂的初次动作完全随机它碰不到瓶盖、拧不动瓶盖整个回合下来奖励永远是0。此时策略梯度算出来是零价值网络学到的Q值也全是零——没有任何信号告诉它“朝瓶盖的方向靠近一点是对的”。这就是稀疏奖励Sparse Reward的典型困境不是算法笨是环境里根本没有中间反馈可学。我见过很多初学RL的朋友在这个阶段怀疑人生反复调学习率、换网络宽度但模型就是不涨因为问题根本不在优化器而在奖励密度。用数学一点的话说假设回合长度是T一个episode的累计奖励是R Σ_{t0}^{T} r_t如果只有最终状态达成目标时r_T 1其余r_t 0那么几乎所有采样到的轨迹累计奖励都是0。policy gradient算法对每个样本的更新量都趋近于0网络参数在很长一段时间内根本得不到有效梯度。即使偶尔瞎猫碰死耗子成功了一次在1000条失败样本里那一条成功样本也容易被平均掉路径不清晰学不到泛化。1.2 常规解法的局限奖励塑形、好奇心、课程学习面对稀疏奖励工程上有几条常规路线但每条都有明显的“副作用”。奖励塑形Reward Shaping人工设计一个密集奖励函数比如“离目标越近奖励越高”。问题在于设计奖励函数需要大量的领域知识而且很容易引入局部最优的“钻空子”行为——比如机械臂发现“只要往下压就能加分”哪怕这个动作和拧瓶盖一点关系都没有。这就是常说的reward hacking。好奇心内在奖励Curiosity-Driven用预测误差作为内在奖励引导智能体去探索它不熟悉的状态。思路很好但如果环境本身随机性大预测误差会一直很高智能体会被噪音带跑偏反而忽略真实目标。课程学习Curriculum Learning从简单任务开始训练逐步过渡到困难任务。方法有效但任务的难度排序需要人工设计而且在连续控制任务里“简单”和“困难”往往是平滑变化的难以切分。HER完全绕开了这些思路。它不对奖励函数动手不额外增加探索机制而是对已经发生的经验做一层“语义修正”既然状态空间中任何你能到达的地方都可以被你定义成一个“有效目标”那么这条轨迹在某个目标下就一定是有正反馈的。这样一来即使原始目标没达成我们也能从这条轨迹中提取出“向着另一个可达目标前进”的正样本来学习。1.3 HER到底解决了什么问题把数据重新“翻译”一遍一句话总结HER的三观失败不是没用的失败只是“换了一个目标”的成功。在HER里每个训练样本不再只是 (s, a, r, s)而是 (s, a, r, s, g)——g是目标任务。传统经验回放直接使用环境给的g和r对稀疏奖励环境来说绝大多数样本的r都是0或者-1样本价值密度极低。HER在回放时会以一定概率把原来的目标g替换成轨迹中实际到达的状态 g称为achieved goal然后按照新目标重新计算奖励 r。这样原本“没有达成目标奖励为0”的样本就变成了“达成新目标奖励为1”的成功样本。这个操作看起来简单得像偷懒但背后的逻辑很深任何一个可达状态在目标条件策略goal-conditioned policy的视角下都能成为一条有监督信号的学习样本。策略的目标函数是“在给定目标的状态下执行动作”既然智能体已经在探索中到达了某个状态那就说明这个状态在当前探索能力范围内是可达的用它当目标来训练梯度方向一定是明确的、可学的。2. HER核心原理拆解目标重标记为什么“逻辑自洽”2.1 一个形式化框架通用目标表示与目标条件策略要理解HER先要理解目标条件策略。它不再是一个从状态到动作的映射而是一个从“状态目标”到动作的映射π : S × G → A输入是当前观测s和目标任务g输出动作a。举个例子让机械臂学习“把物体推到指定位置”g就是一个三维坐标 (x, y, z)s就是机械臂关节角度和物体实际位置。训练时我们采样一批transition (s_t, a_t, s_{t1}, g)策略要学习的是在目标g的条件下看到状态s_t应该做什么动作。为了让HER的重标记可行环境必须提供两个关键映射goal空间中的目标表示任务想要达成的结果记为g。从状态到goal的映射 m(s)把任意状态映射到goal空间里的表示。在机器人任务里通常就是末端执行器位置、物体的位置和旋转等。这个映射称为achieved goal。举个例子在OpenAI Gym的FetchReach环境里状态s包含机械臂七个关节的角度和末端执行器的xyz坐标目标g就是末端执行器要到达的一个坐标点而m(s)就是直接从状态中读出末端执行器坐标。对很多实际任务来说m(s)是可以免费拿到的——它就是你环境中已经观测到的物理量。接着还需要一个判别函数 f(s, g)用来判断“当前状态s是否达到了目标g”。在连续控制里通常设成欧氏距离f(s, g) 1{ ‖m(s) - g‖₂ ≤ δ }其中δ是成功阈值比如Fetch机器人设0.05。在离散任务中f可以是精确匹配比如“拿到了钥匙”这类布尔状态。2.2 目标重标记的操作细节新的目标从哪里来HER的重标记发生在经验回放阶段不是实时生成。具体来说从replay buffer里采到一条transition (s_t, a_t, r_t, s_{t1}, g)后以概率h论文里常用0.8执行重标记沿着这条transition所属的轨迹找到未来时刻 t1 到 T 之间的一个时间步 k。把该时间步的achieved goal m(s_k)取出作为新的目标 g m(s_k)。用新的目标重新计算奖励 r f(s_{t1}, g)得到新样本 (s_t, a_t, r, s_{t1}, g)。为什么一定要选“未来时刻”的状态而不是随便选一个其他轨迹里的状态因为这条轨迹里的状态本质上是在同一个动作序列下实际发生过的状态序列状态转移存在时间上的因果连贯性。用未来某个可达状态当目标等于是给智能体设立了一个“通过当前策略实际能到达”的、有希望实现的子目标。如果随机拿其他轨迹的目标来重标记可能会产生现实中根本不可达的目标反而引入噪音。这里的k可以是固定值也可以随机采样。OpenAI论文里的future strategy是每次从1到4之间随机采样一个k也就是沿着原轨迹往后看最多4步。之所以限制在几步之内一是状态之间的相关性更强二是防止目标离当前状态太远导致样本价值下降。2.3 为什么它有效概率视角与数据利用率的双重提升从概率角度看传统稀疏奖励学习中一条随机探索轨迹到达原目标的概率是极小概率事件比如1e-6。而HER把“到达轨迹中任意未来状态”都算作一个正样本事件这个概率显著增大。作者在论文中也给出了一个NIPS 2017的经典实验在FetchPush任务中训练8×10^6个时间步后基于DQN/DDPG的智能体成功率从0%提升到了接近90%而普通DDPG在同等条件下成功率一直徘徊在0%。数据利用率提升的逻辑更直观。原来的经验回放中1000条轨迹里只有1条存在非零奖励其余999条都是垃圾样本。HER把999条垃圾样本中的大部分自动改造成“对某个子目标有正反馈”的样本梯度信号密度提升了几个数量级。你可以把这个过程理解为把一堆空白的试卷同一份题目换几个不同版本的“正确答案”来批改每张试卷都能学到信息。2.4 HER不是万能的适用边界要拎清楚必须说清楚HER不是所有场景都适用。它的前提是任务能定义出“可观测的目标表示”——也就是m(s)必须能方便地提取。比如机械臂抓取、推箱子、导航这些任务天然有坐标、位置、角度等连续目标表示非常适合HER。但如果你做一个“识别图像中是否有猫”的RL任务目标空间是布尔量那么重标记一个“未来状态”几乎没有意义图片里要么有猫要么没有轨迹中拍到猫的样本和原始目标是同一目标不存在新目标。另外HER要求策略是目标条件策略且算法必须是off-policy。后面的章节我会专门解释为什么要off-policy以及怎么判断自己的算法能不能用HER。3. HER实现全流程从算法选型到核心代码3.1 算法选型为什么必须配off-policy算法前面提过HER要求配套off-policy算法这里展开说。off-policy算法的标志是有一个经验回放缓冲区允许从历史数据中反复采样采样训练。DQN、DDPG、TD3、SAC都是off-policy而PPO、A2C、TRPO这些on-policy算法只允许用当前策略生成的数据来更新策略每轮训练后数据就要丢弃或重采样。HER的核心机制就是“修改已经存的样本”——我们改动buffer里transition的目标和奖励再拿它来训练。如果算法是on-policy修改后的样本在当前策略下已经不是“同一分布”的数据用它更新策略在理论上不成立实际中也注定训练崩。反观off-policy算法本身就有“用历史数据来更新当前策略”的强假设buffer里多一批重标记样本只是数据分布变得更丰富不会破坏算法稳定性。我自己最常用的组合是HER DDPG以及HER SAC。DDPG结构简单、调参直观SAC自动调整温度参数探索更强在复杂任务上更稳。论文里是基于DDPG做的实验但后续社区的大量复现都证明SACHER在Fetch类任务上效果更好、更不容易过早陷入局部最优。3.2 核心数据结构一条样本应该存什么HER要正常工作经验回放里的每条样本必须额外保存两个字段g这条transition执行时使用的目标任务。ag执行这个transition后从状态映射得到的achieved goal即m(s_{t1})。之所以要额外存ag是因为重标记时需要根据时间步直接读取轨迹未来时刻的achieved goal。如果buffer里没有存ag重标记就无从谈起。很多初学者实现HER时只在transition里存g导致重标记时拿不到可用的目标训练效果和普通DDPG一样差——这是一个特别典型的错误。另一个容易忽略的细节是重标记后的transition会把原来的g字段覆盖成g但ag字段保持不变。新样本代表的故事是“在目标g的条件下智能体从s_t走到了s_{t1}到达了ag由于ag等于近似等于g所以奖励为成功。”整个样本在语义上是自洽的。3.3 核心代码一个可直接运行的PyTorch风格伪代码我直接给一段接近生产级的伪代码这段代码基于HER DDPG在FetchReach任务上跑通过。为了让你看清楚核心逻辑我省略了网络定义等模板代码只保留HER的重标记核心。import numpy as np class HERBuffer: def __init__(self, capacity, future_k4): self.capacity capacity self.future_k future_k # 未来状态采样的窗口论文推荐4 self.buffer [] # 每个元素是 (s, a, r, s_next, done, goal, achieved_goal) def store(self, transition): # transition: (obs, action, reward, next_obs, done, goal, achieved_goal) if len(self.buffer) self.capacity: self.buffer.append(transition) else: self.buffer.pop(0) self.buffer.append(transition) def sample_batch(self, batch_size, her_prob0.8): 采样一个batch其中80%的样本做目标重标记20%保持原始目标。 batch np.random.choice(len(self.buffer), batch_size, replaceFalse) her_batch [] for idx in batch: transition self.buffer[idx] s, a, r, s_next, done, g, ag transition # 决定是否重标记目标 if np.random.uniform() her_prob: # 找未来状态在整条轨迹中从当前时间步之后随机找一步 future_states self._get_future_achieved_goals(transition) if len(future_states) 0: # future strategy: 随机从未来K步内选一个achieved goal当新目标 new_g np.random.choice(future_states) # 用新目标重新计算奖励 new_r self._compute_reward(s_next, new_g) # 组成新的样本注意done通常不变回合是否结束取决于原始环境不改 her_batch.append((s, a, new_r, s_next, done, new_g, ag)) else: her_batch.append((s, a, r, s_next, done, g, ag)) else: her_batch.append(transition) return her_batch def _get_future_achieved_goals(self, transition): 在当前transition之后的未来状态中收集achieved goals。需要维护轨迹索引。 # 生产级实现中会为每条轨迹维护一个时间戳数组 # 这里简化处理遍历buffer中同episode的数据找到未来状态的ag。 # 核心逻辑是取出transition所属episode中时间步在t1到tk之间的ag列表。 pass def _compute_reward(self, state, goal): 基于欧氏距离判断是否成功距离阈值0.05 dist np.linalg.norm(state[:3] - goal) # 假设前3维是末端坐标 return 1.0 if dist 0.05 else 0.0注意上面代码里我留了个pass因为完整实现需要你在buffer里维护每条样本所属的episode id和轨迹内索引。实际工程中我倾向于用deque存一个episode的所有transitionepisode结束后再统一把transition拆开存进全局buffer同时为每个transition记录episode_index和timestep这样_get_future_achieved_goals就能按索引快速找到未来状态。其他环境里的目标表示如果和状态前三维无关记得调整_compute_reward里的坐标索引比如机械臂抓取任务可能要用物体的三维坐标而不是末端位置。3.4 超参数组合怎么选一份可以直接抄的实验配置在Fetch类机器人控制任务上我实测最稳的HER参数组合是下面这张表参数推荐值说明回放缓冲区大小1e6Fetch环境状态维度不高1e6条样本内存压力不大HER概率0.880%样本重标记20%保留原目标防止策略忘记真实任务future窗口k4OpenAI论文的默认值未来1~4步内随机选目标成功阈值δ0.05Fetch环境官方阈值越小任务越难策略更新次数/回合40次每个episode后更新40次策略网络batch size256在DDPG上比较稳定探索噪声高斯噪声σ0.2机械臂任务上比OU噪声更好用学习率1e-3critic相比论文的1e-3我习惯让actor用1e-4更稳定这个配置不是凭空来的。her_prob设成0.8而不是1.0是为了保留20%的原始目标样本防止模型对真实目标过拟合不足future窗口k4是论文在多个任务上验证过的平衡点——窗口太小目标多样性不足窗口太大目标与当前状态相关性下降。DDNG更新次数每回合40次是我在训练曲线里观察到2万步左右出现明显上升趋势时的参数后续你也可以在40~60之间做小网格搜索。4. 实操过程记录用HER训练机械臂推箱子的完整心路4.1 第一版实验从零到1%的成功率我先用OpenAI Gym的FetchPush-v1做实验任务是把桌子上的箱子推到目标位置。第一阶段是基线测试不用HER直接用DDPG奖励函数按环境默认的稀疏设置箱子到达目标位置给1分否则0分。训练50万个时间步后评估集上成功率通过距离阈值判断始终在0%附近波动。这不是DDPG本身有问题而是稀疏奖励下梯度信号太稀少。接入HER后同样50万时间步成功率肉眼可见地在第15万步左右开始爬升到第50万步时稳定在70%以上。再训练到80万步时成功率稳定超过90%。整个过程中我没有改动任何网络结构或奖励函数唯一的变量就是buffer里的数据被重新标注了一部分。这里有一个非常重要的实操观察HER带来的提升并不是瞬间出现的而是先让Q值估计变得“不稀疏”随后策略才开始学东西。前几万步里重标记样本大量出现critic先学会给“接近目标”的状态打高分然后actor梯度才逐渐跟上所以训练曲线往往有一个明显的“平台期”平台期过了就会快速上升。如果你的训练曲线一直平台不上升大概率是actor的学习率没调整好或者HER概率设得过小——平台期是正常的但平台期长度不能超过训练总步数的30%。4.2 观测指标别只盯着成功率看训练RL模型时很多人只盯着评估成功率这个习惯在HER场景下会误导你。我建议同时观察以下指标critic loss下降趋势重标记样本让critic学习到更多非零Q值如果critic loss长期不降说明网络容量或学习率有问题而不是数据问题。replay buffer中非零奖励样本比例这个比例会从接近0%上升到20%~40%如果始终低于10%说明her_prob太低或future窗口太大导致目标不可达。actor梯度范数梯度一直趋近于0说明策略更新没信号此时应该加大her_prob或降低batch size看看。4.3 踩坑实录哪些“改法”会让HER失效我踩过不少坑挑几个典型的说。第一个坑是在重标记后不更新done标志。有朋友会说既然目标换了原来已经失败的最终状态在新目标下是成功的那done是不是也要从False改成True千万别改。done标志表示环境是否结束这是一个物理过程不是目标空间的属性。回合如果已经结束你不能把后续时间步的action和transition再编成一个新的episode。如果强行改done等于创造了不真实的终止条件会严重干扰时间差分学习的自举逻辑。第二个坑是目标空间和观测空间不一致导致m(s)索引写错。在FetchSlide任务里目标还包括物体速度这一隐藏量如果m(s)只提取了位置而漏掉速度训练出来的策略会沿着错误的目标判据走。排查这类问题的方法很简单打印几条重标记后的样本人工检查新目标和实际achieved goal的距离是否真的小于阈值。第三个坑是忘记保留原始目标样本。把her_prob设成1.0看似大胆实际会让策略只学会“到达最近状态”而忘了真正的任务。因为buffer里的数据绝大多数被标注成“当前探索方向是成功的”策略会被偏差拖着走最终评估成功率反而下降。保持80%~90%的重标记比例是更稳妥的选择。5. 常见问题与排查技巧HER实战中你一定会遇到的五个情况5.1 速查表症状、原因、解法对照我把实践里遇到的常见问题整理成表格你可以直接按图索骥症状可能原因排查方向与解法训练30万步评估成功率仍为0HER概率过低或future窗口过小确认her_prob≥0.8future_k设为4检查buffer里是否有足够重标记样本训练初期critic loss skyrocketing重标记目标与状态之间距离计算错误打印重标记样本检查new_g与s_next距离是否真的小于阈值训练曲线平台期超过50%训练时长actor学习率过小或batch size过大把actor学习率调到1e-4batch size降到256以内观察梯度范数是否恢复评估成功率波动剧烈探索噪声过大策略反复进入同一条探索路径将高斯噪声σ从0.2降到0.1或改用SAC替代DDPG策略过早陷入局部最优比如只学会推箱子但不推到位原始目标样本保留太少先丢失真实任务her_prob降到0.7~0.8重新加入更多原始目标样本5.2 如何判断“是数据没喂好”还是“是网络坏了”这个排查思路很重要。每次模型不涨先分清问题在数据侧还是网络侧。我自己的排查顺序是先看buffer里重标记样本的成功率重标记后奖励为1的占比。把这个成功率和原始样本的成功率对比。如果重标记后成功率也接近0说明目标函数或者距离阈值设置有问题——目标根本不相容。如果重标记后成功率很高比如超过50%但critic loss依然很高再检查网络更新逻辑、学习率、梯度裁剪。先数据后网络能帮你快速缩小问题范围避免把时间浪费在调网络结构上。记住REINFORCE时代养成的习惯——先怀疑奖励函数、再怀疑参数、最后才怀疑网络结构。5.3 高级扩展HER和别的机制怎么组合HER的价值不只是单独使用它跟其他学习机制组合时能擦出更大的火花。与SAC组合SAC的熵调节机制能增强探索多样性和HER的重标记目标形成互补。我在FetchPickAndPlace抓取放置任务上SACHER比DDPGHER少用了约30%的样本就达到相同成功率。与优先级经验回放PER组合PER会优先采样高TD误差的样本而HER构造的样本往往具有较高的TD误差两者方向一致组合训练收敛更快。需要注意的坑是如果PER的优先级更新过于激进会让重标记样本重复更新过多反而增加过拟合风险建议优先级指数α设小一点比如0.3。与课程学习组合HER不用依赖人为排序的课程它天然地通过目标重标记构造了一个“离目标越来越远”的课程——刚开始重标记的都是离当前状态很近的目标训练后期buffer里积累了更多困难目标的样本。你可以在这个基础上再叠加一个额外的课程难度控制比如逐步增大future窗口k效果更平滑。与离线RL组合CHERCurriculum Hindsight Experience Replay就是基于一个离线数据集中不同难度的样本自动排序目标难度来做训练的。如果你只有一批历史数据而非在线交互环境可以关注CHER这一类离线变体。5.4 特殊环境的适配技巧不同环境里HER的实现细节差别很大这里挑三种常见场景说。第一离散目标空间比如要让智能体找到房间里三把钥匙中的其中一把。此时achieved goal是布尔型变量重标记时直接把当前状态对应的钥匙位置作为新目标就行判别函数是精确匹配。需要注意的是离散空间的目标多样性有限重标记带来的增益会小于连续空间此时增大her_prob到0.9会有一定帮助。第二图像输入比如从像素中学习推箱子。目标g往往来自图像特征或目标物体在图像中的位置此时m(s)通常要通过一个编码器提取建议先用监督学习预训练一个图像编码器把图像帧映射到低维特征向量再用HER去重标记特征。如果不先预训练编码器直接在原始像素上做HER我的经验是训练极其不稳定。第三稀疏奖励加上随机初始化的高维空间比如六足机器人从随机姿态走到目标。这种情况下HER能够构造成功样本但策略容易局部陷入“只会从固定初始位置走”的困境。解决办法是配合随机化初始状态分布让探索覆盖更多状态空间同时把future窗口提高到8~10让重标记目标覆盖更长的时间跨度。结尾一点经验之谈在我做过的机器人操作、物体抓取、导航等多个稀疏奖励项目中HER是少数几个“加了就有显著收益”的通用技巧。它真正打动我的地方在于它不需要设计复杂的奖励函数不需要额外搭建探索模块只需要在数据格式上动一点手脚就能让原本毫无信号的训练过程变得高效。这个思路也提醒了我很多所谓的“算法创新”本质上是重新审视我们已有的数据里到底包含了多少被忽略的信息。如果你现在正在被稀疏奖励问题折磨我的建议是先别急着换模型把你现有的buffer打印出来看看——里面有多少条轨迹虽然没到达目标但确实到达了某个位置HER就是把这些被浪费的坐标捡回来的过程。后续如果想更深入可以从多智能体HER、离线HER以及目标条件表示学习这几个方向继续挖这条路很长但每一步都值得。