HER算法深度解析:用目标重标定破解强化学习稀疏奖励难题

发布时间:2026/10/1 17:17:25
HER算法深度解析:用目标重标定破解强化学习稀疏奖励难题 HERHindsight Experience Replay这几年在机器人强化学习领域几乎成了稀疏奖励问题的标配方案。我最早接触这个算法是在跑Fetch系列机械臂控制任务的时候当时用普通的DDPG训练一个简单的推箱子动作跑了上百万步损失还是纹丝不动换成HER之后几千个episode就能看到明显的策略提升。这个反差让我彻底理解了事后重新设定目标这件事的威力。这篇文章就从动机、原理、实现和实战踩坑几个角度把HER从头到尾拆开讲清楚希望能帮到正在被奖励函数折磨的同行。1. 失败轨迹的价值HER要解决的稀疏奖励困境1.1 机器人操作任务为什么越学越绝望机器人操作任务和Atari游戏、棋盘对弈这类强化学习任务有一个本质区别大多数操作任务是目标导向的。机械臂要把方块推到指定位置、抓取物体放到盒子里、倒水、插销钉这些任务成败只有一个硬标准——末端位姿是否到达目标区域。如果没到达环境就返回零奖励整个episode里你得不到任何关于做得对不对的反馈。我在实际跑任务时体会最深的是FetchPush这个环境一个七自由度机械臂需要把桌子上的方块推到目标点。如果用稀疏奖励智能体在探索阶段完全靠随机动作碰运气命中目标区域的概率低到可以忽略策略梯度几乎为零。标准的DDPG在这种场景下训练几十万步Q值函数根本学不出有用的梯度方向因为所有的transition都是reward0批评网络看到的状态动作对都被标记为没价值于是价值函数退化成一片平坦的平原。这不是调参能解决的问题。你可以把学习率调大、增加探索噪声、换网络结构但只要奖励信号里没有信息量任何基于梯度的方法都束手无策。1.2 密集奖励函数为什么治标不治本既然稀疏奖励学不动很多人第一反应是那我手写一个密集奖励函数。比如用机械臂末端到目标点的欧氏距离作为负奖励距离越小奖励越高。这种方案在简单任务上确实见效快但隐患很明显第一距离度量不一定对应真实的任务语义。抓取任务里机械臂末端接近物体可能比朝向目标点更有价值但手写奖励很难表达出这种中间步骤。第二奖励塑形reward shaping会引入局部最优。我在仿真里见过不少策略学会了把手停在方块上方但就是不抓取的摆烂行为因为这样能获得最高的距离奖励但距离真实目标越来越远。第三换个任务就得重新设计一遍奖励而且从仿真迁移到真实机器人时奖励函数里的物理量力矩、速度、接触力往往在真实环境中难以精确测量整个方案的可移植性非常差。HER的思路完全绕开了这个困境——不修改奖励函数而是修改目标本身的定义。失败的轨迹之所以在一开始被丢弃是因为我们用预定义的目标去评判它。但如果把评判标准换成轨迹实际达到的状态失败就变成了成功抵达了另一个目标。2. 事后诸葛亮HER目标重标定的完整机制2.1 核心思想把没做到重新解释为做到了别的HER的论文标题我记得很清楚原文是Hindsight Experience Replay发表在NeurIPS 2017。它的关键洞察可以用一句话概括一个失败的episode里状态序列本身已经提供了一条通往某个真实状态的有效路径只是这个状态不等于我们预设的目标而已。形式化地说原本经验池里存的transition是(s_t, a_t, r_t, s_{t1}, g)其中g是episode开始时指定的目标。如果最终没有达到g整条轨迹按传统做法会被标记为低价值。HER的做法是额外生成一条重标定轨迹把g替换成轨迹中某个实际到达过的状态g然后重新计算奖励r reward_func(s_{t1}, g)。如果s_{t1}恰好达到或接近gr就是1或其他代表成功的奖励值。我没有在碰瓷平行宇宙这个说法但你可以这么理解原来的轨迹在目标g看来是失败的但在目标g看来就是一条标准的成功轨迹策略网络可以从中学到沿着这段状态序列走下去就能成功的经验。这相当于把每一次随机探索无论成败都转化为对某种目标有用的监督信号。2.2 四种事后目标采样策略的取舍那么g具体怎么选论文里给了四种采样方式我在复现时逐一验证过它们的效果差异final取episode终止时的最后状态作为事后目标。这个最简单对每个失败的episode最多生成一条额外轨迹但目标多样性不足尤其是机械臂任务里最后状态往往和初始状态很接近缺乏中间过程的覆盖。episode从当前episode中随机抽取一个状态作为事后目标。这种方式生成的目标分布比较均匀但会引入大量远距离目标学习效率中等。random从整个replay buffer里随机采样状态。问题在于经验池里老策略的状态分布和新策略不一致目标分布偏移严重实际效果反而最差。future对每个时间步t从当前episode的t1到T之间随机抽取一个状态作为事后目标。论文的实验结果和我的复现都表明这种方式效果最好。future策略的直觉在于它只使用未来的状态作为候选目标保证目标在时间上是有序的、可到达的。在t时刻看来tk时刻的状态是当前策略通过后续动作真实达到的所以它的分布和当前策略的行为高度相关学习信号的一致性最好。论文推荐k从[0, 4]之间均匀采样我实测k4时效果最佳。2.3 重标定后的奖励计算细节重标定之后奖励的重新计算有一个容易踩坑的地方。大多数目标导向任务中reward_func是这样定义的计算s_{t1}中目标相关的部分比如方块位置与目标g之间的距离如果距离小于某个阈值就返回0否则返回-1。注意这里用的是0/-1而不是1/0因为稀疏奖励配合RL算法时把失败奖励设为-1而不是0能够提供更明显的惩罚信号。实际操作时我用的是这样的逻辑def compute_reward(achieved_goal, desired_goal, threshold0.05): # achieved_goal和desired_goal都是三维位置向量 distance np.linalg.norm(achieved_goal - desired_goal) return -(distance threshold).astype(np.float32)重标定后的轨迹会生成replay transitions(s_t, a_t, r, s_{t1}, g)。这些经验和原始轨迹一起放进replay buffer两者比例一般取1:1。这相当于把一次交互的数据用了两遍——一遍服务于原始目标一遍服务于事后目标数据效率直接翻倍。3. 从论文到代码HER与off-policy算法的搭配实战3.1 为什么HER必须寄生在off-policy算法里HER不是一个完整的强化学习算法它是一个数据增强模块必须搭配DQN、DDPG、TD3或SAC这类off-policy算法使用。原因是重标定的transition包含的是过去某条轨迹的数据它们的分布和当前策略不同只有off-policy算法才能从这种过时的经验中学习。而on-policy算法如PPO每次更新必须使用当前策略产生的新数据HER生成的旧数据在数学上会导致策略梯度的估计偏差。在实际工程里我推荐用TD3作为HER的基底算法而不是DDPG。DDPG的Q值过估计问题在机械臂接触和抓取任务中特别严重训练后期经常出现明明实际成功率在下降Q值预测却在上升的虚假乐观而TD3的双Q网络和延迟更新机制能够明显缓解这个现象。我的经验是HERTD3的组合在大多数Fetch类任务上比HERDDPG稳定一到两个数量级。3.2 网络结构与状态-目标编码方式网络结构上HER对策略和价值网络的输入有一个特殊要求状态s和实际目标g需要拼接成一个统一的向量。在Fetch类环境中observation是一个dict包含observation和desired_goal两个key其中observation部分又包含了机械臂关节位置、末端位姿、物体位置等信息。我的做法是把s和g直接concatenatedef obs_to_vector(obs, goal): # obs是机械臂/物体的完整状态描述 obs_flat np.concatenate([obs[observation], obs[desired_goal]]) return obs_flat # 重标定后的目标 new_goal episode_states[future_idx] new_obs_vector np.concatenate([obs[observation], new_goal])网络的隐藏层我用的是三层MLP每层256个神经元激活函数ReLU。对于FetchPickAndPlace这种需要同时控制机械臂和判断抓取状态的任务有过实验显示把目标向量单独通过网络的一部分而不是直接拼进主输入效果略好但并没有显著优势为了代码简洁我统一用拼接。3.3 核心训练循环的完整逻辑HER的训练循环和普通off-policy RL最大的差异在于episode结束后的目标重标定以及额外数据写入。我贴一个我在仿真环境里实际跑通的伪代码框架for episode in range(total_episodes): obs env.reset() episode_buffer [] for t in range(max_timesteps): action policy.select_action(obs) # 加探索噪声 next_obs, reward, done, info env.step(action) episode_buffer.append((obs, action, reward, next_obs, info[is_success])) obs next_obs if done: break # 目标重标定为episode_buffer里的每个transition生成事后目标 her_buffer [] for t, (obs, action, reward, next_obs, success) in enumerate(episode_buffer): future_idx t np.random.randint(0, 4) 1 if future_idx len(episode_buffer): future_idx len(episode_buffer) - 1 her_goal episode_buffer[future_idx][3][observation] # 用未来的状态做目标 her_reward compute_reward(her_goal, her_goal, threshold) her_buffer.append((obs, action, her_reward, next_obs, her_goal)) # 原始数据和HER数据一起进replay buffer replay_buffer.add_episode(episode_buffer) replay_buffer.add_episode(her_buffer) # 每步更新策略和Q网络 if replay_buffer.size() batch_size: for _ in range(updates_per_step): batch replay_buffer.sample(batch_size) td3_update(batch)有一个实现细节值得强调her_goal用的是next_obs里的observation部分而不是desired_goal字段。因为desired_goal在reset时就被固定死了如果直接取这个字段重标定的目标永远不会变化整个机制就失效了。我当时在这个细节上卡了一个下午从buffer里采出来的her_goal全部相同训练曲线直接变成水平线。4. 我在复现HER时踩过的坑和调参记录4.1 关键超参数的经验值参考HER对超参数的敏感度比普通RL算法低不少这是它的一个隐藏优点。即便如此我记录了几组让我印象深刻的参数设置都是基于FetchPush和FetchPickAndPlace环境验证过的参数我的经验推荐备注replay buffer大小1e6HER会额外生成一倍数据buffer太小容易覆盖旧经验采样周期k4future策略中的时间跨度上限k太大目标过于遥远HER数据比例1:1原始transition和HER transition各占一半写入buffer批量大小256比普通DDPG的128稍大因为数据里目标分布更广探索噪声Gaussianstd0.2比OU噪声更简单效果相当目标阈值0.05Fetch系列默认阈值换环境要重新测量网络层宽256x256三层MLP宽比深更有效每episode更新次数40对应1步环境交互40次梯度更新样本效率最高特别想提一下探索噪声这件事。DDPG时代很多人习惯用Ornstein-Uhlenbeck噪声因为它能在时间上产生相关性模拟真实物理系统里的惯性。但我在机械臂任务里实测OU噪声和独立的高斯噪声最终效果差异不大高斯噪声还少一个musigma调节参数代码更简洁。如果你的任务里机械臂有比较大的惯性滞后OU噪声也许有一点帮助但不要指望它解决探索的根本问题HER才是那个真正解决问题的机制。4.2 训练曲线锯齿状抖动我的一次完整排查过程我在这里把一次印象深刻的排查过程完整记录下来。当时我在FetchPush上用HERTD3训练前2000个episode成功率曲线一路上升到0.7左右然后开始剧烈抖动上下波动范围达到0.3再往后甚至回退到0.2。我第一反应是探索噪声设大了策略在后期还在做无意义的随机游走。我把高斯噪声的std从0.2降到0.1抖动幅度略有减小但依然存在。然后我检查了replay buffer的数据分布发现一个有意思的现象随着策略变好buffer里成功轨迹的比例在上升但HER生成的事后目标里有很大一部分来自早期那些策略很差的轨迹。这些旧轨迹的状态分布和当前策略的访问分布严重不一致导致价值函数的估计方差变大。解决办法其实很简单——降低buffer里HER数据的比例从1:1改成1:0.5并且清空过一次buffer。之后抖动明显缓解。这个案例也让我明白了一个原则HER不是buffer越大越好当策略进化得很快时旧轨迹的经验价值会迅速贬损需要控制它们在buffer里的占比。4.3 如何判断HER是否真正在起作用新手跑HER时最迷茫的是分不清训练没效果到底是算法问题还是实现问题。我总结了一个简单有效的判断方法单独监控两类数据的TD误差。修改TD3的代码在计算critic loss时按数据来源原始transition vs HER transition分别统计误差。如果HER数据的TD误差明显大于原始数据说明目标重标定带来的学习信号是有效的、网络确实从中学到了新东西。如果两者的误差都接近零且成功率不变说明策略已经收敛到一个局部最优或者探索不足。如果两类误差都在下降但成功率不涨说明奖励阈值或者状态表征出了问题。另外一个直观的观察是成功episode的平均长度。HER有效时成功轨迹的长度会逐渐变短因为策略在学习走更短的路径。我在FetchPush里观察到这个长度从最初的50步逐步收敛到20步左右这个变化比成功率曲线更早反映出策略的进步。5. HER的适用边界什么时候别用以及它的下一代思路5.1 我在实际中看到的HER失效场景HER不是万灵药我在不同任务上碰过几次壁总结出三类典型的失效场景第一类是目标空间和状态空间差异过大的任务。比如倒水任务目标是液体的体积或者倒入杯中的位置但算法能观测到的状态里液体的粒子位置分散且不稳定用粒子中心位置做重标定目标会导致目标本身有噪声策略学到的东西不干净。HER要求目标可以用状态本身来表示目标空间必须是可到达的状态子空间而不是任务的语义概念空间。第二类是任务需要严格的顺序执行。例如先抓取再放置这类多阶段任务中间状态虽然可以被重标定为目标但即使达到了中间目标后续动作依然需要依赖之前的历史。标准HER缺乏对目标之间因果关系的建模训练出来的策略经常是抓到物体但没有后续动作成功率卡在某个中间水平。第三类是目标太过稀疏以至于整个episode里状态几乎没有变化的情况。比如机械臂在一个空旷场景里移动没有物体目标是一个随机远点绝大多数episode里机械臂只是原地微动重标定出来的目标之间几乎重合提供的信息量趋近于零。HER的收益来自状态空间中多样化的覆盖如果随机策略本身无法带来状态多样性HER也没有用武之地。5.2 在HER基础上常见的改进方向顺着HER的机制往深处想有几个方向我觉得很值得关注。一个是CHERCurriculum HER它不随机选用事后目标而是根据智能体当前的能力挑选略高于当前水平的目标相当于给HER套了一层课程学习的壳让重标定目标始终处于最近发展区训练速度可以进一步加快。另一个是HIGSHuman Intuition Guided Goal Selection它在重标定目标时引入人类的直觉偏好优先选择那些在人类看来有教学意义的状态作为目标。还有一个思路是结合世界模型。HER本质上是在事后用真实状态做目标如果环境有一个准确的可学习世界模型就能在训练过程中做想象性重标定提前生成更多样化的逻辑链。这些方向我没有一一在真实机器人上验证过但至少说明HER的换个目标再看失败的思想已经渗透进很多后续工作的核心设计里了。回到最开始的场景。如果你也在做一个目标导向的机器人控制任务手里是一堆零奖励的失败轨迹我的建议是先别急着设计复杂的密集奖励函数试试HER。它也许不能保证所有任务都一次学会但它至少提供了一种不依赖领域知识就能提升样本效率的通用思路。先用仿真环境跑通一遍再逐步往真实机器人迁移这个流程我在多个项目中验证过稳定性是够的。