尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

稀疏奖励不再愁:HER算法如何用目标重标记撬动强化学习训练

稀疏奖励不再愁:HER算法如何用目标重标记撬动强化学习训练 hindsight这个词在英语里是后见之明我们通常拿它自嘲事后诸葛亮。但在强化学习领域这个词却摇身一变成了解决稀疏奖励问题的核心算法。我最早接触 Hindsight Experience Replay后见经验回放简称 HER时是在一个机械臂抓取项目里——训练了整整三天奖励曲线纹丝不动几乎要放弃的时候换成 HER 之后只过了半天策略就开始有了肉眼可见的进步。那种感觉就像终于找到了把失败经验也变成学习养分的钥匙。这篇东西我打算把自己从原理理解到实际调参的经验都摊开讲。适合刚入坑强化学习、正被稀疏奖励折磨的初学者也适合那些已经在跑 DDPG、PPO、SAC但想让智能体在复杂任务里学得更快的实战派。你不需要是数学天才我会把所有概念都掰碎了说。1. 为什么稀疏奖励让人头大——HER 要解决的痛点1.1 那些死活学不会的强化学习场景想象一下这个场景你让一个机器人学会推开桌上一瓶矿泉水。任务目标是把瓶子推到指定的红色圆圈内。问题是红色圆圈只有巴掌大机器人每次随机摆动机械臂想让瓶盖恰好落在圈里的概率低到可以忽略不计。现实中的机器人任务绝大多数都是这种状态——奖励信号稀疏得像沙漠里的绿洲。比如倒水、叠衣服、组装零件这些任务的共同点是只有完成整个任务那一个瞬间才能拿到 1 的奖励其他所有时间步奖励都是 0。这种环境下传统强化学习算法全靠随机探索来碰运气积累正向反馈。但稀疏奖励意味着你随机探索一万次可能连一次正向奖励都摸不到。梯度消失策略原地踏步训练曲线长时间停留在初始值附近。1.2 传统算法为什么在这种任务上直接失灵先说说那些经典算法在这类问题上的短板。Q-learning 和 DQN 这一类基于价值的方法依赖能拿到奖励的样本来更新 Q 值。在稀疏奖励下大部分样本的回报都是 0Q 值网络根本无从学习哪个动作更有价值。Policy Gradient 类方法比如 REINFORCE好一点但同样的问题也存在它对动作的评价依赖轨迹的总回报如果总回报几乎都是 0算出来的梯度方差极大参数更新就像在迷雾里开车。DDPG 这类行动者-评论家Actor-Critic结构稍微强一些但说到底Critic 的 Q 值估计也需要有奖励信号做支撑。我见过很多同学用 DDPG 硬撸 FetchReach 这种简单任务运气好能过一旦换成 FetchPickAndPlace机械臂抓取并放置训练一周曲线依然是平的。原因很简单没有有效的正样本价值网络就是一张白纸。1.3 hindsight这个双关词的精妙之处我第一次听研究员解释 HER 名字的由来时心里拍案叫绝。Hindsight既表达了站在事后角度回看经验也暗含了从失败中提取成功经验的哲学意味。它不是让你去改变过去而是让你换一个目标来审视过去的轨迹。机器人推瓶子没推到红圈没关系我们把它真实到达的位置记为新目标然后重新计算这条轨迹的奖励。这样一条原本全是 0 奖励的失败轨迹摇身一变成了一条成功通往新目标的轨迹。这就是 HER 的全部魔法——重新标记目标Goal Relabeling。2. HER 的核心思想把差一点成功变成成功2.1 三段式拆解目标重标记的完整过程在正式进入实操前必须先建立一个清晰的心智模型。HER 的训练流程由三个核心环节组成。第一采样轨迹Rollout。智能体按照当前策略与环境交互生成若干条完整轨迹。每条轨迹由状态、动作、奖励和新状态构成这些状态里包含一个期望目标就是那个红圈坐标。第二目标重标记Relabeling。这是我们介入的关键环节。面对一条没有达成预期目标的轨迹我们要做的不是把它扔掉而是从这条轨迹事后发生的状态里选一个真实达到过的状态把它当作这条轨迹的新目标。最常用的方式是从轨迹结束后的若干时间步里随机挑一个状态作为新的期望目标。然后基于这个新目标重新计算轨迹里每一步的奖励——因为新目标确实被达成了所以这条轨迹瞬间从失败变成了成功并且轨迹末尾的奖励必定是 1。第三训练更新Update。将原始轨迹和新生成的成功轨迹一同放入经验回放池供 DDPG 或者 SAC 等算法采样训练。这里有个细节状态和动作本身不需要变只需要把每一帧的目标字段替换掉并重算奖励即可。2.2 一个考试错题的类比五秒搞懂 HER说实话目标重标记这个概念第一次接触的人可能觉得绕。我习惯用考试类比来辅助理解。假设你参加一场射击比赛目标是十环。你打了一枪脱靶偏离到靶子左上角。按正常逻辑这一枪没有任何参考价值。但 HER 的视角是虽然十环没打中但这一枪左上角打得极其精准——如果你把目标改成本来就在左上角的位置这一枪就是满分操作。所以 HER 做的事情就是把每一次脱靶记录都变成瞄准那个实际落点并且打中了的成功样本。对于机器人来说这种成功的假样本虽然目标不是最初指定的那个但同样包含了丰富的状态-动作-结果对应关系。它相当于告诉策略我用这样的动作序列成功到达了这样的状态。当大量的失败轨迹都被转化成不同目标下的成功轨迹时策略就能学到什么样的动作会导向什么样的状态变化。这比凭空摸索要高效得多。2.3 未来时间步的采样策略具体是怎么做的刚才提到重标记新目标最常用的策略是从未来时间步future time steps采样。我来解释具体操作以及为什么这样做。假设一条轨迹有 T 个时间步我们手里有状态序列 s_1, s_2, ..., s_T。我们通常会这样设定一个重标记比例参数比如 0.8 或 1.0表示一条轨迹里有多少比例的数据会被重标记。对于每条要重标记的样本它在时间步 t我们会从 (t, T] 这个区间里随机抽取一个时间步 t然后把 s_t 里的目标字段比如物体坐标当作这条样本的新目标。这样做的好处非常直观越是靠近轨迹末尾的状态越有可能接近最终目标。如果从整条轨迹里随便抽可能会抽到刚开始时、目标还很远的状态那样重算出来的奖励虽然正了但起点到目标太近学习效率会打折扣。从未来时间步采样保证了重标记目标和轨迹实际走向有一定的时间连续性。2.4 HER 到底强在哪里一个理论视角很多教程会告诉你 HER 有效但不说它为什么有效。这里从两个维度补充一下。第一奖励密度直接提升。经过重标记后经验回放池里的正样本比例从接近 0% 提升到了接近 50%取决于重标记比例。这意味着价值网络每次采样小批量数据时几乎一定能看到正反馈Q 值估计的方差大幅降低。直观来说算法终于看清了梯度方向。第二天然的课程学习效应。仔细想想HER 的目标分布里既有容易达成的目标比如实际走过的位置也有困难的目标原始指定目标。策略不会一开始就承受所有难度而是先学会达到容易达成的状态再逐步过渡到达成困难的目标。这种由易到难的隐性课程让探索过程少走了大量弯路。我自己在机器人抓取项目里体会尤其深刻——任务目标距离很远的时候HER 能稳定引导策略先靠近再尝试抓取这是一个非常自然的渐进过程。3. 实战操作零基础跑通一个 HER 训练项目3.1 环境选型OpenAI Gym 的机器人任务集这一部分我用自己实际跑过的环境为例直接给出可复现的步骤。强化学习环境的选型我大力推荐 OpenAI Gym 里的机器人任务集Fetch 系列包括 FetchReach机械臂末端到达目标点、FetchPush把物体推至目标、FetchPickAndPlace抓取物体并放置到目标。这些环境采用 MuJoCo 物理引擎自带稀疏奖励定义和多种目标生成逻辑是验证 HER 效果最便捷的试验田。先装依赖Python 3.8 环境下运行pip install gymnasium[mujoco] # 新版 Gym 用 gymnasium 替代 pip install mujoco-py # 如果使用旧版环境需要这个然后加载环境import gymnasium as gym env gym.make(FetchReach-v4) obs, _ env.reset() print(obs.keys()) # 观察空间里通常包含 observation, achieved_goal, desired_goal 三部分这里的核心结构要认清每次观测都拆成三部分——当前观测状态observation、实际达成的目标achieved_goal、期望目标desired_goal。HER 的重标记操作正是在这三者之间腾挪。3.2 手把手写一个最小可用的 HER DDPG 脚本选定了环境接下来就是写核心算法。为了方便说明我摘出最关键的重标记逻辑片段代码基于 stable-baselines3 的 HER 实现思路改写但去除了无关细节。import copy import numpy as np def relabel_trajectory(episode, her_ratio0.8, future_k4): episode: dict包含 obs, acts, next_obs, rewards 等数组 返回重标记后的新样本 her_samples [] horizon len(episode[rewards]) for t in range(horizon): if np.random.random() her_ratio: continue # 从未来时间步中随机挑一个作为新目标 future_time np.random.randint(t, min(t future_k, horizon)) new_goal episode[achieved_goal][future_time].copy() # 用新目标替换原目标并重算奖励 new_obs copy.deepcopy(episode[obs][t]) new_obs[desired_goal] new_goal new_next_obs copy.deepcopy(episode[next_obs][t]) new_next_obs[desired_goal] new_goal new_reward env.compute_reward(episode[achieved_goal][t 1], new_goal, None) her_samples.append((new_obs, episode[acts][t], new_reward, new_next_obs)) return her_samples代码的关键点就是最后一行env.compute_reward(achieved_goal, desired_goal, info)。在 Gym 的 Fetch 任务里这个函数会检查实际达成的目标是否足够接近期望目标足够接近就返回 1否则返回 0。换上新目标后这条样本的奖励几乎必然变成 1。但只做重标记是不够的HER 必须配合 off-policy 算法才能发挥最大功效因为重标记产生的成功样本并不是当前策略真正执行出来的轨迹它必须放在经验池里被反复采样学习。我用 DDPG 做基础算法原因在于它对 off-policy 数据的需求天然契合 HER。SAC 也可以但 DDPG 更简单调参经验更成熟。核心训练循环结构大致是# 伪代码理解流程即可 for epoch in range(n_epochs): # 1. 收集 episode episode collect_one_episode(env, policy) # 2. 原始样本入池 replay_buffer.add(episode) # 3. HER 生成成功样本 her_data relabel_trajectory(episode) replay_buffer.add(her_data) # 4. 从经验池采样更新 actor 和 critic for _ in range(n_updates): batch replay_buffer.sample(batch_size) update_ddpg(batch)3.3 参数怎么调buffer 大小、k 值、重标记比例超参数的选择直接决定训练效果这部分我结合自己的试验数据展开。重标记比例her_ratio我建议从 0.8 起步。这个值表示一条轨迹里有多少比例的数据会执行重标记。调到 1.0 也不是不行但会让经验池里假成功样本过多策略可能会过度拟合到那些容易达成的伪目标上导致对真实目标的学习变得迟缓。0.8 是一个兼顾探索和利用的中间值。future_k 值这个参数决定从未来多少个时间步里选新目标。OpenAI 原论文里测试了 k1 和 k4发现 k4 在多数任务上优于 k1。k 太小新目标和当前状态太接近学习不到如何通过动作改变状态的有效信息k 太大又会引入太多无关状态噪声。我在 FetchPush 任务上分别用 k4 和 k8 做过对比k4 的收敛速度明显更快最终成功率也更高。经验池容量HER 相当依赖经验池的多样性和规模。我的经验值是至少 10 万条样本起步。如果机器内存允许50 万条也不算多。容量太小重标记产生的成功样本很快被旧数据稀释效果大打折扣。3.4 训练曲线的三个关键观察点HER 训练和普通 DDPG 训练最大的区别在于你能从曲线里读出更多信息。我自己总结出三个必须盯紧的观察点。第一成功率的上升方式。HER 加持下的成功率曲线往往不是平滑上升的而是阶梯状波动上升。因为它本质上是先学会达到容易目标再冲击困难目标的过程中间会有阶段性的突进。如果你看到成功率长期在 0 附近纹丝不动那多半是重标记逻辑写错了或者compute_reward函数使用方式有问题。第二Critic 的 Q 值平均值。HER 会让 Critic 对达成目标这件事给出显著偏高的 Q 值预测。如果 Q 值的平均值在训练早期就快速上升说明价值网络正在从重标记样本中学到有效信息如果 Q 值始终低迷说明重标记产生的正样本没有被充分采样。第三探索噪声的衰减节奏。DDPG 通常依赖 Ornstein-Uhlenbeck 噪声或者高斯噪声来探索。HER 会显著加速学习所以噪声衰减可以比默认参数稍微快一点。我在实际项目中把噪声标准差从 0.3 衰减到 0.05 的时间缩短了三分之一没有出现策略崩溃的现象。4. 实战中踩过的坑与排查技巧4.1 坑一重标记后目标维度对不上HER 实现中最大概率翻车的点就是目标维度处理不一致。Fetch 环境里achieved_goal通常是一个三维坐标但如果你使用的是自己定制的环境achieved_goal和desired_goal的数据结构可能一个是我写成的 dict另一个是 numpy 数组直接复制就报错。排查方法很简单遇到维度报错的时候先打印出来看print(type(obs[achieved_goal]), obs[achieved_goal].shape) print(type(obs[desired_goal]), obs[desired_goal].shape)大多数情况下问题出在 deepcopy 之后忘了同步desired_goal的数值。我这里再提醒一句深拷贝对象时只拷贝你实际需要的那几个字段不要整个 obs dict 无脑 copy否则内存开销会爆炸。4.2 坑二HER 全开导致策略跑偏有一种情况训练初期成功率上升极快但到了某个点之后就卡住不动了。我仔细追踪后发现问题出在重标记比例太高导致经验池里全是人工成功样本原始目标几乎被淹没。策略学到的其实是一个能够移动到大部分位置的策略而不是移动到特定目标的策略。解决思路是往经验池里混入更多原始轨迹数据。我后来把重标记比例降到 0.6效果立竿见影。如果你也遇到这种问题先别急着动学习率调一下重标记比例多半能解决。4.3 坑三稀疏奖励环境下 Critic 过拟合HER 虽然大幅提高了正样本比例但 Critic 仍然有可能过拟合。具体表现为训练到中后期Q 值预测很高但实际 rollout 的成功率却在下降。这通常是因为重标记产生的轻易成功样本太多Critic 对部分状态给了过度乐观的估计。我的排查经验分两步。第一步降低 Q 网络的学习率从 1e-3 降到 3e-4 往往有效第二步在 Actor 和 Critic 更新次数上做文章把每次 rollout 后的更新次数从 40 提高到 80让 Critic 有更多机会消化数据。这两步配合基本上能压住过拟合。4.4 问题速查表一张表解决 80% 的异常我把训练过程中常见的异常现象、可能原因和应对手段整理成了一张表方便你对照排查。现象可能原因排查手段成功率全程为 0重标记后新奖励计算错误单独验证compute_reward(achieved_goal, new_goal)是否为 1成功率前期上升后长期卡住重标记比例过高将her_ratio从 0.8 降至 0.5~0.6Q 值很高但 rollout 失败率也高Critic 过拟合降低 Q 网络学习率或增加每次迭代更新次数训练初期 Loss 就 NaN奖励或观测维度存在异常值检查是否有无穷大奖励加入观测值裁剪环境重置时间过长GPU 利用率低环境采样过慢导致经验池增长慢改用向量化环境并行采样4.5 独门心法先跑通再优化我给新手的建议只有一条第一版代码宁可笨不可复杂。先把 HER 逻辑写成一个独立的函数跑通 FetchReach 这种最简单的任务成功率到 100% 之后再逐步引入目标生成策略、多进程采样、自动超参搜索这些花活。我见过太多人一上来就想复现论文里的完整方案结果错误埋得太深排查一周都找不出问题。5. HER 的变体与更多应用场景5.1 从经典 HER 到更聪明的变体经典 HER 的从未来时间步采样目标策略通常够用但在某些任务上存在明显局限。比如目标状态本身非常复杂例如图像、自然语言描述此时随机采样一个未来状态作为新目标可能生成的样本对学习毫无帮助。于是出现了不少改进思路。其中一种是基于能量函数的目标选择策略不随机采样而是优先选择与原始目标语义相近、但更容易达成的状态作为新目标。另一种把 HER 和分层强化学习结合先用 HER 学习低级技能再在高级层面学习技能的组合顺序。这些变体我虽然没有在生产环境跑过但在论文复现中体会到它们解决的是更边缘的问题——如果经典 HER 在任务上已经能跑到 90% 成功率那没有必要引入额外的复杂度。5.2 除了机器人HER 还能用在哪HER 不止适用于机械臂。只要是目标可观测、奖励稀疏的任务它都有发挥空间。我自己评估过两个方向。第一个是游戏 AI。很多游戏的目标比如到达某个位置、拿到某个道具非常明确稀疏。用 HER 重标记游戏角色真实经过的位置就可以把大量失败的对局变成有效的学习样本。第二个是工业控制中的配方优化。比如工业窑炉的升温曲线控制最终目标是到达某个温度曲线但中间因为各种扰动总是不达标。HER 可以把实际到达的曲线看作目标学习一条有效逼近轨迹的控温策略。当然这个方向对安全性要求极高实际落地仍需谨慎验证。5.3 为什么日常项目中我更偏爱 HER 而非高维复杂算法做了几年强化学习落地项目我的感受是很多团队一上来就追求新出的复杂算法觉得模型越大越高级。但实际业务场景中数据效率智能体往往比算力堆砌的智能体更管用。HER 最大的优势在于它几乎不需要额外算力只靠对现有轨迹做事后重标记就能成倍提升样本利用效率。这种低成本改进在公司资源受限的环境下比换一个更大规模的模型划算得多。最后分享一个我常用的训练小技巧这一部分不写算法写个实验技巧。我在跑 HER 训练时习惯每隔 50 个 epoch 手动保存一份模型并同时存下当时的经验池状态。这样做的原因是HER 训练中偶尔会遇到环境物理引擎不稳定的情况比如某一个 rollout 出现了异常大的力导致机器人飞出空间这一条异常数据如果不及时清除会污染后续所有训练。有了定期 checkpoint一旦发现成功率曲线异常下滑我可以快速回退到最近的健康状态而不是从头再来。这个习惯救过我至少三次推荐大家都试试。
返回列表