ARTICLE DETAIL

资讯详情

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

HER原理与实战:用事后目标重标注破解稀疏奖励问题

HER原理与实战:用事后目标重标注破解稀疏奖励问题 1. Hindsight是什么先说说这个项目标题Hindsight就是“事后回看”。很多人第一眼看到这个词会把它理解成“后悔”、“早知道当时如何如何”但在强化学习领域这个词代表着一个相当炸裂的想法当智能体没能达成目标时不要惩罚失败而是重新换个角度看待这段经历把它当作“成功完成另一个目标”的经验来学习。说白了就是让智能体学会一种能力哪怕这次没成功也能从“失败的经历”里挖出“成功的样本”。这个思路最初来自OpenAI在2017年发表的一篇论文《Hindsight Experience Replay》简称HER。论文的核心问题非常直接强化学习里最令人头疼的稀疏奖励问题——智能体在巨大的状态空间里漫无目的地探索绝大多数尝试都得不到任何奖励信号训练半天情绪稳定地在原地打转损失一路平躺你根本不知道是代码写错了还是环境太难了。HER提出后很多原本几乎训练不动的任务立刻“活了”。比如机械臂抓取物体、推箱子、门把手转动这类多步操作甚至像“拿某个螺丝刀拧某个方向的一颗螺丝”这种长程任务HER都成了标配方案。几乎所有后续做机器人操作、爬行动仿真、具身智能的团队都绕不开这个技术。这篇文章我想从头到尾把一个HER项目拆开讲透技术原理是什么、为什么能work、具体怎么落地实现、训练中会遇到哪些坑以及最后一点私货——hindsight这种“事后重定义目标”的思维模式对我们日常做技术方案选型、调bug、写代码到底有什么启发。适合谁读如果你是做强化学习研究的或者在做机器人控制、游戏AI、推荐系统这类涉及序列决策的项目这篇文章可以直接当作HER的工程落地手册。如果你是刚入门RL的初学者只要了解基础的DQN、策略梯度、经验回放概念也能读懂全文我会把每个概念都用大白话拆开。先打一个比方一个小孩学投篮每次都投不进教练说“你就站在刚才抛球的位置把篮筐朝右挪50公分投进去就算赢”。HER干的事情就是把篮筐的位置重新放到球最终落地的位置然后告诉这个小孩“干得漂亮你刚才准确地把球投到了一个新篮筐里。”虽然原来的目标失败了但小孩积累的却是大量“如何把球送到某个位置”的真实手感。几次下来他在任何篮筐位置都能投得进去。这个思路让我当时看完论文拍了大腿怎么这么简单的东西之前没人想到。2. 核心思想拆解为什么“事后重定义目标”这么有效2.1 稀疏奖励问题的死结在哪要理解HER的价值先得搞清楚它要解决的问题有多痛。在稀疏奖励环境里reward往往是个极度稀疏的信号——只有到达目标状态才给一个1或10的奖励其他任何状态都是0。比如机械臂抓取任务只有当夹爪触碰到目标物体才会返回奖励。可机械臂有6到7个自由度动作空间是连续的哪怕策略网络输出一点点偏差夹爪就擦着物体边缘过去了永远碰不到。这意味着什么经验回放缓冲区里的样本绝大多数都是reward全为0的“无效样本”策略更新时梯度信号几乎为零。智能体得到的反馈是不管我怎么动好像都一样地一无所获。那它就没有动力去调整策略。这是死结一。死结二更隐蔽即使智能体碰巧接近了目标但离成功还差一步比如手指已经碰到物体了只是没有抓紧然后物体滑落整个episode结束返回reward0。这段轨迹从数学上讲是一段“高度接近成功”的宝贵经验但按照标准RL训练它和一段毫无意义乱撞的轨迹在loss层面没有任何区别同样被当成纯失败数据丢掉。浪费极其浪费。这就是HER要解决的核心矛盾目标只有一个但要学会从所有“中途状态”中提炼成功的经验。2.2 HER的做法重新标注目标HER的想法非常朴素——这个轨迹虽然没完成目标g但它确实从s0走到了sT也就是完成了一个“新目标”g。那好我直接说这段轨迹是在完成g时产生的成功轨迹把它塞进经验池作为“如何到达g状态”的正样本参与训练。具体操作是每一次episode结束后除了保留原始目标下的经验序列state, action, reward, next_state, goal之外额外再生成K份“回看目标”的经验数据。回看目标的挑选方式有好几种常见的是直接取这个episode最终到达的状态作为新目标。因为对于样本轨迹的任何一步t只要把最终状态当作目标那“agent在状态s_t执行动作a_t后到达s_{t1}”这件事从“向着最终状态前进”这个视角看就是在一步步逼近目标这段轨迹的每一步都是合理且有意义的。Reward的定义也会重新计算。假设目标是一维/多维向量一般用距离函数判断“是否到达目标”比如欧氏距离小于某个阈值就奖励1否则0。在重标注后的目标下以前几十步里可能一步都拿不到奖励现在后半段轨迹里往往能拿到大量奖励信号。2.3 数学视角HER到底改变了什么从数学角度说标准经验回放是从一个固定分布中采样(s,a,r,s,g)来更新Q函数或策略。但稀疏奖励环境下r分布高度偏向0信息熵极低。HER相当于人为改变了采样分布把原本“失败轨迹上全是0”的分布映射成“混合了成功信号”的新分布。用原始目标的轨迹是真实物理因果的体现用重标注目标的轨迹是逻辑自洽的“虚拟成功”。两者混合起来经验池里就有了大量“伪成功”样本这些样本让Q函数的梯度不再处处为零而是能持续给出“往哪个方向调整策略能更接近某个状态”的反馈。我记得原论文里有个很形象的说法HER其实是在变相做课程学习curriculum learning。一开始智能体被教授的都是“简单任务”——比如随机推一个滑块推到一个随机位置就算成功随着这些“简单任务”的经验积累Q函数对“任何状态下朝某个方向推能接近目标状态”有了越来越准确的估计当它真正去执行原始目标时就能复用那些估计少走大量弯路。2.4 与奖励塑形、课程学习的对比有人可能会问那我直接用奖励塑形reward shaping不就行了比如越接近目标给一个越大的密奖励。实际做过的朋友都知道奖励塑形最大的问题是要手调一堆权值怎么定义“接近”就是一个火葬场。做机械臂抓取时用MSE距离算奖励物体姿态稍微复杂点尺度稍失衡Q值就可能爆炸。而课程学习需要人为设计任务难度梯度同样是很大的工程成本。HER的优势在于几乎不需要任何任务先验知识不需要了解目标的具体物理语义只要知道“目标是什么形式”是一维向量、二维坐标还是姿态矩阵就能自动产生课程。说实话我第一次看完论文就感慨这个思路干净得不像一个RL trick。3. 实操落地从零实现一个HER项目3.1 环境选型与前期准备我实际跑HER项目时仿真环境用的是MuJoCo OpenAI Gym接口。建议初学者先用FetchReach这类最简单的任务环境练手一个7自由度机械臂需要把末端执行器移动到指定三维坐标点。别一上来就上FetchPickAndPlace或者Hand Manipulation Suite那些任务同时涉及抓取、多物体交互、稀疏奖励坑非常深调试起来几天都看不见一次正奖励。如果你只是想快速理解HER的运行机制甚至可以先做一个玩具环境在一维直线上智能体从一个随机起点出发通过连续动作走到目标位置。状态空间是一维坐标动作是位移增量目标随机生成。这种环境下十几分钟训练就能看到明显效果配一把MATLAB式的debug视角适合打断点观察经验池结构。工具链上我用的是Python 3.8 TensorFlow 1.14当时后来也试过PyTorch 1.8。说句公道话HER本身不挑框架核心逻辑只在经验重放采样那里。网络结构也简单一个Q网络、一个目标Q网络加上一个确定性策略网络用DDPG基座就能撑起来。3.2 算法主循环与关键代码HER的实现核心不在网络而在“经验怎么存”和“经验怎么取”。这里我给出一个经过简化的训练主循环def train_her(env, agent, buffer, k4, episodes5000): for episode in range(episodes): obs env.reset() ep_obs, ep_actions, ep_rewards, ep_next_obs [], [], [], [] goal obs[desired_goal] # 原始目标 for t in range(env.max_steps): action agent.policy(obs) # 加噪声探索 next_obs, reward, done, info env.step(action) # 记录原始数据 ep_obs.append(obs[observation]) ep_actions.append(action) ep_rewards.append(reward.copy()) ep_next_obs.append(next_obs[observation]) obs next_obs if done: break # 关键HER重标注 for t in range(len(ep_obs)): reward compute_reward(ep_next_obs[t], goal) # 原始目标 buffer.store((ep_obs[t], ep_actions[t], reward, ep_next_obs[t], goal)) # 额外生成K个回看目标 for _ in range(k): future_goal ep_obs[np.random.randint(t, len(ep_obs))] # 从未来状态选目标 new_reward compute_reward(ep_next_obs[t], future_goal) buffer.store((ep_obs[t], ep_actions[t], new_reward, ep_next_obs[t], future_goal)) # 正常经验回放更新 for _ in range(100): batch buffer.sample(256) agent.update(batch)这行future_goal ep_obs[np.random.randint(t, len(ep_obs))]就是HER的灵魂。它从t时刻之后的未来状态中随机挑一个作为新目标因为当前时刻t之后确实到达了那个状态所以这段(s_t, a_t, s_{t1})天然就是“接近目标future_goal”的正确动作。我通常把K设为4或8。K1也能训练成功但收敛明显变慢K8收敛最快但每步更新的计算量也就上去了。在FetchReach里K4基本是效率最优的甜点位。3.3 目标选择的四种策略原论文详细对比了四种挑选“回看目标”的方式这四种我在项目里都实测过策略名称做法实验结果final取整条轨迹的最终状态当目标收敛较慢但稳定future在t时刻之后随机选一个状态当目标效果最好收敛最快episode在当前整条episode里随机选任意状态当目标效果接近future略差random在经验池里随机选任意状态当目标效果最差从直觉上讲future策略之所以最强是因为它保证了重标注的目标是“从当前时刻出发未来的确能到达的状态”逻辑自洽性最强。final策略虽然简单但轨迹长度较长时早在t0就把最终状态当目标中间几十步的规划信号依然很稀疏。我一直习惯用future策略K4。原论文的网格搜索也验证了这个组合几乎在全部环境都是最优的。3.4 网络更新细节与超参坑DDPG本身有两个棘手问题Q值过高估计和策略更新对学习率敏感。HER把这些老问题原封不动继承过来了。Q网络我用两层256的MLPReLU激活L2正则。DDPG的训练通常需要给动作加入探索噪声我实测OU噪声在HER里并不比高斯噪声强多少反而高斯噪声会更稳定。绝对值上动作噪声的方差要逐渐衰减前期大一点让智能体充分探索后期小一点让策略收敛。有个指标要盯经验池中“伪成功样本”的比例。如果比例过高Q函数会对“成功”过于乐观因为伪成功样本只代表了“能达到目标状态”的乐观情况却没有“不能达到目标状态”的负面样本如果比例过低又退化成普通DDPG。在我跑的环境里伪成功样本占总样本30%-50%时训练最稳定。调整方法就是改K值或者限制只从轨迹的后半段选目标。4. 常见问题与调试心得实录4.1 训练长时间不收敛先查这四件事目标距离阈值定得不合理。这是新手最容易踩的坑。比如FetchReach里官方的成功判定是欧氏距离小于0.05米。如果你用的距离函数阈值太大比如0.2米智能体还没真正接近目标就被标记为“成功”策略会懒散地停在半路。阈值太小又会让奖励信号比想象中还要稀疏。我的建议是用环境官方阈值没有的话先画一张“末态距离目标距离”的分布直方图观察探索几个episode后能达到的最小距离范围再定阈值。目标表征不一致。有些任务里目标向量和观测向量维度含义千差万别比如观测是关节角末端坐标目标是三维坐标那计算距离时只能在“目标相关维度”上算。我见过有人直接拿全部状态维度和目标向量做MSE结果哪怕末端执行器已经精准到位其余维度上的随机抖动也把距离拉得很大HER学到的东西全被噪声淹没。经验池Buffer容量太大。Buffer太大早期那些杂乱无章的探索经验迟迟不被清出晚期训练时采到的早中期无效样本太多训练步伐像是陷入泥潭。参考做法把Buffer容量设为单epoch全部经验量的2到3倍即可不要无脑设1e6。目标Q网络同步周期太慢。DDPG里目标Q网络是慢慢跟上主网络的通常用tau0.05做软更新效果可以。但如果同步太慢Q值预估滞后严重HER重标注出来的“伪成功”会更失真会出现训练曲线震荡剧烈甚至回退的情况。4.2 重标注后的奖励函数到底怎么算才不炸我在做物体抓取任务时踩过一个很典型的坑原始观测是相对坐标目标也是相对坐标我直接用了绝对位置差异量纲完全不同训练一开始甚至出现了loss为NaN。后来规范成了统一做法所有目标一律转成绝对笛卡尔坐标在计算距离前对每个维度做标准化。标准化参数从经验池里统计得到——即每个维度的均值和标准差在训练过程中动态更新。计算成功与否的阈值我建议看原始环境代码里achieved_goal和desired_goal的距离判定方式。对FetchReach这类环境简单MSE就行但FetchPickAndPlace这种涉及旋转的任务不能用简单的坐标MSE要给位置和旋转分别算距离再加权。4.3 稀疏奖励环境下成功率的评估要“宽容”HER训练过程中成功率曲线不是单调上升的。它经常是先零然后偶尔冒几个刺再掉回零接着突然拉升。如果用“最近100个episode的平均成功率”做指标前期会一直接近0看不出训练是否有进展很容易让人误删代码。我习惯额外看一个指标平均距离进度。即每个episode结束时的末态距目标距离与初始距目标距离的比值。这个值即使成功率为0也会随着训练慢慢下降能更平滑地反映Agent是否有在接近目标。刚开始比值可能是0.8训练几万步后变成0.4再往后掉到0.1成功率才开始往上冲。下图是成功率曲线的大致形态手上项目数据不好外发只说趋势前2万步成功率几乎为02万到4万步之间开始跳变到30%左右然后阶梯式爬升到90%以上。典型的“长尾爆发式收敛”——如果你用普通DDPG训练同样的环境可能50万步成功率还是0。4.4 一个容易忽视的朴素细节HER重标注目标从未来状态里采样这意味着一条轨迹里靠后的状态会在重标注时被反复当作目标。如果环境目标的物理量纲跨度很大比如坐标可以从-10变化到10但其中一个维度比较固定这个不均匀分布会让经验池目标域偏置。解决办法很土但有效把目标维度按最大值全局归一化到[0,1]区间。这在数学上等价于只是缩放目标不会改变相对距离判定但对Q网络的收敛稳定性提升非常明显尤其当目标向量多维度、量纲不统一的时候。5. 更进一步HER的变体与边界5.1 与优先经验回放的结合标准HER用的是均匀随机采样但训练后期经验池里样本质量差异很大。近年有不少工作尝试把HER和PER优先经验回放结合比如根据TD误差对重标注样本和原始样本分别加权。我自己试下来结论是前期别加PER因为前期所有样本TD误差都很大优先级区分度不高反而破坏了HER精心构造的课程感。到了训练后期成功率超过50%时再加PER可以明显加速最后10%的收敛进度。这个开关时机大概在“成功率曲线出现明显拐点”的位置。5.2 与多目标学习的联系HER最本质的贡献在于它把一个单目标任务变成了一个隐式的多目标学习问题——每次采样都同时教给网络“如何从不同状态到达不同目标”。这个思路和多目标强化学习、通用值函数逼近器UVFA是相通的。后来很多后续方法比如把目标向量和状态向量拼在一起构建统一Q网络或者用成对的状态对比学习来替代距离函数其实都建立在这个“重定义目标”的哲学之上。你在理解HER之后去看那些变体会发现内核几乎没变。5.3 局限在哪里要泼冷水的话HER并非万能。如果任务的目标空间和状态空间差异极大——比如目标是“把桌上的苹果放进盘子里”但状态空间是关节角和像素图——从任意未来状态里挑目标未必能构成有意义的课程。因为从像素图里随机挑一张对应的“目标”可能根本不可达或无法理解。另外HER对“目标必须可描述、可度量”是有依赖的。如果任务是开放式的比如“探索地图里所有未访问区域”目标本身难以形式化为固定向量HER就无法直接上手。所以如果要总结HER的适用边界适合目标可以用低维向量表征、且未来状态本身具有目标语义的任务。位姿控制、物体抓取、导航寻路这些都是HER的主场。6. 写在最后的实战体会我不太喜欢把它包装成一个玄乎的“方法论”但做了几年RL回头看HER给我留下最深的印象反而是别只盯着眼前定义好的那个目标多去想想“现在走到的地方能算作哪些别的事情的成功”。落到具体技术项目上就是别把失败样本当垃圾丢掉。所有做强化学习的人前几个月几乎都会陷入同一个误区——只奖励成功惩罚失败于是智能体什么也学不会。HER教我的恰恰相反失败样本里往往藏着大量“局部成功”的信息关键是你有没有一套机制把它们翻译成有效的学习信号。这跟调试代码时看日志的思维是一样的不要把报错当作失败而是当作一次机会搞明白现在的状态离正确状态之间差多少维度哪些动作是有效的只是目标定错了而已。实际跑项目时我每次为HER调参都会想起这个逻辑链任务失败不是因为动作完全无效而是因为“成功阈值”可能设得太苛刻中途的每一个状态都是未来若干个目标点之一真正难的不是让智能体达到某个特定目标而是学会“从任何状态出发朝任何目标靠近”的通用能力。当训练收敛后成功率冲到95%以上的那个瞬间你会觉得之前所有调试到深夜的辛苦都值了。最后再分享一个小技巧跑HER实验时记得定期把经验池里的重标注样本可视化出来看看那些“伪成功”的轨迹前后状态是否自洽。很多时候你的算法看起来不收敛根本原因只是重标注的目标全被选在轨迹前段的乱撞状态上导致经验池乱成了一锅粥。HER不是银弹但它教给你重新理解“目标”和“失败”之间的关系。即便你最终不在项目里用它这种视角对整个RL竞赛、自动调参、甚至日常工程复盘都很有帮助。
返回列表