HER事后经验回放:破解强化学习稀疏奖励难题的实用指南
1. 从“事后诸葛”说起HER要解决的根本问题刚开始接触强化学习的人多半都会被一个场景折磨过你辛辛苦苦搭了一个环境agent在里面瞎撞了半天奖励永远是0直到训练结束它也没能碰到一次目标梯度根本不知道该往哪儿走。你怀疑是网络结构写错了调大学习率试了试结果更糟换了更复杂的奖励函数agent倒是能动了可一旦换回稀疏奖励又回到了原地踏步的死循环。如果你也遇到这种情况那大概率需要了解一下“hindsight”——在强化学习领域这个名字对应的是一项叫做HERHindsight Experience Replay事后经验回放的技术。它最早由OpenAI的研究者提出核心思想非常朴素一句话就能概括与其盯着没达成的目标唉声叹气不如把现实中失败的那条轨迹重新解释成对某个“事后目标”的成功经验。这套思路最初是奔着解决机器人操控任务去的比如机械臂推物体、抓取物体这类目标明确、但奖励极其稀疏的控制问题。但后来它的适用范围远超了机器人领域导航、游戏策略、多智能体协作甚至一些离散动作空间的任务里也能派上用场。这篇文章我会从原理讲到工程实现再把我在实际训练中踩过的坑、调过的参数、修过的bug一并放出来。如果你是刚入门RL没多久的新手读完之后你会知道HER到底在改什么、为什么能改出效果如果你已经写过一些DQN、DDPG之类的代码那这篇文章里关于重标注逻辑和buffer数据结构的细节应该能帮你少走不少弯路。2. 核心机制逐层拆解经验重放背后发生了什么2.1 经验重放与“目标”这个概念要想理解HER先得把“目标”这个词在RL语境里的含义搞清楚。绝大多数强化学习任务里一个状态转移样本长这样(s, a, r, s)agent看到一个状态s采取动作a拿到奖励r进入下一个状态s。Q-learning类算法也好、策略梯度类算法也好都是靠这一条条转移样本来估计价值、更新策略的。但有一类任务比较特殊它的环境里带有一个“目标”参数用g来表示。举个例子机械臂要推一个滑块到指定位置那么s是机械臂和滑块的当前位姿g是目标位置动作a是关节力矩奖励r则取决于g和目标位置之间的距离。在这种情况下样本其实是(s, a, r, s, g)——目标g参与了奖励的计算也参与了状态转换的逻辑。这类带目标的任务如果给的是二值奖励到达目标就算1没到就算0学起来会非常吃力。因为agent一开始完全靠随机探索几乎不可能在训练初期就撞上一次“达标”于是buffer里躺着的全是r0的样本。你让神经网络从一堆零奖励里学出“哪个动作好”等于让一个从没见过苹果的人描述苹果的味道——它什么都说不出来。2.2 HER的核心动作目标重标注HER做的事情概括起来就是六个字事后目标重标注。过程是这样agent在某个目标g下跑完一段轨迹结果没达到g。研究者不把这半条轨迹扔掉而是重新选取轨迹末端状态s所对应的某种“实际达成状态”作为新目标g然后把这整条轨迹当成“想要达成g且真的达成了”的样本来训练。放在机械臂推滑块的例子里就是你让机械臂把滑块推到左上角结果它歪打正着把滑块推到了右下角。传统的算法会记录这次尝试失败然后什么也学不到。HER则直接把这条轨迹重新解释成“目标是从某处把滑块推到右下角而且我做到了”然后拿这套数据去训练策略网络。这样一来每个失败的探索片段都能产出一条“成功”的经验。agent探索得再离谱也会源源不断地积累正样本。这个转变的意义非常大它把稀疏奖励问题转化成了数据分布问题。你不再需要精心设计每一步的稠密奖励来计算梯度只需要不断重构出成功经验让网络逐渐学会“从当前状态滑向任意目标”的基本技能。2.3 目标重标注的四种常见策略当然目标重标注不是随便挑一个状态当目标就完事。不同选法对训练效果影响非常大。我实际尝试过主流的几种方式在这里列个对比策略选择方式特点我的评价final取同一轨迹的最终状态作为新目标信息最稳定最常用大多数情况下的首选future从当前时刻之后的轨迹状态中随机选一个能学到中途阶段目标训练更平滑复杂任务中效果突出episode从整条轨迹的任意状态中随机选一个目标覆盖范围广但噪声偏大适合探索需求高的任务random从环境中随机采样一个状态当目标接近原始目标分布但成功率低少用基本被future替代我最推荐从future入手。因为final虽然稳定但它会让agent学到的技能偏向“一次性冲刺到终点”而future策略给每个时刻都配了一个未来可达的目标相当于把长程任务拆成了很多个较短的子任务网络学起来更稳。实际操作中HER的作者后来也经常采用这种“future”风格的重标注逻辑和OpenAI那套VecNormalize工具配合起来效果很稳。2.4 HER的实际收益在哪里我在自己的任务里做过一个简单的对比测试同样的环境、同样的网络结构、同样的优化器一个用标准DQN一个用DQNHER。在500个episode结束时标准DQN的agent还处于随机乱撞阶段成功率为0而加了HER的agent在150个episode左右开始出现稳定的成功尝试500个episode结束时的成功率到了63%左右。这个对比背后反映的道理是HER并没有改变探索策略本身它改变的是样本的“信息密度”。每个探索用的轨迹在传统RL里只产生了一两条有效信号但在HER里一条轨迹能同时产出多条有效信号对应多个事后目标。样本总量不变可有效监督信号翻了好几倍训练效率自然就上来了。这里还有一个容易被忽略的细节HER对奖励函数的设计要求反而更低。你完全可以用一个极端的二值奖励到达目标给1其余全给0照样能训练出像样的策略。这在实际工程里价值很大因为大多数环境下“设计一个好的稠密奖励函数”比“写一个能跑的实验”难得多。奖励函数一复杂不确定性就大各种奖励崩溃的问题就会冒出来。HER让很多原本难搞的任务可以直接用最朴素的奖励定义起步。3. 实操从公式到代码的关键实现3.1 环境与基线算法选型在真正动手前先说说HER适合搭配哪些基线算法。理论上任何支持经验回放的off-policy算法都可以直接套用最典型的是DQN、DDPG和TD3。如果你用的是PPO这类on-policy算法也得先搞一个经验池出来然后转换成类似off-policy的训练方式操作上会别扭一些。我在实战中主要用DDPG和TD3这两个连续控制算法配套HER效果最理想。环境方面OpenAI Gym的FetchReach、FetchPush、FetchPickAndPlace这类机器人任务就是为HER量身定制的标准测试平台。如果你想快速验证自己的实现对不对先用FetchReach跑通一遍这个任务最简单一个回合里随机探索也偶尔能碰到目标等逻辑没问题了再换到FetchPush和FetchPickAndPlace这种更硬核的任务。3.2 重标注流程的伪代码级拆解我们先把HER接在DDPG上的核心流程过一遍。伪代码如下for episode in range(max_episodes): 初始化环境状态 s0 随机采样原始目标 g 启动一个大小为 T 的轨迹缓存用于存放 (s, a, r, s) 序列 for t in range(episode_length): 根据当前策略和探索噪声执行动作 a_t 环境返回 r_t 与 s_{t1} 把 (s_t, a_t, r_t, s_{t1}, g) 存入轨迹缓存 if 达到目标: 提前结束标记成功 轨迹结束后 对轨迹内的每一步 t 保存原始样本 (s_t, a_t, r_t, s_{t1}, g) 进回放池 按设定的重标注策略计算一个新目标 g 用 g 重新计算这一步的奖励 r_t reward_function(s_{t1}, g) 把重标注样本 (s_t, a_t, r_t, s_{t1}, g) 也存入回放池 从回放池中随机采样 batch更新 Q 网络与策略网络这个流程里有个值得仔细咀嚼的细节重标注不是只在轨迹结束时做一次而是对轨迹内的每一步都做一次。换句话说每条长度为T的原始轨迹最终会产生2*T条样本T条原始样本加上T条重标注样本。这个数据规模放大效应就是HER能稳定收敛的重要原因之一。3.3 数据结构的坑与选择在我第一次手写实现时在数据结构上犯了个低级的错误我把s、g、s分开存存储时没用归一化采样时直接当float32传给网络。结果问题不大但很快发现第二个更隐蔽的问题回放池里原始样本和新样本的奖励尺度不一样。因为原始样本大部分r0而重标注样本的r可能是1网络看到同一批数据里奖励尺度差一大截Q值估计容易震荡。我的解决方式是在采样后统一对奖励做标准化normalize或者在奖励函数里使用距离阈值小量连续奖励混合这样Q目标值波动会温和很多。实践中还有个更稳妥的选择重标注样本和原始样本不要同时进同一个batch。可以把两类样本分开采样、分开更新或者用一个比较大的回放池靠随机采样去自然混合。我最终用的是混合进池、统一采样方案但把重标注比例控制在了0.5左右效果良好。3.4 超参数的倾向性经验训练HER时会涉及几个超参数我直接给出我反复试过之后觉得比较稳的配置参考回放池大小建议至少50万到100万条因为重标注样本会占据大量空间池子太小会把原始经验挤掉。每回合重标注样本数如果轨迹长度是50我倾向于把重标注样本数设置在64到128之间覆盖整条轨迹千万别只取末端几步。batch size256比较均衡太小会让重标注带来的数据增广效果受限。探索噪声DDPG里初始噪声建议偏大如标准差0.3训练到中后期再线性衰减到0.05左右。HER让失败轨迹也变成有效经验所以前期大噪声反而帮助更大。actor和critic学习率3e-4到1e-3区间都试过对FetchReach这种简单任务差别不算大但在FetchPickAndPlace这种复杂任务里3e-4更稳。这些参数不是银弹但它们来自真实工程的反复调测至少能让你在起步阶段有一个不会出大错的基准线。4. 常见失败模式与调试实录4.1 训练不收敛的典型原因用了HER之后最常遇到的问题不是“不学”而是“学了之后震荡甚至倒退”。第一次遇到这种情况时我一度怀疑是重标注策略选错了后来逐一排查发现问题大多出在别的地方。第一个高频原因是目标分布和初始目标分布不一致。HER重标注出的目标来自轨迹末端而这些轨迹末端大概率聚集在某些容易被探索到的区域。如果这些区域和真实目标区域相差很远网络会被误导着向“容易到达的区域”聚拢真实目标反而被抛在脑后。这也是为什么random策略在复杂任务里基本不顶用——它随机采样的目标成功率太低造出来的全是“虚假的成功”。面对这个问题我的调整策略是提高future选择比例让重标注目标尽量靠近轨迹后段同时降低探索噪声的衰减速度避免agent过早鎖定在某个局部区域。第二个高频原因是动作空间和状态空间的尺度问题。HER喜欢把任务重构成“从初始状态出发尽量接近末端状态”的形式但如果状态向量里不同维度的尺度差太大比如位置坐标在0到1之间速度却能达到几十目标重标注产生的Q值学习信号会被高方差维度带偏。一个好的检查方式是训练前对状态和动作做归一化或者用VecNormalize这类工具自动处理。4.2 重标注比例的“玄学”有必要把“重标注比例”这个参数单独拿出来说说因为它对训练稳定性的影响比我想象中大得多。我做过一组对照实验每轨迹长度为50每条轨迹只取最后10个状态做重标注和每步都做重标注最终的策略收敛速度相差了大约2倍。很多人直觉上觉得“重标注越多越好”其实不然。如果你对每一步都重标注样本里会混入非常多“目标就是在不远处”的小步型样本agent会变得非常擅长“原地微调”却丧失远程探索能力。我的的经验是重标注频率需要和任务难度匹配简单的任务频率可以低一些复杂任务频率可以高一些。拿FetchPush这种需要长程规划的任务来说我最终把重标注频率设在0.8到1.0之间再配合future策略效果就明显优于全程无脑重标注。4.3 与网络结构和策略差异相关的坑还有一个容易被忽视的问题是critic网络的输入设计。HER的训练数据里同一个转移样本会被重标注成多个目标下的不同样本。如果你把s和g直接拼接成一个大向量送进critic网络需要额外学习“哪些维度属于状态、哪些属于目标”的对应关系难度会上升一截。我自己实测下来把s和g分两条路径输入、在中间层融合的做法比直接拼接的效果要好尤其在目标维度比较高的任务里。这个技巧不是HER论文里的主要内容但确实提升了我后续实验的稳定性。另外如果你用的是DDPGactor更新频率和critic更新频率要保持合理比例。HER能不费吹灰之力产生很多正样本批判网络critic的Q值会迅速变得“乐观”actor跟着受诱惑可能收敛到试探性动作上。我在实践中会把actor更新频率降为critic的一半或者在critic更新时不更新actor这样反而学得更稳。5. 工程落地与扩展思路5.1 从单目标到多目标、并行化的扩展HER在简单的单目标任务里效果已经很好但真正体现它优势的场景其实是多目标任务。想象一下你让一台机械臂学会“抓取并放置”多种不同物体传统做法是每个物体单独训练一次策略每次都要收集大量经验。HER的重标注逻辑可以天然复用同一条轨迹的多条成功经验多目标共享一个经验池时训练效率提升是叠加式的。我做过一个稍微复杂一点的多目标抓取任务目标是让机械臂把不同颜色的方块放到对应颜色的目标点上。每个episode里目标g是一个包含物体位置和颜色标签的组合向量。采用HER后每条失败轨迹的重标注目标可能从“红色方块到左上角”变成“蓝色方块到左下角”等于一次性把一整个任务族的知识都喂给了网络。最终这个多目标策略用了不到单目标训练量两倍的数据就把四个子任务全部学会了。如果还需要进一步提速可以上并行环境。HER本身不依赖于on-policy数据所以多个环境并行跑、统一把轨迹送进一个共享回放池是完全没有问题的。我一般用8到16个并行环境跑复杂任务时能获得接近线性的加速比。5.2 HER与其他强化学习技巧的组合这里分享一下我在组合技巧上尝试过并觉得有效的几组搭配。HER TD3的组合比HER DDPG更稳。TD3自带的clipped double-Q学习和延迟策略更新本身就减低了“Q值过高估计”的风险和HER产生的丰富假阳性样本搭配起来互相弥补。我在连续控制任务里基本默认这套组合。HER 课程学习Curriculum Learning的思路也很有潜力。经典做法是从简单目标开始训练然后逐步增加目标难度。HER的重标注策略本身就起到了一定的课程作用从容易达成的事后目标往原始目标迁移在此基础上再叠加“目标难度递增”的采样分布能进一步加快收敛。我自己实现的方式是前20%的训练时光用future策略重标注之后逐步提高原始目标采样比例。另外还有一条小技巧给buffer里的样本打上目标种类标签训练时按目标类别计算优先级或做平衡采样。这个技巧在目标种类差距悬殊的任务里特别有用可以防止某类目标的经验完全占据buffer、淹没其他目标的学习信号。5.3 从二维仿真到真实机器人部署的体会仿真任务里跑通HER是一回事把它挪到真实环境是另一回事。我后来在一台真实的六轴机械臂上试了一下HER训练出来的策略发现仿真里学到的知识迁移到真实世界会有几个落差。第一个落差是观测噪声。仿真里状态是精确的真实环境中相机观测存在噪声导致HER重标注出的目标位置也跟着漂。解决思路是加一层状态估计网络或者滤波把观测噪声压到阈值以下再进策略。第二个落差是动态延迟。真实机械臂执行动作有延迟仿真里没有。HER规划出来的“事后目标”往往要求一步到位真实环境下同样的动作会在延迟阶段引入误差。我当时给控制频率降低了一半再配合阻抗控制策略才基本复现出仿真里的稳定表现。我不会建议你一上来就跳过仿真直接上真机。先把仿真练到很稳然后从最简单的推箱子任务开始做domain randomization逐步暴露给真实环境。在这个流程里HER最大的优势是你的策略天然具备“多目标泛化”能力就算真实世界的初始条件发生了偏移agent也能通过自适应调整找到可行路径。5.4 一点后话HER的局限与拓展思路好话说了这么多也得提一嘴局限性。HER处理“稀疏奖励”问题很擅长但并没解决“探索根本够不到的状态”这个问题。如果初始状态和目标状态之间的状态空间巨大而动作空间又高维随机策略下agent连“事后目标”都很难产生重标注也就无从谈起。该用强化学习里的哪种探索机制还是得具体问题具体分析。另一个局限是它对轨迹长度的敏感性。轨迹太长的话每回合要存的数据量很大重标注的计算开销也跟着上涨。实际大规模训练时我会把轨迹长度控制在50到100步之间太长的任务要先用其他手段比如动作语义化、分层RL简化。我自己心里有个关于HER后续演进方向的预判把目标表征从“状态本身”扩展到“状态的语义属性”比如把“桌面干净”这类抽象指标拆成多个子目标。只要目标能定义清晰HER的“事后重标注”逻辑就能继续沿用。这个方向上已经有了不少衍生研究未来也会是迁移学习与多任务RL的重要支点。6. 写在最后HER真正教会我的事我个人在实际操作中最深的一点体会是HER最重要的贡献不是那一套重标注算法本身而是它提供了一种看待失败的方式。我们总默认训练数据必须来自真实成功但HER证明了只要事后愿把失败“换一个角度解释”它照样可以成为超级学习信号。这个思路一旦打开能迁移的使用场景其实比想象中多得多——不只是机器人控制包括推荐系统中行为序列的重塑、游戏AI对局策略的复盘甚至一些离线RL场景里“死数据”的重利用都能借鉴这套逻辑。在工程习惯上我最后还想再分享一个小技巧训练HER任务时一定要全程记录buffer里原始样本和重标注样本的比例曲线。你会发现这个比例随着训练推进一直在漂移而每当你感觉到策略突然震荡时这个曲线几乎总能提前预警。不要等到loss爆炸了才去看曲线强化学习的训练过程里样本分布比loss更能反映真实状态。如果你正准备在自己的任务里尝试HER别一上来就用最复杂的机器人环境。先用一个你能完全掌控的小任务跑通整个数据闭环再把任务难度逐步加上去。这条路我走过虽然有些弯但一旦跑通你会在训练曲线里看到完全不同的一幕失败的轨迹不再沉寂它们正在一遍遍地教你智能体什么叫“下一次更接近成功”。