ARTICLE DETAIL

资讯详情

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

HER算法详解:用目标重标记破解强化学习稀疏奖励难题

HER算法详解:用目标重标记破解强化学习稀疏奖励难题 第一次看到hindsight这个词大多数人脑子里蹦出来的是“事后诸葛亮”。但在强化学习圈子里它有一个更硬核的身份——Hindsight Experience ReplayHER一篇专门用来解决“稀疏奖励”问题的经典算法。如果你训练过一个机械臂给了它一个很远的目标结果它碰都没碰到每一步拿到的奖励都是零网络根本不知道该往哪个方向梯度更新这时候 HER 就是那个能让你从一堆“失败”里学出“成功经验”的骚操作。这篇文章我会把 HER 的原理、实现、调参和应用场景掰开揉碎讲清楚适用所有正在搞机器人控制、RL 稀疏奖励任务、或者想给 agent 开“上帝视角”的人。1. 项目整体设计为什么需要“后见之明”1.1 稀疏奖励问题的真正痛点先放一个我经常用的生活类比。你教一只狗捡飞盘如果把奖励定义成“它必须用嘴接住飞盘并且叼回你脚下”才给骨头那狗前一百次尝试大概率什么奖励都拿不到。狗会迷茫你也很挫败。强化学习里的稀疏奖励就是这种状态奖励函数只关心“最终目标是否达成”中间过程一概给零。经典的小技巧是设计 reward shaping给中间状态一点正向反馈但这是“人为先验”工程量和偏差都很大。HER 的思路完全不一样它不修改奖励函数而是修改“目标”本身。比如狗没叼回飞盘它只是跑过去碰了一下飞盘那 HER 就把这次经历的目标记成“碰到飞盘”然后告诉 agent你成功完成了“碰到飞盘”这个目标给奖励。听上去像是在作弊其实不是因为目标都是真实发生过的事实只不过它把“未达成的原目标”重新标记成“已达成的新目标”让原本稀疏的奖励变得稠密。这个思路在机器人操控任务里特别实用因为机器人每一步都在产生与目标相关的现实状态只是它永远够不到远处那个原始目标。如果我们只会死磕原始目标那 agent 从零开始的探索几乎等于随机搜索效率极低。HER 等于给探索过程加了无数个“可达成的小目标”让 agent 先学会走再学会跑。1.2 HER 的核心思想目标重标记HER 的原始模型出自论文Hindsight Experience Replay作者把重点放在 off-policy 强化学习上特别是 DDPG、DQN 这类有经验回放池的算法。每个 transition 原本是四元组 (state, action, reward, next_state)但多目标任务里还要附带一个 goal所以变成了 (s, a, r, s, g)。问题的核心在于 r 通常由 s 和 g 共同决定r f(s, g)。对于稀疏奖励f 几乎只在 s g 时返回 1其他时候都是 0。HER 做的事情是在每轮 episode 结束后不从这份经验里去感知而是额外生成一批“重标记后的目标”。比如用 episode 中某个未来时间步的状态 s_t 作为新的 goal g对同一个 transition (s, a, s) 重新计算奖励 r f(s, g)把 (s, a, r, s, g) 再塞回经验回放池这样回放池里就既有“原始目标的经验”也有“事后目标的经验”。后者虽然不是在追求原目标但它们能让 agent 学到在状态 s 下执行动作 a 会发生什么状态变化而这种变化对应某个真实目标的达成。我最早读论文的时候最大的疑问是用重标记目标训练会不会让 agent 执行策略时把目标搞混答案是 HER 只在训练阶段做重标记在评测阶段仍然使用原始目标agent 需要的输入始终包含目标和当前状态网络学到的是“给定一个目标如何生成动作”不是“瞎猜一个目标然后执行”。这就类似一个人下棋时复盘输棋的棋局会拆掉棋盘假装从某一步重新下学到的依然是“在不同局面下哪种走法更好”并不会在正式对局里自己给自己摆新棋局。1.3 HER 和普通经验回放有什么本质区别普通经验回放解决的是样本相关性、提高数据利用率HER 解决的是奖励信号稀缺性问题。两者可以叠加使用并不冲突。普通经验回放是把“过去的 transition”存起来随机采样HER 是对“过去的 episode”做后处理生成更多目标标签。用公式表达假设原始 episode 长度为 T每步有一个 transfer。普通的 buffer 最多有 T 条数据HER 加上 k 个额外目标后数据量变成 T × (1 k)。有了更丰富的目标分布价值函数更容易被推到一个平缓的区域。尤其是二进制奖励0/1普通回放里大多数样本 reward0Q值的方差大而 HER 重标记后的样本 reward1 的比例大幅提升Q 值能够更快地双向逼近真实价值而不是一路被零奖励压到底。我实践下来觉得HER 特别适合两类任务一类是“多目标连续控制”比如机器臂到达指定位置、夹取特定物体另一类是可并行的“稀疏奖励任务”比如导航到某个坐标点、视觉抓取。2. 核心细节解析与实操要点2.1 HER 算法流程从头到尾只看一条经验怎么“洗牌”这里我把 HER 的完整流程拆开。通常 HER 与 off-policy 算法搭配我以 DDPG 为例子。整体结构初始化策略网络 π(a|s,g)、Q 网络 Q(s,a,g)以及目标网络。每个 episode从目标集合 G 中采样一个原始目标 g。与环境交互直到 episode 结束保存当前 episode 的所有 transitions包括每一步的 obs、action、reward、next_obs 和 goal。将每个原始 transition 直接存入回放池。对当前 episode 额外采样 k 个目标来自未来状态或最终状态为每条 transition 生成 k 个重标记后的样本计算新的 reward再存入回放池。从回放池中随机采样 batch 数据更新 Q 网络再更新策略网络。这里最关键的一步是第5步中的“额外目标怎么选”。原文提供了几种策略final只用 episode 结束时的最终状态作为额外目标。future从当前 transition 之后的未来时间步中随机抽取状态作为额外目标。random从所有访问过的状态里随机抽取。episode从当前 episode 中的所有状态里随机抽取。实测下来future 策略几乎总是最优的因为它利用了一个很重要的规律短期内经历的状态往往与当前行为处于同一个成功轨迹附近这样目标既具备可达性又具备多样性。final 虽然简单但每个 episode 只有一个额外目标训练慢很多random 容易选到与当前行为毫无关系的目标学习噪声很大。推荐优先使用 k4这是论文里的默认值大多数任务在这个值附近表现最稳定。如果你的任务成功概率极低可以考虑 k8 或者更大让 buffer 里成功目标占比提高。2.2 关键参数与实现细节目标维度、奖励函数和噪声在实现 HER 的时候最容易搞错的是“目标集合的维度”。以 Fetch 环境为例状态空间是 25 维机器人关节位置、物体位置、末端执行器位置等目标空间是 3 维一个坐标点。网络输入通常要拼接观测和目标也就是 28 维输入。HER 重标记只是改变 goal 那 3 维不能改变策略输出动作的维度。奖励函数的选择也要注意。Fetch 系列环境默认的稀疏奖励是 f(s, g) 1 当且仅当 |s - g| 小于某个阈值比如 0.05。HER 中重标记后的样本如果使用的是未来状态几乎一定满足阈值条件因此奖励通常是 1。这会让回放池中正样本比例高很多但也要避免网络把“达成任意目标”都当成简单任务导致策略输出太平均。实际中我会对奖励做一个小缩放比如把成功奖励设为 1失败奖励设为 0这个已经够用如果你用连续奖励做 dense 版本反而可能引入偏差。探索噪声也是不可忽略的环节。DDPG 用的是 OU 噪声或者高斯噪声。HER 对噪声的容忍度相对较高因为哪怕探索不足只要 episode 里有状态变化重标记后的数据都能提供学习信号。但我用过纯确定性策略加很小的噪声训练 HER结果很容易卡住。建议在 episodes 前期把噪声标准差设大一点比如 0.3后期衰减到 0.05具体要看动作范围。2.3 网络架构与训练心态别盲目上大模型很多人以为 HER 是算法魔法模型随便写就能跑通。不是这样的。HER 的本质是数据层面的丰富化真正让策略稳定还是要靠好的 critic 网络。对于 Fetch 这类低维控制任务MLP 两三层就够了不需要 ResNet。我常用的结构是观测和目标拼接后过 256-256 的全连接层激活函数 ReLU最后输出 Q 值和动作。Actor 网络同样 256-256 输出动作。如果你拿来处理图像输入比如视觉抓取那要先用卷积编码器提取状态特征再把特征和目标拼接。注意卷积网络训练更慢而且 HER 重标记后的目标空间与图像空间不对齐需要额外做目标编码器把图像目标嵌入到低维空间不然直接拼接会很难学。我踩过的一个坑是更新 target network 的 τ 值。HER 对目标网络更新频率很敏感τ 太大容易训练震荡太小则学习缓慢。用 DDPG 时我习惯设 τ0.05每 episode 更新一次如果发现 critic loss 震荡明显降到 0.01。另一个坑是 batch size。用大 batch 能提高稳定性但 HER 产生的目标样本多样性高batch size 从小到大试一圈128 是性价比最高的。3. 实操过程从零构建一个 HER 训练流程3.1 环境选型为什么拿 OpenAI Fetch 当“练手沙盒”我建议第一次实现 HER 的人直接选 OpenAI Gym 的 FetchReach-v1 或者 FetchPush-v1。原因有几点这些环境自带稀疏奖励并且官方已经把 reward 计算封装好了。状态空间和动作空间是连续值适合 DDPG。目标判定有明确的阈值重标记后的成功概率非常直观。最重要的是这些环境原本就是论文里的基准环境复现结果可对照。FetchReach 是最简单的目标是让机械臂末端到达某个三维坐标点。FetchPush 需要把桌子上的物体推到一个目标位置属于物体交互难度更高。如果你用 FetchReach 都训练不收敛那多半是代码逻辑有 bug而不是 HER 的问题。安装环境只需一行pip install gymnasium robosuite但 robosuite 不一定自带 Fetch 环境传统姿势是安装gymnasium-roboticspip install gymnasium-robotics然后注册环境。3.2 核心代码实现HER 的数据管线应该怎么写完整的 DDPGHER 代码量不小这里我给出最关键的重标记逻辑这部分是 HER 的灵魂。def her_sample_goals(episode_transitions, strategyfuture, k4, future_steps50): 从一个 episode 的所有 transitions 中采样 k 个额外目标。 episode_transitions: list of (obs, action, reward, next_obs, goal) 返回 list of new_goal, 每个新 goal 是一个向量 episode_len len(episode_transitions) goals [] for _ in range(k): # 随机选一个时间步 t 作为“观察点” t np.random.randint(0, episode_len - 1) if strategy future: # 从 t 之后的未来时间步里随机选状态最多偏移 future_steps allowable_future np.arange(t 1, min(episode_len, t 1 future_steps)) if len(allowable_future) 0: sampled_state episode_transitions[-1][3] # next_obs else: future_idx np.random.choice(allowable_future) sampled_state episode_transitions[future_idx][3] # next_obs elif strategy final: sampled_state episode_transitions[-1][3] else: sampled_state episode_transitions[np.random.randint(episode_len)][3] goals.append(sampled_state) return goals上面这段代码需要注意我取的是next_obs而不是obs。这是因为状态转移之后到达的位置才能作为“事后目标”。如果用obs会导致目标本身在动作执行之前就存在后面计算 reward 时对不上。接下来是把重标记后的 transition 加入回放池的核心片段def add_her_transitions(episode_transitions, replay_buffer, k4, strategyfuture): for trans in episode_transitions: obs, action, reward, next_obs, goal trans # 原始样本直接进 buffer replay_buffer.add(obs, action, reward, next_obs, goal) # 额外目标样本 extra_goals her_sample_goals(episode_transitions, strategystrategy, kk) for new_goal in extra_goals: for trans in episode_transitions: obs, action, _, next_obs, _ trans 根据环境自带的 reward 函数计算重标记奖励 new_reward compute_reward(next_obs, new_goal, reward_typesparse) replay_buffer.add(obs, action, new_reward, next_obs, new_goal)注意这里的 reward 必须基于next_obs和new_goal计算不能直接复用原始 reward。很多人在这里直接复制了原始 reward导致 HER 完全失效我至少见过三个人踩过这个坑。如果你自己写过奖励函数一定要额外写一个compute_reward(state, goal)的接口方便重标记时调用。整体训练循环可以这样写伪代码for episode in range(EPISODES): obs, info env.reset() goal sample_goal() # 从目标分布采样 episode_transitions [] for step in range(MAX_EPISODE_STEPS): action agent.actor.get_action(concat(obs, goal), noiseTrue) next_obs, reward, terminated, truncated, info env.step(action) episode_transitions.append((obs, action, reward, next_obs, goal)) obs next_obs if terminated or truncated: break add_her_transitions(episode_transitions, replay_buffer, k4, strategyfuture) for _ in range(UPDATE_TIMES): batch replay_buffer.sample(BATCH_SIZE) agent.update(batch)3.3 训练曲线与结果分析用什么指标判断有没有用我训练 FetchPush 时观察到的现象很典型前 200 个 episode平均成功率几乎为零不是因为没在学而是因为探索阶段原始目标很难达成。加入 HER 后大概从 300 个 episode 开始成功率缓慢爬升到 800 个 episode 可以到 40% 左右最终稳定在 70%。对比没有 HER 的 DDPG同样是 800 个 episode成功率还在 3% 水平徘徊。要真正评估模型水平不要只看平均成功率推荐看“目标距离”的中位数和分位数。在每个 episode 里记录 final state 与目标之间的欧氏距离距离越小说明策略越接近目标。HER 重标记会让 agent 先学会“靠近目标”再学会“精确到达”所以你会看到距离先大幅下降然后成功率高频跃升。我还会在训练时保存每个 episode 的重放影像很多环境都支持 render_modehuman 或者用 rgb_array 录制视频。HER 训练的轨迹有时候会很诡异一开始会看到机械臂做出各种奇怪的姿势但仔细看会发现它总能碰到目标附近区域这就是“后见之明”在起作用。如果视频里机械臂总是发呆不动那可能是动作噪声过小或者目标拼接出了问题。4. 常见问题与排查技巧实录4.1 训练不收敛先从奖励和目标下手遇到训练不收敛首先检查重标记后的 reward 是否真的变稠密了。一个快速验证方法在训练之前把随机采样的 1000 条 transition 打印出来统计 reward1 的比例。如果比例小于 20%说明额外目标采样策略有问题或者目标空间和状态空间的度量不一致。Fetch 环境的目标就是坐标点你可以直接打印 new_goal 和 next_obs 的前三个维度对比肉眼就能看出是否一致。还有一个常被忽略的点HER 需要 off-policy 算法如果你的 base 算法是 A2C、PPO 这类 on-policy 算法直接把 HER 数据喂进去是没意义的因为样本分布不匹配。当然你也可以改成用 PPO replay buffer但那已经是另一个研究方向了。我建议在入门阶段严格用 DDPG 或 SAC。4.2 训练震荡critic 的 loss 飘忽不定HER 会显著增加回放池中正样本比例因此 critic 的 loss 波动会比普通 DDPG 更大。如果你发现 critic loss 在训练中期突然升高大概率是 batch 里混入了相同 episode 的重标记样本导致样本相关性太高。解决办法在回放池的采样阶段强制要求一条 transition 如果一个 episode 的重标记样本被采到不要在同一 batch 中出现超过 5 次。另一个震荡原因是 target network 更新频率太高。我试过每步都更新 target结果策略直接“抽搐”。后来自定义UPDATE_TARGET_EVERY10每个 episode 更新一次 target稳定性明显提升。如果你用 SAC 作为 base 算法也可以把 target entropy 系数调低一点因为 HER 已经让奖励信号变稠密过大的熵奖励会让策略太随机。3.3 目标空间过大高维目标怎么办如果你做视觉抓取目标是一张图片那就不能直接把 raw image 作为 goal 输入网络。HER 重标记需要一个“状态到目标”的映射最简单的是用预训练好的编码器提取图片特征在编码后的 embedding 空间做重标记。但要注意编码后的距离度量是否真实反映状态接近程度如果编码器训练得不好重标记的目标可能“看起来”很近实际却很远。我实操过一个折中方案目标仍然用物体位置的低维向量但观测里附带视觉特征。这样 HER 重标记只发生在低维目标空间视觉特征只用来感知环境。效果比纯低维好也比纯图像稳定。4.3 速查表HER 常见问题排查现象可能原因解决方法成功率长期为 0重标记目标采样错误reward 未更新检查 new_goal 来源用随机样本打印 reward 分布成功率偶尔跳到 1 又掉回 0探索噪声过大降低高斯噪声标准差改为 OU 噪声训练很慢k 值太小额外目标不足k 从 4 调到 8观察曲线变化目标区域震荡target 网络更新过快降低 τ 值延长 target 更新间隔表现好但在测试失败训练时用了重标记目标测试时目标变了确保评测阶段只给原始目标网络输入维度报错拼接 obs 和 goal 时维度不对检查是否对齐 target 空间维度4.4 家长式经验千万要保存检查点和重放如果你要烧好几个小时训练千万别只保存最后的模型。HER 训练过程中的最优模型往往出现在中后段而不是最后一个 epoch。我习惯每 100 个 episode 保存一个 checkpoint然后跑 10 个 episode 做验证取平均成功率最高的 checkpoint 做最终评测。这样能避免后期过拟合到训练集上的目标分布。另外重放视频是定位 bug 的最佳工具。有一次我训练出来的策略在测试时总是把物体推出桌面外后来看视频才发现那是因为训练时的目标采样分布本身包含了桌面边界外的点HER 把“推出桌面”也当成一个成功目标学进去了。解决办法是重写sample_goal限制目标范围或者加入“禁止出界”的惩罚。这个 bug 不通过视频真难发现。5. 应用场景与扩展思考5.1 机器人操控从单任务到多任务复用HER 最成功的落地场景就是机器人手爪抓取、推动、摆放这些操作任务。在这些任务里奖励函数往往只在最后一步给 1中间全是 0如果状态维度高直接端到端训练几乎不可能。HER 的价值在于让同一个数据集同时支持多个目标训练出的策略其实是一个“目标条件策略”你可以在推理时给任意目标它都能生成到达该目标的动作序列。更进一步HER 和多任务学习可以结合。把不同任务的目标混合在一个回放池里用同一个模型完成“推动”和“抓取”只要目标空间设计合理模型会自然学会任务之间的迁移。我见过一个项目把 FetchPickAndPlace 的目标空间扩展成“物体位置 分类标签”成功让一个 agent 学会多种物体操作。注意多任务时目标空间要能区分不同任务否则重标记会把两个任务的目标混淆。5.2 自动驾驶、推荐系统里的“后见之明”不只是机械臂。任何有“稀疏延迟奖励”的问题都可以套用 HER 的思维。比如自动驾驶变道任务车辆没有在 200 米内成功完成变道算失败但如果它行驶了一段距离并产生了安全轨迹也可以用“事后目标”把它标记成一次成功的换道过程——当然要保证不会撞车。推荐系统里也可以把“用户没有最终点击”的会话重标记为“完成了对某些物品的浏览”把展示行为作为过渡目标增加训练信号。我在实际项目里帮人做过一个库存调拨的模拟器目标是让每个仓库库存达到指定水平稀疏奖励只在与目标差异小于阈值时触发。用 HER 之后agent 学会了很多中间状态的“达成”训练速度提升了好几倍。它的意义不是让某个任务变简单而是给奖励稀疏的现实问题提供了更通用的学习信号。5.3 HER 的进阶搭配SAC、课程学习与目标生成最后聊点扩展。HER 本身不挑算法最近几年大家更喜欢用 SAC 做 base因为 SAC 更稳定、对超参没那么敏感。SAC HER 的组合在 MuJoCo、robosuite 里都有不错表现。我在训练时会在 SAC 的 temperature 上做调整HER 已经提供了稠密奖励temperature 可以设得比纯 SAC 更低比如 0.1 起步。另外一个好搭档是课程学习。先用简单的目标距离近的训练再逐步采样远处目标让 agent 像人一样从容易到难。HER 的多目标特性可以天然支持这种课程你只需要控制sample_goal的分布。如果发现 HER 后期提升缓慢试试只采样更难的目标或者提高目标阈值的精度。目标生成也值得研究可以训练一个额外的 GAN 或 VAE 来生成“适中难度”的目标专门喂给 HER 重标记。目标难度太高会导致重标记后的样本离原目标太远太低则学习上限不高。我个人觉得先从最朴素的 future 采样开始跑通实验再考虑进阶这是最稳妥的路线。最后分享一点我个人的体会。HER 这个名字起得很妙它借用“事后诸葛亮”这个人类认知习惯来改进机器学习的探索策略。我自己在实现过程中最大的收获是一个看似简单的目标重标记背后对数据流、网络结构、超参数都有连锁影响不能因为代码短就轻视它。如果你现在也卡在稀疏奖励任务上照着这篇文章先跑通 FetchPush再去应用到你自己的场景应该能少走很多弯路。如果训练中遇到什么诡异的问题欢迎在评论区聊聊我尽量帮你排查。
返回列表