ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

稀疏奖励下的强化学习突围:HER事后经验回放原理与工程实践

稀疏奖励下的强化学习突围:HER事后经验回放原理与工程实践 如果你在一个稀疏奖励的强化学习任务里折腾过那你大概率体验过那种“奖励永远是零模型打死不学”的绝望。我最早在做机械臂抓取任务时模型训练了几十万步成功率还是零当时的调试心情不亚于对着一个不会叫的电话喂食。后来真正救了我的不是换网络结构不是调学习率而是换了一种思路允许模型“事后给自己编一个目标”。这个词在英文里叫 hindsight也就是“后见之明”。它后来成了强化学习领域一个标志性的技巧——Hindsight Experience ReplayHER事后经验回放。这篇我把自己从原理到工程实现的一整套理解都整理出来顺带着踩坑记录和调参心得。不管你是刚入门强化学习、准备复现论文还是已经开始做机器人控制或策略学习这篇应该都能帮你把概念落地成可运行的实践。hindsight 这个词非常有画面感人总是在失败之后才后知后觉“刚才为什么要那样”。而 HER 做的事恰恰就是把这个“后知后觉”变成训练信号让算法从自己的失败轨迹里挖出正面的经验。这个思想初听很绕但一旦吃透你会觉得稀疏奖励问题顿时有了一个朴素又不失聪明的解法。1. 一个词讲清楚HER事后诸葛亮的强化学习1.1 为什么强化学习会“撞墙”先说说我遇到的最经典的场景。目标是让机械臂把物体推到某个指定位置环境通常只有一个奖励如果物体距离目标的欧氏距离小于某个阈值给 1否则给 0。这就是教科书级别的稀疏奖励问题——奖励只在一个极窄的区间内出现而初始状态下机械臂乱动一百步可能一下也没碰着那个阈值。问题在于普通强化学习靠的是“奖励反馈”来调整策略奖励全是 0等于梯度全是空的。哪怕你用了 DQN、DDPG、PPO 这些算法策略网络也没有任何有意义的信号去改变参数。有人可能会说给一个惩罚每步 -1逼它快点到达目标但实际测试会发现模型学到的是“原地罚站”或者干脆打转并不会真的学会接近物体。这个问题的本质是目标太难而环境给不了中间台阶。所谓“万物可学”的前提是你得让模型有一套从失败中提取有效信息的机制而不是永远面对一片虚空。1.2 事后诸葛亮把失败经验变成教材HER 的想法其实特别像我们平时做复盘。比如你投篮目标是正中篮筐但球砸中了篮筐右侧弹了出来。如果只看结果这次是失败的奖励是 0。但反过来想如果设定的目标是“让球碰到篮筐右侧”那你其实已经完成了这个目标。整条轨迹对“篮筐右侧”这个虚拟目标来说是一段百分之百成功的经验。在 HER 里算法会缓存一条真实轨迹它原本设定的目标 g实际走过的状态序列 s_1, s_2, ..., s_T以及每个状态对应的动作。在回放的时候我们不是把原目标 g 当成轨迹目标去训练而是把轨迹末段实际到达的状态 s_T或者其他某个中间状态改写成目标 g然后把这组数据放进经验池。这样一来哪怕模型压根没达到初始目标它也照样拿到了一截“成功轨迹”状态 s_t 是接近 g 的动作 a_t 是带着目标完成的奖励是 1。这些经验被用于训练模型会慢慢理解“如果我想去这个新目标我应该这么行动”。当它积累了大量这样“事后成功”的经验后再面对原来的旧目标时反而会有足够的知识去完成它。这就是它的核心哲学与其亡羊补牢不如把每只羊走过的路都变成一条正道。1.3 “HER到底有什么用”速览如果你想判断某个任务适不适合用 HER可以看这几个条件任务有一个清晰的目标表示比如坐标、位姿、属性向量能写成向量形式奖励是稀疏的或者根本没有中间奖励环境是可重置的、可以重复采样的最好是模拟器目标是条件式的也就是说策略的输入中带有目标信息适合的例子非常多机械臂推箱子、抓取、移动物体到指定位置又比如迷宫导航、多智能体协作中的“到达指定据点”甚至对话推荐系统里“让用户最终选择某类商品”这种任务也可以抽象成目标型任务。只要满足“目标能表示成向量”和“稀疏奖励”两个条件HER 基本都能发挥作用。2. 对比三种常见解法HER凭什么能唱主角2.1 奖励塑形看似直接实则伤筋动骨很多新手会想稀疏奖励是吧那我给距离奖励不就好了。物体离目标近一点奖励高一点这不就有梯度了嘛。奖励塑形本身没有错很多人也在工程系统里这么干。但问题在于设计一个好用的奖励函数非常难。你用一个 L2 距离当奖励模型可能学会很奇葩的路径——先远离目标再绕回来因为某个中间状态恰好使 L2 距离变短却让路径更长。有时为了“刷奖励”模型甚至会原地抖动因为只要靠近目标就有正反馈至于最终能不能稳定停在目标位置反而不重要。我见过一个项目项目组为了让机械臂学习快一点把奖励函数改成了带权重的距离惩罚结果模型不但慢了下来还学到了一个“高频抖爪子”的作弊策略。这种情况不是少数。奖励塑形本质上是在人工编码任务先验你设计得越细引入的偏置就越多越容易产生手术式修补。2.2 课程学习需要大量人工设计扩展性受影响课程学习的思路也很自然先让模型学简单的任务再逐渐过渡到困难任务。比如先让机械臂把物体推到离目标很近的位置等成功率上去了再拉远初始位置。这种方法确实有效在某些场景下效果很惊艳。但问题也很明显简单的任务谁给你定义如果你可以设计“离目标 10cm”作为第一阶段那其实你已经对任务做了很多分析。换个环境、换个物体、换一套随机化策略课程可能完全不适用。而且课程节奏很难把握早一步模型学不会晚一步浪费时间。如果你做的是多目标任务课程设计基本是一场灾难因为不同目标的困难程度互相纠缠人工给它们排序列非常痛苦。2.3 为什么HER更优雅目标重标注HER 最大的优势在于不需要额外设计奖励不需要人工设计课程它在训练机制上做文章把“真实目标”替换成“实际到达的目标”自动把困难任务转成简单任务。从理论上说它是从贝叶斯视角做了一件事把后验中更可能成功的假设当成了训练样本。用更直白的话形容就是普通经验回放是在一堆失败里寻找成功HER 则是先主动把失败判定为成功然后再学习这段轨迹。数据量没有变多但数据内部蕴含的“指导性”变强了。这也是为什么我遇到做机器人任务的朋友第一个推荐的技巧就是 HER。它不挑算法可以和 DDPG、TD3、SAC、PPO 等主流算法结合而且改动量很小。毕竟它修改的只是经验管理方式不是策略网络的结构。3. 算法内部机制从轨迹到重标注的一整套动作3.1 从一次采样到回放HER在流程上做了什么HER 的完整训练循环可以拆成 5 步。第一步采样一整条完整轨迹从初始状态出发一直到任务失败或达到最大步数。第二步记录下这条轨迹里每步的状态、动作、下一状态、奖励还有初始目标。第三步构造新目标。通常是从这条轨迹里挑一个“实际到达过的状态”把它封成 g。第四步把原目标 g 和新目标 g 分别配上这条轨迹生成多份经验数据。第五步把这些数据放进经验池等待策略更新时被采样。这里有一个很容易误解的点同一段真实轨迹因为你给它配了不同的目标 g它就能被转化成多条不同含义的经验。比如第一份数据里目标是房间左下角状态是逐渐接近右下角的奖励是 0这表达的是失败第二份数据里目标改成了右下角状态是一路接近右下角的奖励是 1这表达的是成功。同一批状态因为视角不同一个成了负面教材一个成了正面教材。这种构造方式让经验池里的数据分布和真实任务的目标分布产生了一个巧妙的偏移训练策略时新目标出现的频率更高而这些新目标大多对应着实际容易到达的状态于是模型有一个非常密集的正反馈训练面。这也是 HER 能加速收敛的根本机制。3.2 目标重标注的公式除了“最终点”还能选哪些目标重标注听起来简单但具体选择哪个新目标很有讲究。最常用的是把整条轨迹的最后一个状态 s_T 当成新目标因为它是“实际结果”最符合事后诸葛亮的逻辑。但如果你只是按“终点”来选经验多样性还是有限。所以我们通常还会用以下策略去生成候选目标集。第一个策略从整条轨迹里随机抽取 k 个状态比如从中选一个状态作为新目标。这样做的好处是中间状态比最终状态更能体现“过程正确”当任务需要分阶段完成时这种策略经常比只用终点效果更好。第二个策略选择轨迹末尾几步的状态比如取最后 1/4 段里的随机一个状态。这比纯终点有更多变化又不像全局随机那么跳适合目标任务难度中等的场景。第三个策略只选最终状态。这样对应的是“我只关心终点”的任务特性简单直接在部分任务里能获得最好效果。我在应用时通常默认用全局随机选 k 个候选目标。因为全局随机能让目标分布更丰富相当于隐式地构造了多个从中间位置出发的子任务模型学到的策略更平滑。但要注意的是如果你选的目标离当前状态太远比如选了轨迹开头的状态而轨迹本身很短那么这个目标可能离轨迹其他状态都非常远学习信号依然稀疏效果反而差。所以候选目标的集合最好和轨迹长度匹配不要出现目标点和轨迹本身没有交集的情况。3.3 回放策略与目标概率每个参数都有讲究光构造新目标还不够能不能被用起来回放策略同样关键。HER 的最典型做法是每一条原始轨迹除了保留一条“原目标经验”再额外生成 N 条“新目标经验”这些经验会一起进池子。论文里的对比实验显示如果只保留原目标经验和普通回放没有任何区别如果新目标经验过多比如新目标经验压过了真实目标模型又会偏离原始任务。这里有一个重要的超参数叫未来时间步数 K即未来状态采样范围。每次采样新目标时我们不是真正从所有状态里等概率挑而是从轨迹的当前时间步 t 之后的未来状态里挑。这个“未来”的范围就是 K。比如 K4表示从 t, t1, t2, t3 这四个状态里挑一个当目标。为什么必须是未来状态因为这样新目标基本上都规划在轨迹的“前面”模型学到的动作序列是朝目标靠近的而不是朝后走的。在实现里我们会对每条经验的更新时间 t随机生成未来索引 t_future然后从轨迹中那个未来时刻的实际状态生成目标。策略概率通常是这样的以概率 1-\beta 使用原始目标 g以概率 \beta 使用重标注目标 g\beta 常见取值在 0.2 到 0.5 之间。当初的实验结果表明即使把 \beta 取到 0.5也就是接近一半的训练样本都是“事后成功”效果依旧很好。我自己的经验是短任务轨迹 20 步以内选 0.2长任务轨迹超过 50 步选 0.3 到 0.5 会比较稳。3.4 HER的训练循环伪代码结合具体代码来看HER 的一次数据构造大概是这样的流程我用伪代码示意重点在逻辑def create_her_sample(transition_batch, episode_states, horizon, beta): for each (s, a, r, s_next, g) in transition_batch: if random.random() beta: # 从未来状态里随机选一个作为新目标 future_idx random.randint(t, min(horizon, t K)) new_g episode_states[future_idx] new_reward compute_reward(s_next, new_g) # 存储这份新经验 store(s, a, new_reward, s_next, new_g) else: # 保留原始目标 store(s, a, r, s_next, g)如果你正在用 DDPG、TD3 或 SAC其实改动点就是这一步在往 replay buffer 里写数据之前把“目标”字段做一次重标注然后额外生成几条样本。别的都不用动。4. 手把手实现HER从环境到训练的完整记录4.1 环境怎么选从Bit Flipping到Fetch逐步升级如果你是从零开始复现 HER我强烈建议先用一个简单的环境跑通逻辑而不是一上来就上机械臂仿真。我最初尝试的环境是 Bit Flipping这是一个二进制的输赢问题有一个长度为 N 的二进制序列作为目标比如 10100每次翻转某一位当序列完全等于目标时获得奖励。这个环境特别适合验证 HER 的原理因为它状态和目标是同一套向量表示直观且计算量小。等你跑通了 Bit Flipping再上 OpenAI Gym 里的 FetchReach 或 FetchPush。FetchReach 的任务是让机械臂末端到达一个位置复杂度适中非常适合观察目标重标注带来的曲线变化。FetchPush 则在真实项目里更常见它涉及推杆和物体交互情况更复杂但也是衡量 HER 能否处理“状态与目标交互”的好环境。环境选择上有一个硬性要求状态向量中最好包含当前物体、手臂末端的坐标并且目标的维度要和状态中位置的维度对得上。如果你用的目标维度是 6但状态向量是 18那么模型内部做拼接时必须严格对齐否则逻辑能跑通但训练效果完全不可控。4.2 核心代码骨架目标重标注这一块要写对下面是我实际用 DDPGHER 跑 FetchReach 时的关键代码骨架去掉了无关细节只保留核心逻辑。# 采样一整条轨迹 obs, actions, rewards, next_obs, goals [], [], [], [], [] obs env.reset() goal obs[desired_goal] for step in range(episode_len): action policy.select_action(obs[observation], goal) next_obs, reward, done, info env.step(action) obs.append(...), action.append(...), reward.append(...) goal.append(obs[desired_goal])在将数据写入经验池前做一次目标重标注for t in range(episode_len): for _ in range(her_per_episode): if random.random() 0.3: # 未来采样 future_t min(t random.randint(1, K), episode_len - 1) new_goal achieved_goals[future_t] # 用未来状态代替目标 else: new_goal desired_goals[t] reward compute_reward(next_obs, new_goal) replay_buffer.add(obs[t], action[t], reward, next_obs, new_goal)注意一个细节原目标经验和新目标经验不应该互相覆盖。我当时犯的一个错误是只用新目标替换原目标结果原目标任务的成功率始终上不去因为策略完全被重标注目标带跑了。正确做法是保留一部分原始经验至少整体 50% 到 70% 的样本应该保持原目标新目标经验作为补充信息加入。4.3 超参数清单与训练配置参考给想直接复现的朋友提供一个参考配置我用这套配置在 FetchReach 上从零训练到接近 95% 成功率耗时大约两小时单张 1080Ti也可以用 CPU 跑但很慢参数取值说明算法DDPG HER也可以换 TD3效果类似经验池容量20 万条稀疏奖励任务建议大池子每 episode 额外生成的目标经验数4 条原经验 1 条新目标 4 条未来时间步 K4越大的 K 能让目标离当前状态更远目标重标注概率 β0.30.2 到 0.5 都可网络隐藏层三层每层 256经验池数据多样容量要够批量大小128偏大利于稳定Actor 学习率1e-3要配合 her不能过大Critic 学习率1e-3同上探索噪声N(0, 0.2)加大噪声有利于采样到更多状态折扣因子 γ0.98结合轨迹长度别用 0.9 这种更新次数每 episode 更新 40 次相当于每个 episode 内模型更新较频繁这里要解释一下为什么池子要开这么大。HER 在训练时会不断加入重标注数据池子如果太小新数据很快会把旧数据冲出去。而重标注数据本身还包含“当前目标分布”和“未来目标分布”的偏移需要足够大的池子来混合这些分布否则梯度噪声爆炸训练反而不稳定。我试过把池子缩到 5 万条结果曲线震荡得像心电图。4.4 训练指标怎么看成功率比平均奖励更有意义很多教程习惯盯着平均奖励看但在稀疏奖励任务里平均奖励会长期趴在 0 附近看了让人心慌。我建议把评估指标换成“多目标成功率”每隔一定步数在测试阶段随机采样 100 个初始状态和目标让策略去跑算一算在限定步数内完成任务的比例。这个指标在训练初期可能一直是 0但在某个阶段会突然快速上升。那种曲线从 0 跳到 95% 的瞬间是 HER 最有成就感的时刻。我当时记录了训练曲线前 100 个 episode测试成功率为 0到第 300 个 episode突然出现第一个成功案例随后在 400 到 700 个 episode 之间成功率指数式上升。当达到 95% 后曲线还会保持很长一段基本不回落。这种“从零到爆发”的模式其实就是重标注经验带来的正反馈开始压过随机探索带宽的典型表现。5. 踩坑实录HER不work的五个典型原因5.1 目标维度拼接错误这是最隐蔽的坑HER 要求策略网络的输入中包含目标向量。很多新手把状态和目标的拼接维度搞错了但程序不报错因为张量形状刚好匹配。比如你本意是把 [状态(18维), 目标(6维)] 拼成 24 维可代码里写成了只拼状态或只拼目标网络照样可以前向传播损失却完全不下降。排查这种问题最有效的办法是找一个超简单的“单目标环境”比如固定目标不动用普通 DQN 训练试试如果还是学不动那多半是输入拼接逻辑错了。5.2 目标重标注频率过高导致“忘本”我在早期实验中把每条轨迹额外生成 8 条重标注经验结果训练起来特别快前几百步就看着损失哗哗下降但跑到 800 步后原始目标的成功率却始终在 20% 徘徊。回头看原因重标注经验占训练数据 90% 以上策略完全被带偏学到的动作虽然能让重标注目标顺利完成但对真实目标的覆盖能力极差。这个问题很隐蔽因为只看 loss 和重标注目标的成功率一切正常。解决办法是经验池中保留足够的原目标任务样本。我的经验是把额外经验条数控制在 4 到 6 条并且重标注概率保持在 0.3 左右这样原目标任务成功率能长时间维持在高位。5.3 探索噪声不够重标注也没用HER 依赖探索策略采集到多样化的状态。如果你把动作噪声设得很小比如 DDPG 里设为 0.01那整个轨迹基本都是确定性输出状态总是打转新目标也总在相似的位置重标注经验多样性会很低。这个坑我印象很深一开始我用很少的噪声训练HER 根本不起作用后来把噪声增到 0.2训练效果立刻好了很多。要理解 HER 本质上是“从探索过程中偶然发现的状态”里提取经验探索不足经验池就是空的。5.4 批量大小和网络容量不成比例很多简化实现的网络只有两层 128 个神经元这在简单任务上没问题但在稍复杂的 FetchPush 或更复杂的机器人任务上就不行了。HER 会产生大量不同目标的数据这些数据本质上对应着不同的子任务网络容量太小无法拟合“目标条件策略”的复杂函数。我最终在 FetchPush 上用的是三层 256批量大小 128这和论文原始配置一致效果才起来。如果发现损失函数死活压不下去或者训练曲线极其缓慢优先检查网络容量然后再考虑超参数调整。5.5 测试方法不对用随机目标而非固定目标评估有时候模型其实已经学会了任务但你测试的成功率一直很低。最大的可能性是你把测试目标设置得太随机。在 FetchReach 里目标是随机采样出来的如果空间范围过大模型可能真的没见过这些目标。正确做法是先对测试目标做一次分布统计看看模型训练时接触到的目标空间和测试目标空间是否一致。如果测试目标超出训练覆盖范围你应该调整测试策略先做固定目标测试确认模型能完成任务再逐步扩大目标范围。我见过有人调 HER 调了一个月结果只是测试目标采样范围设太大模型在部分目标上确实没学好但成功率曲线完全可以做得更高。这个坑听起来不诡异但每次测试配置一换结果忽高忽低极其折磨人。6. 扩展方向与个人体会6.1 和其他算法结合从DDPG到TD3、SAC甚至PPOHER 可以和多种策略梯度算法结合并不局限于 off-policy 算法。DDPG 是最自然的组合因为它天然支持经验回放TD3 也不错因为 HER 经验的多样性正好适合 TD3 的稳定特性。如果你用的是 SACHER 也很好用不过 SAC 对经验池容量和熵温度参数更敏感需要额外调。PPO 这类 on-policy 算法用 HER 需要做一点变通常规做法是先收集大量轨迹在更新前做目标重标注生成虚拟经验然后在此基础上计算 PPO 的 surrogate loss。这在实现上比 off-policy 复杂一些但效果也不错尤其在动作空间不连续的任务上。今年发布的不少大模型对齐 task 也会借用类似思想在拒绝采样后对“接近目标但没完全成功”的轨迹做重标注。所以 HER 不止是一个强化学习算法它已经成了一种经验构造和增广范式。6.2 从仿真走向真实机器人如果你准备把 HER 用在真机上有两点必须早做准备。第一真机采集轨迹的时间和成本远高于仿真所以经验池的利用效率非常关键建议优先采用 TD3HER 并配一个大容量经验池减少重新采样的频率。第二真机环境的动力学模型和仿真有差异目标重标注需要加一个“置信度门控”只有当你认为实际到达的状态确实是策略可以达到的才把目标重设为它。否则模型会学到一些在真机上无法复现的脆策略。我在真机部署时还额外做了一步用实际传感器读到的末端位置代替仿真中的 ground truth 来重标注目标这样即使视觉定位有偏差模型也能学习到更真实的目标分布。这算是一个很务实的工程技巧。6.3 扩展应用多智能体、对话系统、推荐系统HER 的目标重标注思想其实可以迁移到很多和“目标-状态”结构相关的领域。比如多智能体路径规划中智能体没到达预设目标但到达了另一个智能体的位置这也可以当作一个成功样本。又比如对话系统中用户最后选择了推荐列表中的 B 商品虽然不是初始推荐的 A 商品但可以将 B 商品作为“对话成功目标”去优化策略。推荐系统里也有类似问题推荐结果偏离了初始目标但用户确实发生了点击这种经验如果重标注为成功往往能提升推荐策略的鲁棒性。这些方向都在我一个客户的合作项目里验证过。HER 作为一个通用思想它的下一个热点大概率是和数据增强、离线强化学习结合起来在 offline 场景下不额外采样新轨迹而是直接对 offline 轨迹做目标重标注然后训练一个可以泛化到新目标的目标条件策略。这类方法已经开始出现并应用在实际工程里。最后再分享一个我自己的习惯每次新任务我几乎不做复杂的奖励设计而是先把任务写成“目标条件形式”然后立刻加 HER 跑一版。如果 HER 不起作用再检查目标表示是否合理、状态是否可覆盖、奖励是否过于苛刻。这种调试顺序帮我省过非常多的时间。你如果正在被稀疏奖励折磨完全可以从这里开始先跑通一个最简单的环境再逐步向复杂任务过渡。HER 不是银弹但至少在“目标明确、奖励稀少”这一类任务上它是性价比极高的起手式。
返回列表