多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

HER算法实战:用事后经验回放破解稀疏奖励难题

HER算法实战:用事后经验回放破解稀疏奖励难题 1. 从“事后诸葛”到强化学习hindsight 这个词的含金量英文里 hindsight 指的是“事后才看明白”中文常调侃成事后诸葛。放到算法优化里看这其实是一类很被低估的先验你不需要提前知道正确的目标是什么只需要在失败之后回头看发现“如果当初目标换成另一个方向这次经历其实挺成功”。我第一次认真琢磨这个词是在复现 OpenAI 2017 年那篇《Hindsight Experience Replay》的时候。标题直译就是“事后经验回放”当时觉得这是给稀疏奖励下的强化学习续命的一招。真正跑起来才发现这个思想比算法本身更值钱它把“失败样本”重新签名为“其他目标的成功样本”让一个什么都不会的策略在冷启动阶段也能持续获取学习信号而不是在探索死区里空转。这篇文章是我把 HER 完整落地到机械臂抓取与仿真导航任务过程中的总结。如果你正准备训练抓取、让智能体在稀疏奖励迷宫里去达成某个目标或者想搞懂多目标强化学习中的目标重标记relabeling到底怎么实现这篇文章基本覆盖了从原理到工程实现的全部关键点。看完你应该能自己接上 DDPG也能避掉我在调参路上踩过的大部分坑。1.1 我为什么会盯上 hindsight 这个方向当时的项目背景很简单仿真环境里有个七自由度机械臂要从台面上抓取一个方块放到目标位置。任务只给一个稀疏奖励——方块中心与目标点的距离小于阈值就算成功给 1其余情况一律 0。这样一个看似简单的任务我用普通 DQN 和 DDPG 跑了一周成功率依然趴在 0% 到 1% 之间。后来翻论文时看到 HER才意识到问题不在网络结构也不在超参数而在“所有失败经验都被浪费了”。机械臂每一次都能推动方块只是没推到目标点。如果把这些轨迹标记为“失败”丢弃策略永远不知道“自己刚才其实完成了另一个目标”。hindsight 的核心就是把这种“失败”重新解释成“对其他目标的成功”样本利用率立刻就不一样了。1.2 这篇文章适合谁看如果你正在做连续控制、机器人操作、稀疏奖励导航或者准备复现多目标强化学习论文这篇文章会很对路。我会用偏工程的角度拆解 HER先讲清楚它解决什么问题再讲原理和伪代码然后给出一套可落地的 DDPGHindsight 实现方案最后把训练中遇到的典型问题和排查方式整理成速查表。即便你之前没碰过强化学习只要懂一点点神经网络和策略梯度的基础概念也能跟上推导过程。2. 稀疏奖励与目标条件策略HER 真正要解决的问题2.1 目标条件马尔可夫决策过程HER 面向的不是普通强化学习而是目标条件强化学习Goal-Conditioned RL。这里的核心区别在于策略的输入除了当前状态还包括一个目标向量 g输出动作时要在给定目标的条件下决策记作 π(a|s, g)。在目标条件 MDP 中奖励函数本身就是目标相关的一类函数。以上面提到的机械臂抓取任务为例状态 s 是关节角度、末端位置、方块位置这些信息目标 g 是期望的方块落点坐标动作 a 是各个关节的力矩或位置增量。每一步结束后智能体要判断当前到位状态是否接近目标并给出奖励 r_g(s, a, s)。如果到位状态与目标 g 的距离小于阈值就判定任务成功。这种设定看起来很自然但它在网络设计上有一个隐藏要求状态和目标的表示要分开不能混为一谈。观测空间通常由三部分构成自有状态比如机械臂关节角、期望目标desired goal、实际到位状态achieved goal。很多工程新手在这里翻车把实际到位状态直接当目标塞给网络结果训练到后面完全分不清“自己当前在哪”和“想让我去哪”。2.2 稀疏奖励让梯度信号变成“零”如果任务环境采取稠密奖励比如每一步按“离目标近了给正分远了给负分”来反馈策略还能靠梯度慢慢爬。但很多现实任务根本无法设计稠密奖励或者设计出来的稠密奖励反而诱导出投机行为。于是大家转过头来用稀疏奖励只有成功那一瞬间给 1其余时刻都是 0。这样一来回报信号本身没有坡度整个动作空间里成功路径又只占极小比例。随机探索几乎不可能在有限步数内撞到成功智能体就等于在一个全域零奖励的环境里“瞎走”。我见过不少实验曲线横着走了几万步成功率纹丝不动原因就在这里状态空间高维、动作连续、奖励稀疏、探索困难四个问题叠加在一起。打个比方这就像让一个从没摸过方向盘的人在空旷停车场里找唯一一个车位只告诉他“到了给一分没到不给分”但没有告诉他离车位还有多远。他可能转悠一整天一次都得不到反馈自然学不到任何东西。2.3 事后认知为什么恰好能破局人类解决这种问题的思路很朴素我这次没把方块放到目标点但我把方块推到另一个位置了。那个位置虽然不是预定目标但它本身也是一个合理的落点。如果我把目标改成那个位置那我这次尝试就是成功的。hindsight 的价值就在这里它不要求智能体真的完成指定目标而是让智能体从“已完成的状态”中反推出“如果这是目标我该怎么做”。这样每次探索都不白费因为只要轨迹末端产生了一个可观测状态就能把这个状态当作替代目标来构造正样本。从数学上看替代目标样本配合稀疏奖励相当于给数据分布加入了一个“隐式课程”。训练初期策略先把容易达成的目标学会因为替代目标往往离当前实际轨迹更近随着策略能力提升它才能逐步完成更难的原始目标。这种由易到难的过程不是人为设计的而是重标记机制天然带来的。3. 拆解 HER 核心机制让失败经验改签身份3.1 经验回放与目标重标记HER 的原始做法非常干净智能体在训练过程中照常和环境交互把每一步经验都存进回放缓冲区。区别在于每次采样一个 batch 用于更新网络时算法会额外抽取一部分经验把它们的原始目标 g 替换成同一轨迹中某个未来时刻的“实际到位状态”g然后再用 g 重新计算奖励。关键点在于替换的从来只有目标向量和奖励状态转移、动作、下一步状态这些物理事实全部保持不变。我们还是拿同样的状态、同样的动作、同样的结果去训练只是给这次经历换了一个“解释口径”。原本一个 0 的失败样本在稀疏奖励下重新算出来可能变成 1因为到位状态恰好和历史某个未来状态重合。这里有个很容易误解的细节HER 重标记是在采样阶段做的不是存储在缓冲区里的物理修改。如果你想当然地把重标记后的样本写回缓冲区后面再采到同一个原始样本覆盖关系会乱掉训练稳定性立刻崩给你看。正确做法是保留原始经验只在每次采样后生成重标记副本两者一起参与更新。3.2 伪代码视角下的一次完整迭代把算法展开成可执行的步骤大概是这样对每个 episode 初始化状态 s0采样一个原始目标 g 执行 rollout得到轨迹 (s_0, a_0, s_1, ...) 把原始经验存入回放缓冲区 R 针对轨迹中的每个时间步 t 从同一轨迹的未来状态t1 到 T中随机采样一个 g 用 g 重新计算奖励 r r_g(s_t, a_t, s_{t1}) 把重标记样本 (s_t || g, a_t, r, s_{t1}) 存入 R 从 R 采样一个 mini-batch 用 DQN 或 DDPG 等离线算法更新 Q 网络和策略网络论文里常见的做法是原始目标样本和替代目标样本按 1:4 的比例混合。也就是每个经验除了保留原目标版本还会额外生成 K 个替代目标版本。我在实践中一般取 K4这个值在多数任务里表现都不错。如果你任务的目标空间特别大或者分布特别复杂可以把 K 加大到 8 试试但不要无限加否则原始目标的任务信号会被稀释得太厉害。3.3 HER 为什么能稳定提升样本效率先看一个最直观的收益原本一条稀疏奖励轨迹里几乎只有最后一两步可能产生非零奖励其余全是 0。重标记之后每个轨迹点都可以通过“把目标设为未来某个状态”的方式获得新奖励信号而且这个信号因为状态接近目标大概率是正样本。数据不再是一潭死水。更深一层HER 实际上改变了策略的优化方向。普通强化学习只学“如何达成给定目标”但在探索初期给定目标几乎都是不可达的梯度也因此失效。HER 先把“如何达成可达目标”学好让策略具备把状态拉近目标的能力这种能力天然迁移到原始目标上。这也是为什么它能适应从简单到复杂的目标分布相当于自动课程学习。这里也要说明白 HER 的边界它解决的是“奖励信号稀疏但目标可由状态定义”的问题。如果任务根本没有清晰的目标向量或者成功与否和当前状态没有直接距离度量关系HER 就不太适用。比如对话生成、图像生成这种目标很难形式化的场景直接套 HER 很别扭。它最适合的还是机器人控制、导航这类有明确状态空间和距离度量的连续控制任务。4. HER 落地实操接入 DDPG 的全过程4.1 为什么选 off-policy 算法做底座HER 从原理上就依赖经验回放天然和 off-policy 算法绑定。你可能第一反应是“那我用 PPO 行不行”答案是不行。PPO、A3C 这类 on-policy 算法要求更新时使用的样本必须来自当前策略的采样分布而 HER 的重标记样本本质上来自旧策略哪怕通过重要性采样修正也无法妥善处理“目标被替换后回报分布改变”这件事。实测下来HERPPO 基本没有效果成功率和纯 PPO 没啥区别。所以我最终选的是 DDPG或者更稳一点可以用 TD3。它们在连续动作空间里表现成熟而且天然支持大型回放缓冲区。SAC 也可以但 SAC 的熵正则项在多目标场景下需要额外调参前期反而容易不稳。如果你只想快速复现 HER 效果先接 DDPG 最省事。4.2 网络输入与重放缓冲区的设计实现 DDPGHindsight 时网络输入结构要设计清楚。Actor 网络的输入是把自有状态 s 和期望目标 g 拼接成一个向量Critic 网络输入则再拼接动作 a。输出只有动作。到位状态 achieved_goal 不进网络它只用于重标记时计算替代目标。回放缓冲区的条目也要分成两部分存一部分是物理的状态转移 (s, a, r, s, done)另一部分是这条转移对应的原始目标 g。等到采样时如果需要重标记就根据轨迹 ID 找到同一轨迹上的未来状态生成替代目标再构造新样本进网络。我一开始图省事把目标直接拼进状态里存结果重标记时找不到原始目标还得重新拆非常折腾。还是老老实实分开存代码清晰也方便调试。另外缓冲区容量不要省。连续控制任务里DDPG 对缓冲区大小很敏感我一般设到 1e6 级别实在不够就降到 5e5但别低于 1e5。早期策略探索出来的轨迹分布和后期差别很大缓冲区太小会丢掉很多“早期失败但富含信息”的样本HER 的收益会打折扣。4.3 关键超参数和我的初始配置下面是我跑通抓取任务时用的初始配置你可以当成起点不必逐字照抄。超参数初始值说明未来状态采样数 K4每个经验额外生成 4 个重标记目标原始目标:替代目标1:4采样时保证原始目标经验保留一定比例回放缓冲区容量1e6DDPG 类算法需要较大缓冲稀疏奖励阈值0.05距离小于该值视为成功Fetch 系任务常见设置Actor/Critic 学习率1e-3 / 1e-3偏高容易发散偏高慎用探索噪声Ornstein-Uhlenbecksigma0.2冷启动阶段保证随机性训练周期数50每个周期含若干 episode 和若干更新步Batch size256重标记会放大样本量batch 大一点更稳这里我要特别说明奖励阈值。在 HER 的 Fetch 系列任务里0.05 是论文默认值它代表到位状态和目标位置的欧氏距离小于 0.05 米就算成功。但如果你换到自己的任务环境一定要先看看状态量的尺度。比如你的坐标范围是 0 到 100那 0.05 的阈值几乎不可能触发重标记后也造不出正样本整个训练等于白搭。先把阈值定成一个“从历史轨迹统计来看可以偶尔触达”的值再逐步收紧。4.4 训练过程中的观察记录任务环境是基于 Mujoco 的 FetchPickAndPlace 类环境我用 DDPGHindsight 跑下来前 5 个周期成功率基本是 0这个阶段全是探索噪声在瞎动。从第 10 个周期开始重标记样本开始让策略学到“把方块推近某个位置”的基本技能成功率缓慢爬到 10% 左右。后面 20 到 40 个周期是性能上涨最快的阶段成功率从 20% 一路冲到 70%。这时候如果去看 Actor 的动作输出会发现它已经具备“接近方块—抓取—移动到目标点—松手”的完整行为链。到 50 个周期左右成功率基本稳定在 80% 上下不再有明显上涨。一个很值得注意的现象是如果用同样的 DDPG 但不加 HER跑同样周期数成功率始终保持在 0% 左右。两者差距不是 20% 或 30%而是“完全学不会”和“学到不错”的区别。这就是稀疏奖励任务里“有信号”和“没信号”的本质差别。5. 常见问题与排查实录5.1 我踩过的五个典型坑第一个坑用 PPO 跑 HER。我最初看到 HER 框架简单下意识就把它接在旧代码的 PPO 流程里。结果跑了三天成功率动都不动。后来回头读论文才发现HER 这个名字里自带“Experience Replay”它默认就是给离线回放类算法设计的。换到 TD3 之后问题立刻消失。血的教训先确认算法族再动手写代码。第二个坑重标记时把状态和目标搞混。有段时间我在构造新样本时直接把期望目标 g 替换成替代目标顺手把自有状态 s 也改成到位状态想着“让目标更接近状态”。理论上看着合理实际上完全破坏了物理约束策略被训练去预测一个并不存在的状态转移。后来严格规定重标记只动目标向量和奖励状态转移原封不动训练才恢复正常。第三个坑奖励阈值设置不合理。任务环境换成自定义场景后我忘了调阈值仍用 0.05。但该场景坐标范围很大机械臂末端离目标点动辄差好几个单位导致重标记后奖励全是 0。后来我先跑了几条随机轨迹统计到位状态和目标位置之间的典型距离把阈值定在中等距离很快就出现了可学习信号。第四个坑探索噪声过小导致状态覆盖不足。HER 的替代目标是从“未来状态”里采的如果策略从一开始就非常确定、动作输出近乎于零那未来状态全挤在起点附近替代目标也毫无多样性。我一开始把噪声设得很小结果训练曲线平得像心电图。调大噪声之后状态空间覆盖度上来了重标记目标丰富起来学习才真正开始。第五个坑目标空间维度太高。最初我以为 HER 是万能的直接拿它训一个目标是“末端完整位姿位置姿态角”的任务。结果训练速度直线下降因为均匀采样出来的替代目标在高维空间里几乎都是不可达的重标记信号和一维位置目标完全没法比。后来我先把目标降到末端位置三个维度等策略成熟后再引入姿态维度难度才可控。5.2 问题排查速查表症状原因解决方法成功率一直为 0loss 也不下降奖励阈值过大或过小重标记全是 0统计轨迹距离分布重新设定阈值PPO 接入 HER 后无效算法族不匹配换 DDPG、TD3、SAC 等 off-policy 算法训练后期策略震荡原始目标样本比例过低提高原始目标占比或减少 K 值状态被替换导致 loss 发散重标记把 s 改成了 achieved_goal只改目标与奖励保持状态转移不变替代目标没有多样性探索噪声过小提高噪声或增加随机动作概率高维目标空间学不动均匀采样无法覆盖目标空间目标降维、按距离加权采样或策略生成目标5.3 调参顺序心得HER 的参数不多但千万别一上来就想着把 K、阈值、网络结构一起调。我自己的经验是先固定一个能跑的配置再一个一个变量换。优先级顺序参考这样的思路——先确认奖励阈值合理再确认重标记有没有生成足够多的正样本然后看探索噪声是否让状态空间有足够覆盖最后才动网络容量和学习率。判断重标记有没有生效有一个很简单的办法训练开始时打印每个 batch 里“重标后奖励非零”的比例。如果这个比例长期低于 5%说明替代目标离到位状态太远要从阈值或采样方式下手。如果比例高于 40%说明任务本身已经不难了可以开始评估原始目标成功率是否在涨。另一个经验是保存训练过程中的回放缓冲区状态。HER 的样本分布变化剧烈早期样本和末期样本差异很大如果代码突然崩溃能从保存的缓冲区里接着训不至于全部白跑。6. 从 hindsight 向外延伸6.1 自动课程与目标生成HER 本质上是一种隐式的自动课程替代目标大多是可达的所以策略先学简单目标再逐步逼近原始目标。顺着这个思路继续走就是让目标生成变成显式的过程。比如 GoalGAN 这类方法用 GAN 去生成难度合适的目标让策略始终被推着走向“跳一跳够得着”的境界。相比 HER 的随机采样显式生成可以在高维目标空间里更有方向性地选择任务难度。我之前尝试过在 HER 基础上加一个简单的“距离加权采样”替代目标不从未来状态里均匀采样而是优先选那些离当前位置适中、既不算太近又没有远到完全不可达的状态。这样做的直观效果是训练后期的成功率曲线比纯 HER 更平滑尤其在高维任务里提升明显。它的原理也好理解均匀采样在高维空间里会让目标大多落在中远距离范围而人类学习新技能的节奏本来就是“先近后远”。6.2 与好奇心、模型预测控制的结合HER 还有一类很有价值的组合方向和内在好奇心机制结合。HER 的优势在目标重标记但它的替代目标仍然依赖智能体实际探索到的状态。如果探索本身特别差比如机械臂一直缩在角落不动那未来状态全挤在一起重标记目标也没啥用。这时给策略加一个内在奖励鼓励它访问“预测模型认为意外”的状态就能有效拓宽轨迹散布为 HER 提供更丰富的历史状态池。我实际测试过“HER内在好奇心”的版本相比纯 HER在冷启动阶段的状态覆盖率明显更高达到同样成功率所需的周期数大约缩短了三成。当然代价是要维护一个预测误差网络训练开销更大。如果你的任务不差那点算力这是个很推荐的组合。反过来如果任务本身就容易探索只是目标不好达成那加好奇心就是徒增麻烦。另外基于模型的强化学习也可以和 hindsight 结合。模型预测控制能给出更多有依据的未来状态作为候选目标替代目标的“可达成性”会比随机采样更高。学术上这类工作路线已经不少工程上建议先跑通标准 HER再逐步叠加。6.3 最后说点个人体会我从这个项目里学到的最大一课不是 HER 的公式或者重标记的细节而是“不要轻易放弃看似无信号的失败数据”。很多强化学习项目卡住不是策略网络不够强是数据利用方式太粗暴。把失败当成垃圾丢掉和把失败重新解读成经验训练效果完全是两个世界。hindsight 这个词也很妙它提醒我们回头看的时候总能从过去里挖出本来没注意到的价值。放到算法里这种智慧变成了数据增强放到工程里它意味着每次失败的实验曲线都值得存档和分析因为换个角度它们可能正好是某个目标点的成功样本。我现在每次训练新任务前都会先问一句这些“失败”数据里有没有藏着一条能用的“成功”曲线
返回列表