ARTICLE DETAIL

资讯详情

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

HER目标重标记:从失败轨迹中学习,解决稀疏奖励难题

HER目标重标记:从失败轨迹中学习,解决稀疏奖励难题 第一次听到“hindsight”这个词大多数技术人脑子里蹦出来的可能是“事后诸葛亮”这句俗语。但在强化学习领域它有一个极其硬核的身份Hindsight Experience Replay简写为HER是解决稀疏奖励问题的经典方案之一。我最早在机械臂抓取仿真环境里接触它当时用普通的DQN训练智能体在一个只有末端触碰到目标物体才给奖励的任务里折腾了好几天都学不出任何有效动作。换上HER之后一个晚上就能看到明确的接近目标物体的策略出现这个改观让我印象很深。这篇文章我想把这个方法彻底拆开从核心思想到实现细节再到调试经验尽量讲清楚它到底是怎么做到“从失败里学习”的。如果你正在做机器人控制、游戏AI、导航这类奖励稀疏的强化学习任务或者你已经跑通了基础算法但面对复杂环境无从下手这篇文章应该能带来一些可落地的参考。即使你只是刚开始了解强化学习我也会尽量把概念讲得通俗让你理解HER到底在解决什么问题。1. 后见之明的力量为什么稀疏奖励让人抓狂1.1 稀疏奖励到底难在哪里强化学习的本质是让智能体通过与环境的交互学习一套策略来最大化累计奖励。听起来很直接但一旦任务属于“稀疏奖励”类型事情就变得非常棘手。所谓稀疏奖励指的是绝大多数状态下智能体拿到的奖励都是0只有极少数关键状态能获得正反馈或负反馈。举个例子让一个机器人学习把桌面上的方块抓起来。常规的奖励设置可能是只有成功抓到并抬高到指定高度才奖励1分。那么在训练早期机器人随机挥动机械臂几乎永远得不到这个正奖励。所有走过的轨迹都像是“白走一趟”梯度信号几乎为0智能体没法知道哪一步动作好、哪一步动作差。这就好比你让一个新手学投篮但只有投进空心球才告诉他“做对了”其他任何情况都不给反馈。正常人的学习早就崩溃了智能体也一样。稀疏奖励环境的主要困难在于探索效率极低。智能体需要靠随机动作去撞大运找到第一个正奖励这个“撞大运”在高维连续动作空间里几乎是不可能完成的任务。即使偶尔碰上奖励正样本也太少模型容易过拟合到某条偶然成功的轨迹无法泛化。1.2 换个角度看失败HER的出发点HER的思想深受人类学习方式的启发。仔细想想我们人类在实践中学习并不是每次都必须“成功”才能获得经验。投篮没进但你能看到球飞到了偏右的位置于是你学会“出手角度要往左调一点”。下棋输了但你会复盘“如果当时不贪吃那个兵局面会好很多。”这就是后见之明当时没有实现最初的目标但你知道了“如果目标是另一种样子刚才那串动作就是成功的”。HER把这种思路搬到了强化学习里。它的核心逻辑是在当前回合中智能体原本要到达目标 A但实际探索并没有到达 A。可是这整条轨迹确实到达了另一个状态 B。如果我们“事后”把目标改成 B那这条轨迹就成了一个成功轨迹奖励不再是稀疏的0而是可以学习到正向信号。也就是说不是让智能体学会“怎么成功”而是让智能体学会“成功后的状态长什么样”从而在大量失败轨迹里挖掘出教学价值。这种思维听起来很朴素但它直接改变了强化学习经验回放机制的处理方式。HER 实际上没有改变“探索”和“利用”的基本框架而是改造了样本本身把原本无用的失败样本重新标记成可用于训练的“准成功样本”。这个思路对很多 low-level 机器人任务特别有效因为在这些任务里目标状态往往可以用向量表示比较容易重定义。2. HER的核心机制目标重标记与轨迹采样策略2.1 如果给一条轨迹换个目标在具体介绍 HER 之前需要先明确它适用的任务设定。HER 主要针对“多目标任务”也就是每个 episode 都对应一个给定的目标 goal环境的状态里必须包含两部分信息desired_goal期望目标和 achieved_goal实际达到的状态。常见任务如 OpenAI Gym 里的 FetchReach、FetchPush、FetchSlide 等都属于这类。一个 episode 可以表示为一条轨迹s0, a0, r1, s1, a1, r2, ..., sT其中每一步的状态 si 本身包含当前实际的机械臂末端位置、物体位置。在原始目标 g0 下每一步的奖励 r_i 只有在满足某个判定条件时才是1否则为0。这样的轨迹学习起来非常困难。HER 的做法是在采样经验回放时不仅使用原始目标 g0 来训练还额外生成一些“重标记目标”g。g 从哪里来最好的来源就是这条轨迹本身未来某个时刻的状态。因为既然轨迹中确实到达了状态 s_t那么把 s_t 当作目标就是合理且真实可达的。在重标记的目标下回放的那一步 transitions_t, a_t, s_{t1}就很有可能是带正奖励的因为 s_{t1} 距离 s_t 非常接近。于是原本全是零奖励的 buffer 里多了很多正样本模型就能学到“在这个状态附近做这个动作会走向目标”的知识。这个机制并不复杂但要注意一点重标记的目标不能随便从状态空间里随机选最好从该轨迹的“未来状态”中选取因为这样可以保证目标本身是当前策略可以实现的学习起来的难度曲线比较自然。如果随机选一个根本不可能达到的目标智能体会收到大量“伪成功”信号反而导致策略跑偏。2.2 四种目标采样策略参数调整决定成败HER 论文里给出了四种从轨迹中抽取替代目标的方法分别是 final、future、episode 和 random。实际工程中最常用的是 future 策略它的表现最稳定。final 策略最简单就是只把整条轨迹最后达到的那个状态作为替代目标。这个策略适合轨迹较短、目标相对容易达到的场景。如果轨迹太长最后的状态和前面大部分动作的因果距离太远中间步骤仍然很难学到有效关联。future 策略是在轨迹中随机选择一个“未来时刻”的状态作为替代目标。具体做法是给定当前回放时刻 k从 k 到轨迹末尾之间随机抽取一个时间点 t把 s_t 作为替代目标。为了避免每次选的目标过于分裂还会引入一个超参数 K表示只考虑未来 K 步内的状态。论文中常用的设置是 K4采样概率 p0.75。也就是说每条经验有75%的概率被重标记为未来目标25%的概率保留原始目标。episode 策略则是从整条轨迹的任意状态里选目标不只是未来。这会引入更多样化的目标但也可能选中那些和当前动作完全无关的状态噪声更大。random 策略是从环境的全部状态空间里随机选目标除非你做的是目标空间本身特别简单的情况否则一般不太推荐。我把几种策略的优缺点整理成了一个对比表格方便你选择采样策略替代目标来源优点缺点适用场景final轨迹最终状态简单、确定性高长轨迹中间步骤信号弱短轨迹任务future未来 K 步内的状态密度高、信号稳定增加超参数 K 和 p机器人抓取、操作任务最常用episode轨迹内任意状态目标多样性高目标可能和动作无关探索初期random状态空间随机采样覆盖范围大伪目标过多学习困难几乎不推荐2.3 为什么重标记之后效果这么好从数学角度看HER 实际上是在修正经验回放中的目标分布。多目标强化学习要学的其实是两个映射关系从“当前状态 目标”到动作的映射以及从“状态 目标”到价值的映射。原始稀疏奖励条件下价值函数几乎处处为0梯度消失。重标记后让价值函数开始在一些真实可达的目标附近有非零值从而产生学习信号。更直观地说HER 把“稀疏的单点反馈”变成“路径上的密集反馈”。它不需要人工设计奖励函数不依赖域知识只要你能定义状态表示和奖励判定条件就行。这在实际工程里非常讨喜很多机器人任务里我们只知道“目标位置”很难设计复杂的 shaping rewardHER 几乎是一键式解决。不过也要清醒地认识到HER 不是万能的。它对状态表示非常敏感。如果 achieved_goal 的表示不完整比如机械臂抓取任务里只记录物体位置而不记录物体朝向那么重标记的目标可能会遗漏关键信息导致学习失败。此外HER 并不能解决所有探索问题它只是让失败轨迹变得更有信息量。如果任务本身的探索空间极大而且失败轨迹几乎不会接近任何成功状态HER 的效果也会大打折扣。3. 实操落地从环境搭建到关键代码实现3.1 环境接口使用 GoalEnv 标准在实际项目里应用 HER第一步是确保环境遵循类似 Gym GoalEnv 风格的接口。我以 OpenAI Gym 中的 FetchReach 为例说明。FetchReach 是一个二维机械臂仿真环境任务目标是一个三维坐标点机械臂需要把末端移动到指定位置。环境的主要接口有三个关键方法reset 返回一个包含 observation 的字典其中 observation 里有 achieved_goal当前末端位置和 desired_goal目标位置step 根据动作更新状态并返回新 observation、奖励、done 等compute_reward 根据 achieved_goal 和 desired_goal 判断是否达到目标并返回奖励。如果你打算用自己的机器人仿真环境建议也按照这个结构来封装因为 HER 的重标记过程直接依赖 achieved_goal。一个特别容易踩的坑是很多人把 reward 判定写在 step 函数里而没有独立的 compute_reward 函数。HER 重标记时需要重新计算新目标下的奖励如果奖励逻辑散落在 step 里代码会很乱也很容易出错。我建议无论如何都要把奖励计算抽成单独的函数方便在重标记时调用。3.2 简化版 HER 核心代码解析下面我用 Python 伪代码来演示 HER 重标记的核心逻辑这个代码结构是我实际用过的简化版去掉了复杂的网络细节只突出目标重标记过程。import numpy as np def her_remap(trajectory, transitions, her_param): trajectory: 一条完整轨迹包含 states、actions、rewards、goals transitions: 从 trajectory 中拆分出的 (s, a, r, s_, g) 列表 her_param: 目标采样策略参数如 K4, p0.75 s, a, r, s_, g_orig transitions new_transitions [] for i in range(len(s)): # 保存原始目标样本 new_transitions.append((s[i], a[i], r[i], s_[i], g_orig[i])) # 以概率 p 生成重标记目标 if np.random.uniform() her_param[p]: # 只在未来 K 个 state 里采样 max_future min(len(s), i her_param[K] 1) future_index np.random.randint(i 1, max_future) new_goal s_[future_index][achieved_goal] # 重新计算奖励 new_reward env.compute_reward(s_[i][achieved_goal], s_[i][desired_goal], {achieved_goal: new_goal}) new_transitions.append((s[i], a[i], new_reward, s_[i], new_goal)) return new_transitions这个函数的输出会被合并到经验 buffer 中。普通经验回放只存原始 transition而 HER 在每个 transition 后面额外追加一条或多条“未来目标”版本的 transition成倍扩大了有效样本量。这里有一个实现细节advance 的时候s[i] 的 observation 里本身既有 achieved_goal 也有 desired_goal。重标记时我们只需要替换 desired_goal 这个字段然后用新的 desired_goal 计算奖励别的都不用动。在训练网络时输入给 actor 和 critic 的 goal 维度也必须相应替换否则网络看到的目标向量和奖励对不上梯度就乱了。3.3 超参数设置与训练流程HER 本身虽然不挑算法但要调好超参数才能发挥效果。我的经验是replay buffer 要大一般至少 50 万条 transition因为经历重标记后样本是成倍增加的buffer 太小会导致同一批经验被反复重标记过拟合。batch size 建议 256 或更大multi-goal 环境下数据方差比较大小 batch 容易震荡。actor 和 critic 的学习率分别设置在 1e-3 和 1e-3 量级附近如果训练不稳可以单独降低 actor 的 lr。训练流程上和普通 off-policy 算法没什么两样先用随机策略采样几条 episode 存进 buffer每次更新时从 buffer 里随机采样一个 batch然后对 batch 里的每条 transition 做 HER 重标记追加重标记样本后统一用于更新 Q 网络和策略网络。注意一定要等 buffer 里有一定量数据才开始更新比如 5000 条以后否则统计量不稳。我之前在 FetchReach 任务上调参时发现一个现象future 策略里的 K 如果设得太大比如 K20重标记目标和当前动作之间的时间距离太远Q 网络很难拟合K 太小比如 K1虽然目标很近但信息量太小学习效率不高。K4 确实是论文里多年前就验证过的好值我换了几个任务后依然觉得这是一个靠谱的起点。4. 踩坑记录与经验心得HER 不是银弹4.1 常见问题排查速查表我把这几年用 HER 过程中遇到的高频问题整理成一个速查表每一条都是我踩过的实实在在的坑。问题现象可能原因排查思路与解决方案训练完全不收敛loss 快速坍缩goal 维度设置错误或重标记时 reward 计算错了单独检查 compute_reward确认新 goal 下 reward 应该为 1实际是不是 1策略学到一半开始乱抖重标记目标占总样本比例过高把 p 从 0.75 降到 0.5多保留一些原始目标样本仿真里效果不错真机上完全不行achieved_goal 的状态表示与真机观测不一致确保 sim-to-real 时观测的是同一个坐标系目标向量要做归一化任务 reward 一直卡在 0目标空间太大且环境初始化过于随机先缩小随机范围或改用课程学习让初始目标离起点近一些用了 HER 但和普通 DDPG 没区别环境的状态空间不是多目标格式检查 obs 里是否含有 achieved_goalHER 没有可用重标记信号就会退化其中“目标样本占比过高”这个问题最隐蔽。重标记虽然增加了正样本但如果连原始目标为负的样本也被强制改成正样本智能体可能会忽略真正的任务目标只学习“追逐最近状态”的贪心策略。所以 p0.75 不是越高越好我个人建议 0.7~0.8 之间并且一定保留部分原始目标样本。还有一点HER 不能和 on-policy 算法一起用。因为重标记改变了目标分布和奖励再拿这种“篡改”后的数据去计算优势函数会破坏策略梯度估计的偏差。如果你想用 PPO 之类的算法那就要换一套思路比如 HER 只能用于 off-policy 的 DDPG、SAC、TD3。这也是新手经常搞混的地方我见过有人把 HER 塞进 PPO 的 rollout 里结果训练 loss 直接爆炸。4.2 几个容易忽视的设计细节首先是奖励阈值的设计。很多任务里 compute_reward 是基于距离的稀疏判定当 ||achieved_goal - desired_goal|| 某个阈值时给正奖励否则为0。阈值的选取直接影响 HER 的效果。阈值太大重标记的目标稍微接近一点就算成功学到的策略精度不高阈值太小重标记后仍然大量样本是0提升有限。我的经验是阈值不要低于机械臂本身的位置控制精度否则连仿真环境都会出现震荡。其次是目标空间是否需要归一化。当 achieved_goal 包含多个不同量纲的维度比如位置坐标和角度混合建议做归一化或者阈值分步判定。HER 重标记时会替换整个 goal 向量如果某些维度的数值范围差异过大Q 网络很难收敛。FetchReach 这类任务的 goal 是三维位置范围都是 [-1,1] 左右所以问题不明显。我自己在自定义环境里加入旋转角度后才意识到归一化有多重要。第三个细节是要合理设置 rollout 里的 episode 长度。HER 依赖轨迹中出现的状态多样性如果每次 episode 都因为超时而被打断未来状态集合不够丰富重标记的目标也就没什么价值。适当延长 episode 长度或者调整环境的时间步长能明显改善学习效果。4.3 从 HER 到更现代的后见之明变体HER 虽然经典但学术界和工业界并没有停在原地。后来的 Hindsight Goal GenerationHGG是一个自然的延伸它不只依赖轨迹中的未来状态还会额外学习一个目标生成器专门挑选当前价值函数最难以区分的边界状态作为新目标。这让目标分布更接近能力边界比 HER 的随机采样更有针对性但实现复杂度也高了不少。另外在离线强化学习里HER 的思路也被广泛借鉴。面对静态数据集我们无法继续交互采样但依然可以用后见之明的方式为失败轨迹重新标注目标从而扩充正样本。这种做法在机器人智能体从演示数据中学习技能时尤其常见。如果你已经掌握了 HER 的核心思想再去理解这些变体就会发现它们基本都在解决同一个问题如何从“没达到预期目标”的数据里榨取更多的学习信号。5. 实战案例复盘我如何用 HER 调通一个抓取任务5.1 任务描述与初始困境去年我重写一个桌面抓取仿真任务环境比较接近 FetchPickAndPlace。机械臂需要把桌面上的球抓起来放到一个目标盒里目标盒的位置每一轮随机生成。一开始我用 TD3 直接训练状态空间里包含机械臂关节角、末端坐标、物体坐标、目标盒坐标。奖励设置为只有成功把球放进目标盒才给 1其他情况都是 0。训练了 10 万步之后智能体依旧只会乱动连球都不会去接近。当时的 log 里 reward 几乎全是 0Q value 也是平平的。我意识到这就是典型的稀疏奖励问题于是决定引入 HER。因为环境已经提供了 achieved_goal物体坐标和末端坐标我只需要在采样时做目标重标记。重标记的目标我用物体未来位置和末端未来位置拼接成一个向量替代原来的 goal 向量。5.2 调参数的过程和收获第一轮实验我把 K 设为8p设为0.9发现策略开始朝着球移动但动作抖动得很厉害抓到球之后经常又甩出去。后来我意识到重标记样本里“未来状态”选得太远导致策略过度优化中间状态忽略了最终的放下目标。我把 K 降到4p降到0.7同时把目标判定阈值从0.05放宽到0.1这个阈值让重标记目标更容易产生正奖励学习信号更密。经过这一轮调整智能体在80万步左右成功率达到65%。之后我又给训练加了简单的课程策略最初让目标盒离球近一点成功率提升到85%后再开始随机放置。其实课程学习和 HER 可以共存前者降低探索难度后者提高样本利用效率两者叠加效果很好。5.3 从仿真到接近真实的一点心得仿真环境里 HER 好用不代表真实环境直接能捞。我在仿真中训练好的策略直接迁移到真实机械臂时发现由于相机标定误差实际观测到的物体位置会有误差导致重标记的目标和真实状态不一致。你必须在部署时重新标定观测和目标坐标系或者在 sim-to-real 中加入随机化。另外真实环境中一个 episode 的 length 往往比仿真更受限因为机械臂不能无限跑下去。HER 对轨迹长度和状态多样性有依赖所以真实场景里我更倾向于用 HER 来做预训练再用少量真实数据继续微调。这种方式比纯真机训练省时间得多。写在最后的一个小技巧如果你刚上手 HER我建议你第一件事不是去改网络结构而是打印一条重标记前后的 transition 看看原始 reward 是0重标记后 reward 变1这个变化必须和你的任务语义完全一致。很多 debug 半天的问题其实都是因为重标记的目标没有真正做到“该目标确实在该时间步被达到”。把这条逻辑想想清楚HER 的成功率就能立刻上一个台阶。
返回列表