尧图精选

HER算法深度解析:用目标重标注破解稀疏奖励难题

🕒 发布时间:2026/10/1 23:10:17 📁 来源:尧图网络
1. Hindsight到底是什么一个能“事后补救”的强化学习算法Hindsight Experience Replay简称HER国内一般直译成“事后经验回放”。我第一次看到这个名词是在OpenAI那篇关于机器人抓取和推球的论文里当时第一反应是这名字起得挺妙因为它确实讲了一件事——让智能体学会从“失败”里翻盘把没做成的目标重新包装成“已经完成”的经验。先解释一下它解决的痛点。做强化学习的人应该都有过这种体验你设计了一个任务比如机械臂把桌面上的小球推到指定位置奖励函数写得特别稀疏——推到了给100分没推到给0分。然后你开训几百万步下去智能体还在原地转圈因为它从头到尾几乎没有拿到过正向奖励梯度信号稀薄得跟没有一样。这种问题业界叫“稀疏奖励问题”Sparse Reward Problem也是很多机器人学习、导航、游戏AI项目从demo走向落地时翻车最狠的地方。HER的思路非常朴素既然智能体没推到目标位置A但它实际上把球推到了位置B那不如我们把这次轨迹重新标记成一个“从当前状态出发、目标是B”的成功样本。也就是说一次“失败”的执行只要换个角度看它就是一次“成功”的示范。这就是“事后”两个字的含义——不是预测未来而是回头重新解释已经发生的轨迹。这个思想让我想起学骑自行车。你第一次骑车没骑到目的地歪歪扭扭摔在路边但从“保持平衡”这个分解目标来看你可能已经成功了一段路。如果只盯着最终目的地你这一跤是纯失败但如果把“别摔倒”当作每一步的子目标你其实一直在积累有效经验。HER干的正是这件事它把宏大而稀疏的最终目标拆解成一个个在执行过程中“顺路实现”的子目标并让智能体从这些子目标里学到真正的因果规律。这篇文章主要面向正在做强化学习项目、尤其是机器人控制或密集交互式任务的朋友。如果你是刚入门手头有个环境却训不起来或者你已经在用PPO、DQN这类算法但在稀疏奖励环境下迟迟不见涨分那这篇文章的实操细节对你应该很有帮助。我会把HER的原理拆开、把重标注的四种策略挨个讲透再给出一套可以在机器人控制任务上直接跑的配置最后聊几个我实际踩过的坑。2. 核心机制拆解目标重标注是HER的灵魂但细节比想象中多2.1 一个具体的例子机械臂推球任务里的重标注为了把HER讲明白我们拿一个最经典的环境举例机械臂推球FetchPush。任务描述很简单机械臂需要把一个放在桌面上的小球推到某一个指定位置这个位置每次episode开始时会随机生成。标准的做法是为这个任务设定一个二元奖励如果机械臂末端与目标位置的距离小于某个阈值比如5厘米奖励为0否则奖励为-1。注意这里我用的是“奖励为0”而不是“给正向奖励”目的就是让智能体在每一步都感受到“还没成功”的压力这种密集化处理虽然不至于完全没信号但本质上仍然是一个接近稀疏奖励的任务——因为大部分step里它都在原地挣扎。在HER里每跑完一个episode我们手里会有一整段轨迹记为s_0, a_0, r_0, s_1, a_1, r_1, ..., s_T。这条轨迹原本的目标是g最终状态是s_T。如果s_T没有达到g的邻域这条轨迹在传统经验回放里就是一个纯粹的负面样本价值很低。HER的做法是把这条轨迹的“目标”从g换成一个新目标g然后重新计算轨迹中每一步的奖励。g的选取最常用的就是轨迹的最终状态s_T中对应的目标维度比如球的位置坐标。因为s_T恰恰就是球最终停下的位置那么从“目标是s_T”这个角度来看这条轨迹的最后一个状态就是一个成功状态最后一步的奖励就等于0而前面每一步的奖励也都根据“是否更接近s_T”来重新赋值。这样就得到了一条全新的、带有正负奖励结构的经验。注意我们没有修改智能体的任何行为也没有改变环境动力学我们只是换了一个“提问的方式”不问“你有没有到达g”而是问“你有没有到达g”以及“在这个过程中你是如何一步步接近的”一条原本毫无亮点的失败轨迹经过这种重标注就能给智能体提供“原来用这样的动作序列可以把球推到某个位置”的有效信号。2.2 四种目标取样策略final、random、future、episodeHER论文里对“如何选取g”做了系统性的实验总结出四种策略我用最直白的话转述一下它们的差异因为这直接决定你训练时经验池里样本的质量分布。第一种final策略。直接把轨迹最后一个状态的目标维度提取出来当作g。这是最简单、最常用、也是我推荐大多数人先用的策略因为它的计算量几乎为零而且提供的是这条轨迹里“最有信息量”的一个真实可达目标——毕竟它确实到达过那个位置。第二种random策略。从整条轨迹里随机抽一个状态把该状态对应的目标维度当作g。这个策略的好处是能覆盖到中途的“接近但不完全到达”的情况缺点是抽取完全随机可能抽到一些毫无参考价值的中间态比如球还在起点附近信息增益就小很多。第三种future策略。在当前时刻k之后随机选一个状态作为目标。这个策略有一个潜在优势它对应的目标是在“未来”才实现的因此轨迹中前段的状态距离这个未来目标恰好形成了一条递进的逼近路径学习效率往往更高。论文实验里future策略通常表现优于random但计算上要稍微多花一点功夫。第四种episode策略。从整个episode中随机抽取一个状态无论时间先后。这个方案我实际用得少因为它的随机性太强而且在某些任务里会把原本有意义的轨迹切割得支离破碎。用表格总结一下适用场景策略说明典型场景我的建议final用轨迹最终状态做目标推球、抓取、导航先跑通流程首选用它future用未来某个状态做目标长程操作、多阶段任务效果上限更高但参数稍多random从整条轨迹里随机抽探索性强的任务备选方案绝大多数情况下不如finalepisode从episode里任意抽没有明显阶段性目标的任务很少用容易引入噪声2.3 为什么HER必须搭配Off-Policy算法以及这个坑怎么绕这一点经常被忽略但恰恰决定了你实现的成败。HER改的是经验回放里的样本目标意味着你用重标注后的数据去更新策略但这些数据并不是在当前策略下采集的这本身就是一种Off-Policy的行为。也因此HER和DDPG、TD3、SAC这类Off-Policy算法是天作之合它们天然允许你从旧策略的经验里反复学习。反过来如果你试图把HER套在PPO这类On-Policy算法上问题就来了PPO要求每轮更新必须使用当前策略采样的数据旧数据用多了会带来严重的策略偏移最终结果就是训练发散。我见过有人把HER强行接在PPO上跑了二十万步reward曲线像心电图一样乱跳最后不得已放弃了整个方案。如果你必须使用On-Policy算法也不是完全没招可以尝试一个近似方案每隔几个epoch做一次“经验修正”给重标注后的样本乘以一个重要性权重修正系数。但说实话这样做的工程复杂度远大于优点我个人的建议是直接切换到SAC或TD3省心得多。3. 实操过程从环境搭建到核心代码实现3.1 环境与奖励设计用什么任务验证HER最合适如果你还没有合适的实验环境我强烈建议从OpenAI Gym的Robotics系列开始尤其是FetchReach和FetchPush这两个。它们自带完整的MuJoCo物理仿真并且官方定义里已经包含了稀疏奖励的变体很多用HER的实现也都是在这些环境上做的验证。选环境时有个重要的判断标准这个任务的奖励信号是否足够稀疏但目标是否清晰可辨。如果任务本身密集奖励已经很好学了比如每一步都给距离惩罚那HER的帮助不大。反过来如果目标本身都无法准确定义比如“让机械臂做出一个优美姿势”HER也无从下手因为你没法重标注一个模糊的目标。HER适用的是“目标可以用状态空间里的一组维度表示”的任务这个条件决定了你后面能不能顺利实现。以FetchPush为例目标就是一个三维坐标值球的当前状态也是一个三维坐标值两者可以用欧氏距离直接度量。这种目标结构化程度高的环境是HER的最佳练习场。如果你在自定义环境里做也需要先保证你设计的目标是可以被“事后重新赋值”的。3.2 网络结构与超参数设置的实用建议有了环境下一步就是定网络结构和超参数。这里给出我实际用过并且稳定收敛的一套配置你在自己的项目里可以以此为起点微调主网络三层全连接隐藏层维度设为256激活函数用ReLU。Actor输出层tanh激活因为机械臂的动作空间通常被归一化到[-1, 1]。Critic与Actor结构类似输入拼接状态、动作和目标输出Q值。优化器Adam学习率统一设为1e-3。折扣因子γ0.98。这个值我特意调低了一点因为稀疏奖励场景下长期回报的方差很大过大的γ会让价值估计非常不稳定。目标网络软更新系数τ0.05。这个值比常见默认值0.005要大理由同样是稀疏奖励条件下价值函数震荡幅度大稍大一点的软更新能让学习跟上变化。时间段长度每个episode最多50步。经验池容量1e6。HER重标注比例每采集一条轨迹额外生成4条重标注后的经验存入缓冲区其中future策略和final策略各占一半。这个比例是OpenAI原论文里的经验值实测效果也很稳。3.3 核心代码流程HER的伪代码级实现解析下面是实现HER训练流程的核心骨架我用的是伪代码加关键Python片段结合的方式来说明方便你直接映射到你自己的项目框架里。每完成一个episode你首先需要把原始轨迹存下来def collect_episode(env, policy, max_steps50): obs env.reset() episode_buffer [] for _ in range(max_steps): action policy.select_action(obs) next_obs, reward, done, info env.step(action) episode_buffer.append((obs, action, reward, next_obs, done, info)) obs next_obs if done: break return episode_buffer注意这里存的是info因为FetchPush这类环境里info中会有desired_goal和achieved_goal字段这两个字段就是我们做重标注的关键依据。接着是重标注逻辑我给出一个简化版但功能完整的实现def relabel_episode(episode, buffer, her_strategyfuture): # 先按原样存原始经验 for trans in episode: buffer.store(trans) # 生成额外HER样本 episode_len len(episode) for t in range(episode_len): obs, action, _, next_obs, done, info episode[t] if her_strategy final: new_goal episode[-1][5][achieved_goal] elif her_strategy future: future_t np.random.randint(t, episode_len) new_goal episode[future_t][5][achieved_goal] elif her_strategy random: random_t np.random.randint(0, episode_len) new_goal episode[random_t][5][achieved_goal] # 计算新目标下的奖励 new_reward compute_reward(new_goal, info[achieved_goal]) new_done check_success(new_goal, info[achieved_goal]) # 重新构造transition存入经验池 relabeled_trans (obs, action, new_reward, next_obs, new_done, new_goal) buffer.store(relabeled_trans)这段代码里有几个细节值得敲黑板第一new_done不能用原有的done。因为目标被换了原本的终止条件很可能不再成立你需要根据“是否到达新目标”重新判断。我见过有人图省事直接沿用原始done结果训练时多出了大量虚假的episode终止信号价值函数被污染得一塌糊涂。第二next_obs也要同步修改。有些实现为了图省事只改了目标没改下一状态的goal维度这会导致状态和目标对不上训练时模型学到的是错误关联。一定要把next_obs里和goal相关的分量替换成new_goal。第三原始经验也要存。HER不是要把原始失败样本丢掉而是在保留原始样本的基础上增加重标注样本两者缺一不可。原始样本保留了“目标未达成”的信息重标注样本提供了“某个目标可达成”的路径这种混合经验池是HER能够稳定训练的基础。3.4 完整的训练循环怎么搭有了经验采集和重标注模块整个训练循环就清晰了。为了帮助你把全流程串起来我把它拆成四步第一步初始化策略网络、Critic网络、目标网络和HER经验池。第二步循环采集episode每次采集完立刻做重标注把原始样本和重标注样本都存入经验池。第三步从经验池中随机采样一个batch更新Critic和Actor。注意采样时要保证batch里既有原始经验又有HER经验比例建议控制在1:1左右这样价值函数既不会太保守也不会因为全是“虚拟成功”而忘记真实目标的存在。第四步定期软更新目标网络参数然后回到第二步。这个过程看着简单真正跑起来你会立刻感受到一个明显的差异没有HER时训练曲线在几百万步内可能一直贴着最低奖励徘徊加了HER之后曲线往往会在几十万步内开始爬升。我最早在FetchPush上跑的时候没加HER跑了两百万步成功率一直在2%以下打转加上HER之后大约八十万步成功率就超过了83%那种从绝望到惊喜的转变是理解这个算法价值的直接体验。3.5 网络训练时的batch构造细节训练时batch怎么构造是影响最终收敛速度的另一个隐藏因素。很多早期实现直接batch里混着原始样本和HER样本但这样有一个问题原始样本里的goal是外部给定的目标HER样本里的goal是重标注出来的两者的分布天然不同。如果混在一个batch里不加区分Critic偶尔会感到困惑。我的做法是把batch拆成两部分一半从“原始经验”子池里采样一半从“HER经验”子池里采样分别过网络后合并loss。这样每条经验在更新的时候都能保持目标维度的一致性实测下来效果比混合采样更平滑。当然这里说的平滑指的是loss曲线的震荡幅度不是指最终的收敛值两者对比下来分开采样的收敛成功率普遍高3%到5%。4. 常见问题与排查技巧实录4.1 训练不收敛的排查顺序我踩过的那些大坑第一个经常出现的问题是加了HER但训练还是不动。这时候不要急着怀疑算法实现先检查经验池里重标注样本的奖励是否真的被重新计算了。最常见的一个低级错误是重标注后奖励依然是原始奖励等于你绕了一圈存的还是老东西。我刚实现HER时犯过这个错排查了半天才发现compute_reward函数里读的goal还是原始外部goal导致所有HER样本的奖励全是-1整个经验池里根本没有正向信号。第二个常见问题是目标维度匹配错位。FetchPush环境的achieved_goal通常只有球的位置三维坐标而desired_goal也是三维坐标看起来是对应的但有些自定义环境里目标的维度可能包含物体的朝向或者机械臂末端姿态如果不仔细看重标注时用错了字段训练出来的策略会疯狂钻牛角尖。第三个问题是episode采集太短。如果任务动辄需要几百步才能完成但你的episode上限设成了50步那么智能体永远无法到达最终状态final策略提取出来的achieved_goal也只是一个中途位置意义大打折扣。建议先通过一个简单试探策略跑一遍统计成功时平均需要的步数再把这个值的两倍设为episode长度上限。第四个问题更隐蔽HER经验的比例过高。如果你把每一条轨迹都生成10条重标注样本经验池里90%的样本都是“目标可达成”的虚拟成功样本Critic会被误导认为所有动作都很容易成功策略探索欲望骤降。我建议重标注比例控制在每条轨迹额外生成4到8条之间原始样本与HER样本的混合比例在batch里稳定在1:1左右。4.2 什么时候不建议用HER边界场景要拎清HER不是万能的我至少遇到两类场景它效果很差。第一类目标本身不可重标注的任务。比如对话生成任务里目标是让对话“自然”这种目标是语义级的没法在状态向量里直接找到一个分量对应它那HER就没法用。同样如果目标是一段文本、一张图并且没有显式的结构化表达你很难在事后“换一个目标重新计算奖励”。第二类动态环境里HER的效果会大打折扣。比如环境里有另一个移动物体干扰或者风场变化无常这时候从轨迹最终状态提取的目标未必是策略可以稳定复现的重标注出来的“成功路径”很可能是恰好走运而不是真的学出了规律。印象最深的一次是做一个动态障碍下的导航任务HER训练出来的策略在固定障碍下表现很好换成随机移动障碍后成功率暴跌到原来的一半以下这就是典型的环境动态性导致重标注样本失真。所以如果你碰到这类任务我的建议是不要迷信HER可以考虑改用基于采样的规划方法或者用World Model去做预测控制那些方法对动态环境的鲁棒性更好。4.3 关于“稀疏奖励”和HER互补使用的实操心得最后分享一个我自己的独特用法。HER可以跟其他稀疏奖励增强手段叠加效果往往比单用更好。比如我在一个机械臂装配任务里先把奖励设计成“分阶段稀疏”——接近工件给-0.1插入完成给10装配成功给50——然后在这个分段奖励的基础上跑HER最终的收敛速度比纯HER快了一倍多。这里有个关键点分段奖励的设计不能和HER的重标注目标产生冲突。如果你把“接近工件”也当作一个可重标注的目标可能会导致经验池里大量“目标直接设置为当前位置”的样本削弱学习效率。所以我在设计分段奖励时往往只对“最终装配成功”这一个目标做HER重标注而把中间过程的奖励当成固定的先验知识保留下来。这个坑我踩过一次之后总结出了一条规则HER重标注的目标尽量少而精不要贪多。再补充一点关于Future策略的经验之谈。Future策略虽然理论效果好但它的效果高度依赖future_t的采样窗口长度。窗口太短目标离当前状态太近信息量低窗口太长目标过于遥远几乎和final没区别。我实测下来在50步的episode里future_t从当前时刻的下5步内开始采样效果最好。你可以把这个当成一个初始参考值在自己的任务里再做一次小范围搜索。5. 写在最后的扩展思考我不太喜欢做那种“展望未来”式的总结但有几个在设计HER变体时想到的思路对我后来的项目帮助很大值得拿出来说。第一个想法是把HER和课程学习Curriculum Learning结合起来。HER本质上提供了一串从易到难的目标序列因为越靠前的achieved_goal越容易被达成天然形成了一条难度递增的课程。很多人没有意识到这一点只是机械式地重标注其实可以在此基础上按难度把经验池分区训练初期多采样低难度目标后期逐渐提高高难度目标的比例。我在一个四阶段机械臂任务里试过这个方案比固定比例采样快了约30%达到相同成功率。第二个想法是给HER加一条“人类示范”的约束。HER擅长从失败中学但纯粹的自学还是可能学到效率很低的行为轨迹。如果能在经验池里注入一些人类示范数据让HER的重标注目标优先从这些示范轨迹的末状态中选取可以显著提升样本效率。这个方案我在实际项目里用过一次训练初期的成功率直接从15%跳到了40%效果立竿见影。对我来说HER教会我的最重要一课是失败数据的价值取决于你怎么给它们编故事。很多强化学习项目卡壳不是因为算法不够强而是因为我们用了一种过于苛刻的方式评价经验把大量可能有效的探索判了死刑。HER通过重标注这种优雅的手段让智能体自己从失败里提取出成功信号这是它远比一个普通trick更值得深入研究的原因。如果你正准备在自己项目里用HER我的建议是先别急着上复杂变体把基础版本跑通确认奖励重标定的每一步都没有问题再开始调整采样策略和网络结构。基础版本的成功率一般已经能给你惊喜后续的优化更多是锦上添花。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →