ARTICLE DETAIL

资讯详情

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

HER事后经验回放:从稀疏奖励困境到目标重标注的强化学习实践

HER事后经验回放:从稀疏奖励困境到目标重标注的强化学习实践 1. 从“后见之明”说起HER到底想解决什么问题1.1 强化学习里那个折磨人的稀疏奖励接触强化学习的人多半都经历过一个让人抓狂的阶段智能体在环境里乱撞了很久reward却一直是零训练曲线像一条死人的心电图。尤其是做机器人控制、导航规划这类任务时目标状态很难刚好被随机策略撞到算法就会陷入“什么都学不到”的死循环。这就是稀疏奖励问题。传统做法里最直接的思路是人为设计稠密奖励让智能体每一步都能获得一点反馈。但奖励塑形本身是门手艺活设计得不好容易引入局部最优甚至让智能体学会“钻空子”——比如为了让奖励函数更平滑而设计的势函数反而引导智能体绕远路。另一条路是课程学习、分层强化学习但这些方案要么需要额外的人为干预要么任务适应性差工程落地时非常费劲。我第一次认真关注 hindsight 这个词是在看一篇讲多目标强化学习的论文时。它对应的算法叫 Hindsight Experience Replay简称 HER中文可以叫“事后经验回放”。这个名字非常形象人类擅长把失败的结局理解为“原本可以怎么做得更好”的教训而 HER 正是用这种后见之明来改造强化学习的训练过程。它不依赖额外奖励设计也不需要课程学习却能显著缓解稀疏奖励带来的学习困难。它把每个失败的轨迹都变成一条可能成功的轨迹让数据利用率大幅提升。1.2 为什么过去几年 HER 能被频繁提及HER 能火起来不只是因为理论漂亮更重要的是它贴合真实场景。很多实际任务天然是多目标的比如机械臂抓取目标可以是不同位置的物体机器人导航目标可以是不同的楼层坐标。传统 RL 处理这类问题要么每个目标单独训练一个策略要么把目标拼进状态空间里让网络自己学。HER 恰好天然兼容多目标设定——它把“目标”当作一个显式输入训练过程中又利用目标重标注来制造额外学习信号这让它既实用又优雅。和另外几条改进稀疏奖励的技术路线放在一起看HER 的定位会更清楚技术路线基本思想主要限制HER 的对比优势Reward Shaping人工设计稠密奖励易引入局部最优需大量专家经验零额外设计直接复用稀疏奖励Curriculum Learning从易到难排任务序列需手动设置课程任务结构有要求自动利用目标分布不用人为排课Intrinsic Motivation用好奇心等内在奖励驱动探索容易分心探索方向不可控训练信号与任务直接相关方向更明确Hindsight Experience Replay失败轨迹用替代目标重标注后回放需任务可定义“目标状态”简单有效工程改动小当然HER 不是银弹。它对“目标状态是否能清晰定义”有要求而且不擅长解决“任务完全没有目标状态”的纯探索场景。但在拿抓取、推动、导航、一类任务做验证时它的效果非常稳定。2. HER 的核心机制拆解目标重标注到底在做什么2.1 一个失败的轨迹凭什么变成学习样本先明确一下 HER 所针对的问题设置。这里的强化学习一般是 goal-conditioned RL状态里包含一个目标 g智能体的策略以 (s, g) 为输入目标是学会能达到 g 的动作序列。比如在栅格环境里状态是当前位置坐标目标 g 是某个希望到达的终点坐标动作是上下左右移动。常规经验回放中一条完整轨迹会被存成 (s_t, a_t, g, r_t, s_{t1})。如果智能体走了 50 步都没碰到目标位置整条轨迹的所有 reward 基本都是 0没有任何梯度信号可用。这种轨迹存再多也只是白占内存。HER 做的事只有一件把轨迹的“目标”改成“轨迹最终真正到达的状态”。比如这条失败轨迹实际从 (0,0) 走到了 (3,4)原先设定的目标是 (10,10)那我就把目标改成 (3,4)重新计算每一步的 reward。因为智能体确确实实走到了 (3,4)所以每一步的 reward 就不再全为 0至少最后一步会拿到成功奖励。这样原本失败的经验就变成了“从 (0,0) 走到 (3,4) 的成功经验”可以正常用来更新策略。这里的关键在于目标重标注之后我们并没有篡改现实。轨迹中的状态转移和动作都是真实发生的只是把它解读成了一次成功的尝试。这就是“事后”的含义——等到走完这条路再回过头来看“原来我刚才完成了一次对某个目标而言的成功”。2.2 替代目标从哪里来四种采样策略的取舍HER 论文里给了四种从一条轨迹中挑选替代目标的策略它们的差别直接决定了训练效果final只用轨迹最终状态作为替代目标。random从轨迹经历过的状态里随机挑一个当目标。future把当前时间步之后经过的某个状态当目标。episode把整条轨迹经历过的所有状态当作目标全部加入经验。从工程角度说future 策略用得最多效果也最稳定。它有点像一个“循序渐进”的思路对第 t 步而言拿它之后才能到达的状态当目标会让 “当前状态离目标有多远” 这个信号更有层次感。比如轨迹前几步离最终状态还很远但从“未来某个中间状态”的视角看当前步的动作却可能是合理的。这样重放时每一步都能获得相对合理的梯度信号。final 策略最简单但样本利用率偏低因为一条轨迹只生成一次成功样本。episode 策略数据利用最狠但计算开销大容易出现高度相关的样本堆在一起的问题。random 策略介于两者之间但目标太分散训练稳定性一般。在具体实现时final 可以作为 baseline实际项目中优先用 future。如果训练曲线波动大可以试试 final因为目标分布更集中价值函数学起来反而更平滑。2.3 为什么重标注能起作用从“失败”中提取学习信号从优化视角看HER 的成功可以用“提高了每条轨迹的信息利用率”来解释。一条常规的稀疏奖励轨迹信息量可能只有几个字节没有奖励、没有正反馈。但重标注之后这条轨迹变成了一个包含明确成功信号的正样本价值函数可以从中学习到“当目标是当前实际状态时离目标多远、值函数大概是多少”。这种信号密度上的提升才是 HER 奏效的根本原因。更本质地说HER 利用了目标条件值函数的一个性质同一个状态转移对不同的目标可能构成成功或失败的不同语义。从 (0,0) 移动到 (1,0)对目标 (3,3) 来说是无关紧要的一小步但对目标 (1,0) 来说就是最后一步的胜利。一个真实发生的、物理上完全相同的转移被赋予不同的目标解释后就能变成有效训练信号。这正是 HER 的“哲学”所在不要让失败白费失败里永远藏着可以重用的成功片段。3. 从零实现一个 HER以稀疏奖励的栅格世界为例3.1 环境设计让问题足够有代表性为了看清 HER 的效果我用一个 5x5 栅格世界做测试。智能体从左上角出发目标被放置在右下角附近。动作空间是上、下、左、右四个方向奖励设计为到达目标位置给 1其他情况给 0。这是一个几乎最经典的稀疏奖励环境随机探索时如果完全靠运气可能要上万步才能碰到一次目标。这个环境虽然简单但能清楚展示 HER 的收益在相同步数预算下加了 HER 的智能体学习速度会明显快于 vanilla DQN。实际操作时我建议环境代码里把“目标位置”做成每次 episode 随机生成这样能顺便验证多目标泛化能力。如果目标是固定的HER 的优势会被削弱因为策略只需要记住几个固定的成功路径。环境代码用 Python 写一个简单的 Gym 风格接口即可不需要复杂框架。核心逻辑就是 move 方法检查边界、判断是否到达目标、返回 reward 和 done。3.2 改造经验回放池HER 的关键数据结构常规 DQN 的经验池里存的是 (s, a, r, s_next, done)。HER 版本需要额外存一条轨迹上的所有状态这样当 episode 结束时才能重新构造替代目标。我的建议是每个 episode 用单独的缓冲区暂存结束后再统一写入总池。具体流程是这样的每轮 episode 开始前随机生成一个目标 g策略网络输入为 (state, goal)输出动作。执行动作依次记录每一步的 (state, action, reward, next_state, done, goal)同时把 state 追加进本 episode 的状态列表。episode 结束后对轨迹上的每个时间步 t采样一个替代目标 g按 future 策略从 t 之后的某个状态里挑。根据 g 重新计算每一步的 reward把 (state, action, reward, next_state, done, g) 写入总经验池。这里要注意重新计算 reward 时不能只改最后一步的 reward每一步都要按替代目标重新判断“是否到达”。因为替代目标往往不是最终状态而可能是轨迹中间某个位置所以有些原本在末端才算成功的情况可能变成中途就成功反之亦然。在我的实现里每次 episode 结束后我会额外生成 K 条重标注经验。K 的选择一般取 4 或 8论文里也推荐这样的值。这个超参数代表“从一条轨迹中抽多少次替代目标”数值太大容易让经验池里满是同质样本太小则数据利用率提升不明显。3.3 训练主循环与网络结构如何把 goal 拼进输入网络结构上最常见的做法是把状态 s 和 goal g 直接拼接成一个向量输入。栅格环境里s 是二维坐标g 是二维坐标拼接成四维输入后面接两个全连接层输出四个动作的 Q 值。这个结构非常简单但要注意如果状态和目标的取值范围不同最好在拼接前做归一化否则网络训练起来会非常不稳定。训练主循环用标准的 DDQN 就行不需要其他花活。经验池用重放采样batch size 取 128学习率 1e-3目标网络每 1000 步更新一次。我试过用 DQN 原版HER 配合 DDQN 效果会更稳因为减少了对 Q 值的过估计。伪代码如下直接照搬就能跑for episode in range(episodes): state env.reset() goal sample_goal() episode_buffer [] while not done: action policy.select_action(state, goal) next_state, reward, done env.step(action) episode_buffer.append((state, action, reward, next_state, done)) state next_state # HER: relabel and store for t in range(len(episode_buffer)): s_t, a_t, _, s_next_t, _ episode_buffer[t] # future sampling: choose from t1 onward alt_goal select_future_goal(episode_buffer, t) new_reward 1.0 if reached(s_next_t, alt_goal) else 0.0 replay_buffer.add(s_t, a_t, new_reward, s_next_t, done, alt_goal) # also store original goal experience replay_buffer.add(s_t, a_t, original_reward, s_next_t, done, goal)这段伪代码里最关键的是 select_future_goal 函数。它的逻辑是以 episode 中第 t 步之后的状态序列为候选集从中均匀随机抽取一个状态作为替代目标。这样每个样本的替代目标都与“当前步之后”的真实状态相关梯度信号更有意义。3.4 环境细节的坑别让微小错误毁掉训练经验池容量对 HER 的影响很大。经验池设太小比如只有 1 万条会导致重标注样本覆盖不够效果打折。我的建议是直接开到 10 万条以上。一个 episode 可能产生几十步乘以 K 倍重标注可能很快就把小池子填满了导致之前的经验被过早驱逐。大池子能让经验分布更均匀训练更稳定。另外done 的设定要小心。如果用 future 策略替代目标往往不是 episode 的最终状态所以在替代目标的视角下轨迹可能“还没有结束”。这种情况下重标注样本的 done 应该设为 False即使原始轨迹是 doneTrue。否则智能体会误以为“在目标之外的某个状态终止是合法的”造成策略崩溃。这个小坑我踩过必须单独处理。如果环境是连续控制类任务比如机械臂那状态可能是关节角度目标可能是末端位置。这时用 HER 仍然有效但目标空间可能需要额外的归一化处理尤其是当关节角度和末端位置量纲不同时。简单拼接容易让网络被大数值维度支配我在实际项目里会为每个维度单独做 min-max scaling效果会好很多。4. 调参与踩坑实录那些文档里不会明说的细节4.1 训练初期不收敛先排查这三件事用 HER 训栅格任务时最常见的现象是“前面几千步完全没动静突然在某一个时刻曲线开始飙升”。这不是病是 HER 的正常表现重标注样本的价值函数一开始误差很大需要先学一段时间才能形成有效梯度。如果几千步之后依然毫无起色我通常按这个顺序排查第一看成功率基线。如果随机策略本身就经常到达目标比如 20% 以上成功率那 HER 的优势不明显训练也会因为正负样本不平衡而不稳定。第二看重标注逻辑。检查替代目标是不是真的从轨迹里选了以及替换后 reward 是否算对。很多第一次实现 HER 的人会在这一步漏掉“每步都重新判断到达”的细节。第三看网络输入。s 和 goal 是不是正确拼接维度是否对齐。有一次我忙了半天发现目标坐标和状态坐标的维度顺序颠倒了导致模型学到的完全是噪声。我还习惯在前 2000 步用随机探索填充经验池等池子攒够一定数量再开始训练。这样避免初始阶段经验池里都是同一批重复数据让网络早早就陷入局部模式。4.2 future 策略里的“k 值”到底怎么选HER 论文里future 策略在被选中后还要从未来状态集里随机抽一个这其实等价于“从未来状态里的均匀采样”。实际应用时有人会引入一个超参数 k表示“从未来多少步之内的状态里采样”。k 越小目标与当前步越接近挑战性越低k 越大目标离得远相当于挑战更难的任务。论文原版没有这个 k 参数但我在自己做实验时发现在连续控制类任务上引入一个小的 k 值限制训练更稳定。这个 k 等于“未来窗口”的长度。如果在机械臂抓取场景里k10 表示从“未来10步内的状态”里选替代目标让重放样本的目标不要过于遥远。原因在于连续控制任务的成功信号本来就模糊目标太远会让 Q 值估计方差变大。在栅格任务上k 的用处不大因为状态空间离散且 reward 干净但在真实机器人上我强烈建议试试不同的 k 值。我的参考方案先从 k∞即原版 future开始跑如果 loss 震荡严重再把 k 逐渐往下调观察成功率变化。我的经验是k 取 10~20 时效果比较好再小就会有“步子迈不开”的问题。4.3 目标网络更新频率与 HER 的联动很多人忽略了一个联动效应目标网络的更新频率会显著影响 HER 的效果。HER 会让经验池中出现大量“目标相同但价值不同”的样本比如同一目标下早期失败轨迹和晚期成功轨迹并存。如果目标网络更新太频繁Q 值目标变动大价值函数会很难收敛。我实测下来DDQN 的 target 更新频率在 HER 场景里建议比标准设置慢一点。标准 DQN 通常每 1000 步更新一次 targetHER 场景我建议拉到 2000~3000 步。这样能让 Q 网络有足够时间拟合相对平稳的目标否则 loss 会出现周期性的尖峰。另外HER 在离线数据集上表现也很突出。有些工程场景不允许实时在线交互只能拿固定数据集训练。此时 HER 的 relabel 逻辑依然适用——对数据集里的失败轨迹重新设定目标就能直接增加有效样本量。这一点在做机器人真实部署前的“先离线验证”时特别有用。4.4 当 HER 失效哪些任务不适合硬上HER 不是万能的有一类任务它基本无能为力目标不是“状态”的任务。比如目标是“保持平衡”“达到某个速度曲线”甚至“生成一张图片”这些目标无法用单一状态向量表示HER 的 relabel 机制就无从下手。这时更适合换成 RND、ICM 这类基于内在奖励的探索方法。还有一种情况是目标状态空间极大且轨迹的最终状态与目标语义无关。比如目标是“找到某个特定物品”但智能体的状态只是坐标位置最终状态并不等于目标本身。这种情况下HER 的重标注 “用轨迹终状态当目标” 会产生大量无意义的目标反而干扰学习。如果遇到这种场景就不要硬套 HER考虑用其他手段比如先学一个表示空间把目标映射到可比较的隐空间里。5. 用 HER 的三种正确姿势从入门实验到实际项目5.1 入门选手先跑通一个 mini 实验如果你是第一次接触 HER我建议先不要急着用框架而是自己写一个简易版本。我上面给的伪代码已经足够跑通。用栅格环境时大概 5 万步就能看到明显效果。你可以同时跑一个不加 HER 的 baseline对比两条曲线会非常直观。做这个实验时尽量保持环境简单不要一上来就上连续控制。先把 relabel 流程跑通确认替代目标、reward 重算、done 处理这些逻辑都正确了再去碰复杂环境。很多人一开始就在 MuJoCo 里折腾出 bug 后根本分不清是环境问题、网络问题还是 HER 实现问题。5.2 进阶玩家在稳定基线库上做单点替换如果已经跑通简易版接下来就值得在更接近真实的场景里验证。我这里以 stable-baselines3 为例随便说一句它自带的 HER 实现比较规整但其内部封装层次会让调参显得有点绕。如果你已经有一个自己的 DQN 代码自己实现 HER 往往反而更简洁因为只需要修改经验存储和 sample 两个环节其他代码不用动。如果决定用库建议先确认版本因为库的接口经常变动。把重放比例、替代目标采样策略这些参数单独提成配置文件方便反复调试。工程实践里配置化比写死在代码里重要得多能省下大把实验时间。5.3 项目落地把 HER 嵌入真实机器人工作流真实机器人上使用 HER有两个额外考虑。一是模拟器与真实环境的 sim-to-real gap。HER 在仿真里训练效果通常很好但部署到真实硬件上时由于目标分布变化、动力学误差策略可能明显退化。此时可以用 domain randomization让仿真环境的目标位置、摩擦系数等参数在每次 episode 开始时随机变化增强策略的泛化能力。二是从实测数据里挖经验。真实机器人采集的轨迹往往包含大量失败片段——抓取失败、推动失败、导航失败。这些数据在传统 RL 里只能用“硬训练”的方式处理但 HER 可以把它们全部转成有效训练样本。我在做机械臂抓取任务时曾经用几千条全部失败的运行记录配合少量成功数据就训练出了一个还不错的策略。这种“从失败中学习”的能力在实际项目中价值极大。6. 一点个人实战体会做了几个 HER 相关的项目之后我最大的感受是它不复杂但细节极多。整个算法逻辑用一段伪代码就能说清楚可一旦落到具体任务就会出现各种幺蛾子——reward 重算漏步、done 处理错位、目标采样策略选错、经验池不够大。这些坑每一个都不难解决但积累起来非常耗时间。我后来习惯的调试方法是先跑通一个小环境验证算法逻辑然后用 tensorboard 盯三条曲线总 reward、reach 成功率、Q loss。如果成功率上升但 loss 波动很大优先检查 target 更新频率如果 loss 平稳但成功率不动优先检查数据多样性。把这三个指标盯住大部分问题都能定位到具体环节。最后提一个脚本化技巧把“对比 HER on / HER off”做成实验模板。任何新任务上来先跑两组对比用数据说话而不是凭感觉判断“是否该用 HER”。在很多稀疏奖励任务里HER 的提升是碾压性的而在部分稠密奖励任务里它的收益可能接近于零。做一个固定对比流程能帮你快速判断当前任务是否适合这套方案。这个习惯比记住任何特定参数都值钱。
返回列表