ARTICLE DETAIL

资讯详情

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

HER实战:稀疏奖励强化学习的失败轨迹重标注指南

HER实战:稀疏奖励强化学习的失败轨迹重标注指南 如果你做过机器人控制或者游戏 AI 的强化学习训练大概率经历过这种绝望稀疏奖励环境下智能体在几十万步里一直原地打转奖励曲线像条死线loss 倒是正常下降但策略就是不产生任何有意义的动作。我一开始把锅甩给网络结构、学习率、探索噪声折腾了一个多月毫无起色。后来把 hindsight 这套思路——也就是 Hindsight Experience ReplayHER事后经验回放——加进训练管线才真正意识到问题不在优化器而在你怎么定义经验。我把这套基于 HER 的训练管线内部代号就叫 hindsight因为它本质上就是一套让智能体学会事后复盘的机制。这篇文章从一个实践者的角度把 HER 的原理、实现、调参和踩坑完整过一遍。适合刚接触目标条件化强化学习的同学也适合那些已经在跑 DDPG/SAC 但被稀疏奖励折磨到想放弃的同行。读完你至少能回答三个问题为什么失败的轨迹也有价值如何在代码里落地目标重标注HER 到底解决什么、不解决什么1. 先搞清楚HER 在解决什么问题1.1 稀疏奖励下的学习困境常规强化学习依赖奖励信号来提供学习方向。密集奖励环境下每一步都有一个数值告诉我们当前动作好不好策略网络可以沿着奖励梯度逐步优化。但很多真实任务——机械臂抓取、机器人推物体、导航到达——根本没有密集奖励可用。你只能设置一个二值奖励到达目标给 1否则给 0。这种设定最要命的地方在于智能体在绝大部分时间拿到的都是 0没有任何信号能告诉它你离目标近了一点。假设在某个状态下随机尝试一个动作恰好达到目标的概率是千分之一那么在没有额外引导的情况下要采到第一次成功经验期望步数就是一千步级别。当任务维度上升到机械臂的多关节控制时这个概率会指数级下降几百万步都碰不到一次成功是常态。我做过一个七自由度机械臂的抓取实验初始状态下机械臂距离目标物大概三十厘米随机策略的成功率约在万分之几的水平。前五十万步完全没有任何正反馈策略网络输出的动作几乎就是随机噪声的翻版。这个过程非常劝退但这也是 HER 类方法登场的最佳场景与其等待稀有的成功不如把失败重新解释成另一种成功。1.2 核心洞察失败轨迹里藏着大量成功经验HER 的想法来自 2017 年 Andrychowicz 等人发表的论文核心逻辑非常朴素一个 episode 的轨迹虽然没能达成我们预设的目标 G但它最终到达了某个状态 S_T。如果我们的目标是 S_T这条轨迹就是一条完美成功的轨迹。换句话说HER 本质上是事后换目标把原来那个够不着的目标替换成轨迹实际到达的状态然后重新计算整条轨迹的奖励。由于新目标是由轨迹自身生成的回放缓冲区里会出现大量成功样本智能体就能从这些样本里学到要达到这个状态应该走这样的动作序列。这个思路在人类经验里也完全成立。回想学投篮一开始怎么投都进不了但每投一次都能看到球落点离篮筐的远近下次就会微调出手角度。HER 相当于在强化学习里引入这种落点反馈——即使没进落点本身也是一次有价值的观测。你可以把它理解为一种自动化的课程学习只不过课程目标不是人为设计的而是从失败轨迹里长出来的。2. 原理拆解目标重标注为什么能work2.1 目标条件化怎么做表征要和 HER 配合策略网络必须是目标条件化的。也就是说网络的输入不只是当前观测 state而是 state 加上一个 goal 向量。决策过程变成给定当前状态和想要达到的目标输出动作。这就引出一个重要的结构设计问题goal 和 state 往往不是同一维度的东西。比如机械臂任务里state 是关节角度和速度goal 是目标物位置。你需要额外维护一个 achieved_goal 的概念——即根据当前状态推导出的、智能体实际所在的目标位置。这个映射必须确定且可复现否则重标注时无法一致地计算新奖励。常见的做法是在环境封装里提供一个 compute_achieved_goal(obs) 函数把观测映射成与 goal 同一空间下的向量。以 FetchReach 这类经典环境为例goal 是末端执行器的三维坐标achieved_goal 也是末端执行器的三维坐标奖励函数用两者欧氏距离是否小于阈值来判断成功。这个设计保持了目标空间的一致性后续重标注才有意义。2.2 四种目标选择策略怎么选HER 论文提出了四种从轨迹中挑选新目标的策略实际使用效果差异不小final直接用轨迹最后一个状态作为新目标。最简单但如果轨迹太长中间状态和新目标相差太远样本价值会被稀释。random从整条轨迹中随机挑一个状态。覆盖面广但可能挑到距离当前时刻很遥远的状态导致旧状态配新目标的时序混乱。future只从当前时刻之后的状态中挑选。保证动作序列能导向新目标时序逻辑最合理。episode从整条轨迹随机挑不限未来。实现最简单但训练稳定性稍差。我实测下来future 策略是综合最优的也是社区用得最多的默认选择。原因在于重标注的样本要能作为有效的状态-动作-下一状态-奖励四元组训练关键在于这个动作确实把状态从 A 带到了 B。如果新目标选在动作发生之前的状态那么这个动作对应的成功是错的会污染价值函数。提示如果任务时间步很短比如几十步以内四种策略差距不大。但一旦 episode 超过几百步务必使用 future。2.3 为什么样本效率能提升这么多从数学直觉上看HER 的效果是直接把缓冲区中成功样本的占比抬高了。假设随机策略下的原始成功率是 p一个 episode 有 T 步不做 HER 时成功样本占比就是 p。做了 HER 之后每个 episode 里那 k 条重标注样本全部变成成功缓冲区里正样本比例直接变成 k/(k1) 级别的量。更重要的是一条轨迹不只服务一个目标。同一条机械臂抓取轨迹可以为抓到红色方块原始目标提供失败样本为到达轨迹终点位置提供成功样本为途经点 1和途经点 2各提供一份成功样本。一个 episode 被重复使用多次信息密度成倍上升。这也是为什么 HER 在稀疏奖励且目标可达性尚可的任务里能比普通 off-policy 算法快一个数量级达到同样的成功率。必须强调一点HER 不解决探索问题。智能体如果永远只能到达空旷区域HER 教会的也只是如何在空旷区域移动到达各个点它不会主动让机械臂去碰那个从没碰过的物体。理解这一点能帮你避免对 HER 抱有不切实际的期望。3. 从零实现训练管线怎么改3.1 算法选型为什么必须是 off-policyHER 依赖经验回放天然要求 off-policy 算法。DDPG、TD3、SAC 都是合适的载体其中 SAC HER 的组合在连续控制任务里最稳兼具探索能力和样本效率。我在实际项目中基本只用 SAC HER很少再碰 DDPG。PPO 这类 on-policy 算法要慎用。原因有二其一on-policy 训练要求采样数据来自当前策略重标注后的样本虽然状态-动作对来自当前策略但目标被替换了等价于在另一个 MDP 下制造数据强行使用会引入分布偏差其二GAE 优势估计依赖完整 episode 和原始奖励序列重标注会破坏时间一致性收益估计失真。如果你确实想在 on-policy 框架里用事后思想可以考虑目标条件化的 PPO 配合奖励塑形但那就不是标准 HER 了效果往往打折。我的建议是别绕路直接上 SAC。3.2 回放缓冲区改造存储完整轨迹实现 HER 最核心的改动在回放缓冲区。普通 off-policy 算法只存 transition采样时随机抽四元组。HER 要求存储完整的 episode因为 future 策略需要从当前时刻之后的某个状态提取新目标。我采用的数据结构是两层一个 episode 缓冲队列存最近若干个完整轨迹采样时先从 episode 队列抽若干条轨迹再从每条轨迹内部抽 1 个原始 transition 和 k 个重标注 transition。这样既能保证重标注的时序信息完整又不至于让缓冲区的内存开销失控。具体实现上每个 transition 里除了 obs、action、reward、next_obs、done还要额外存 achieved_goal。注意重标注不需要在存储时完成而是采样时实时算。这样同一个 episode 可以被不同的新目标反复利用也方便随时切换目标选择策略内存效率更高。3.3 采样与重标注核心代码下面是采样和重标注的核心逻辑我用 Python 伪代码的形式给出关键步骤都做了注释可以直接迁移到你的项目里def choose_goal_index(t, episode, strategyfuture): 根据策略选择新目标的时刻索引 if strategy final: return len(episode) - 1 elif strategy random: return np.random.randint(len(episode)) elif strategy future: return np.random.randint(t 1, len(episode)) elif strategy episode: return np.random.randint(0, len(episode)) else: raise ValueError(funknown strategy: {strategy}) def relabel(transition, new_goal): 将 transition 的目标替换为 new_goal并重算奖励 obs, action, reward, next_obs, achieved_goal transition new_reward compute_reward(achieved_goal, new_goal) new_obs obs.copy() new_obs[goal] new_goal new_next_obs next_obs.copy() new_next_obs[goal] new_goal return (new_obs, action, new_reward, new_next_obs) def sample_batch(replay_buffer, batch_size, k4, strategyfuture): 从缓冲区采样一个 mini-batch包含原始样本和 HER 重标注样本 num_episodes batch_size // (k 1) episodes replay_buffer.sample_episodes(num_episodes) transitions [] for episode in episodes: t np.random.randint(len(episode)) transitions.append(episode[t]) # 保留原始目标样本 for _ in range(k): t2 choose_goal_index(t, episode, strategy) new_goal episode[t2].achieved_goal transitions.append(relabel(episode[t], new_goal)) return transitions这段代码有个细节容易被忽略重标注时new_goal 不仅替换了 obs 里的 goal 位也替换了 next_obs 里的 goal 位。因为目标条件化策略在所有时间步都接收目标输入如果只在 obs 里换、在 next_obs 里不换Q 网络看到的时序目标不一致训练直接崩掉。3.4 奖励计算与 done 标志的处理HER 的奖励函数必须可计算、可复算。最常用的是基于距离的阈值判断def compute_reward(achieved_goal, goal, threshold0.05): dist np.linalg.norm(achieved_goal - goal) return float(dist threshold)这里有两个坑。第一threshold 的选择要结合动作步长和控制频率。机械臂末端每步移动几厘米如果阈值设成 1 厘米可能几乎所有轨迹都会被判失败HER 也救不回来设太大又会让成功失去意义。我一般会把阈值调到单步最大位移的两到三倍左右具体值靠小规模实验摸。第二done 标志的处理要格外小心。原始过渡里 doneTrue 表示这条轨迹达成了原始目标或碰到终止条件。重标注之后新目标大概率在轨迹中途就已经达成因此重标注样本的 done 应该根据新目标在 next_state 时刻是否达成来重新计算而不是沿用原来的 done。很多开源实现在这点上偷懒结果就是价值函数被错误的目标终结信号反复污染。4. 调参经验与常见问题实录4.1 一套稳妥的默认超参数如果你不想反复试可以先从下面这组参数跑起我在多个任务上都验证过稳定性不错参数推荐值说明重标注数量 k4每个原始样本额外生成 4 条 HER 样本目标选择策略future从当前时刻之后选目标缓冲区容量1e6有条件尽量大保存更多完整 episode每 episode 采样数batch_size // 5保证原始样本占比 1/5critic 学习率3e-4比普通 SAC 略低防止重标注奖励波动带崩 Q 网络目标阈值 threshold单步位移的 2~3 倍需要在实验前粗估自动熵调节开启SAC 默认开启低温度加速收敛k 值的影响值得单独说。k 太小成功样本占比不够加速效果不明显k 太大原始目标样本被稀释智能体会过度偏向解释历史而忽略真正要完成的目标。社区默认 k4 是一个比较均衡的取值即原始样本与重标注样本比例为 1:4。4.2 训练初期 Q 值波动大怎么办这是我踩过最多次的坑。HER 重标注会产生大量意外成功样本比如机械臂乱甩时偶然让末端到达了某个位置这条轨迹被重标成成功轨迹后会给 critic 一个非常大的正反馈。如果 critic 学习率偏高Q 值会在几轮迭代里剧烈跳变policy 也跟着乱。解决办法有两个可以叠加使用。第一把 critic 学习率从常规的 3e-4 降到 1e-4 或更低让价值网络更慢地吸收那些偏激的样本。第二在奖励上做 clip比如把稀疏奖励限制在 [-1, 1] 区间避免个别大奖励主导梯度。我在项目里同时做了这两件事训练曲线明显平滑很多。另一个常见问题是目标空间不同维度的尺度不一致。比如 goal 的前两维是位置单位米量级 0.1后一维是角度单位弧度量级 3直接 concat 进网络会导致距离计算被大尺度维度主导。解决办法是对 goal 做独立归一化或者用带权距离函数计算奖励。4.3 什么情况别硬上 HERHER 不是万灵药下面这些场景我试过效果都很一般探索本身是瓶颈的任务。比如物体藏在封闭盒子里智能体根本观测不到HER 只能解释它看到的状态绕不过探索盲区。目标空间是高维连续空间且结构复杂。比如要从图像像素空间直接生成目标HER 重标注出来的目标过于杂乱策略学不到有用的语义此时需要先训练目标表征压缩网络。任务本身有密集奖励可用。既然每一步都有信号直接用原始奖励训练就好HER 反而会因为目标重标注引入不必要的非平稳性。我个人的体会是HER 最适合目标明确、状态可达、稀疏奖励的任务组合。把它想成一把专门针对稀疏奖励的扳手而不是万能螺丝刀用起来会顺手很多。4.4 和课程学习、数据增强的搭配技巧最后分享一个我实际项目里验证过的扩展思路。HER 和课程学习是可以串起来用的。标准做法是先让智能体在容易的目标集合上训练等成功率上来后再把目标难度提升。HER 在其中扮演的角色是当课程目标难度提升、成功率暂时掉下来时重标注机制保证掉下来的这段数据依然富含正样本训练不会因为课程切换而停滞。另一个好用的搭配是目标集数据增强。如果任务的目标物存在多个配色或尺寸可以把同一轨迹的 achieved_goal 做小幅扰动生成更多样化的重标注目标。这相当于在目标空间做正则化能明显提升策略在新目标上的泛化能力。我做过一个多物体抓取实验加了目标扰动后未见物体的抓取成功率提升了约 18%代价只是每步多一次采样计算。我在实际使用中还有一个习惯把 HER 的开关做成训练过程中的可配置项。前期探索阶段用大噪声 SAC 跑通基本动作中期开启 HER 加速目标收敛后期如果发现策略在少数目标上过拟合就临时增大 k 值把注意力拉回到多样化经验上。这种动态调度不是论文里的标准做法但实践中确实被我验证过有效。训练的本质是让数据说话HER 给了你一种重新解读数据的方式至于怎么解读、什么时候解读完全可以灵活一点。
返回列表