ARTICLE DETAIL

资讯详情

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

稀疏奖励难题如何破?HER事后经验回放核心原理与工程实践全解

稀疏奖励难题如何破?HER事后经验回放核心原理与工程实践全解 1. hindsight的两种指认从“事后聪明”到算法命名做强化学习这几年我越来越觉得 hindsight 这个词比很多华丽术语都更能戳中我们做无模型算法时的痛点。它原意是“事后聪明”也就是人们常说的“事后诸葛亮”——事情发生之后谁都能讲出一套“我当时早知道会这样”的话。但在我们这行hindsight 还有另一个更硬核的指向OpenAI 在 2017 年提出的 Hindsight Experience Replay事后经验回放简称 HER。这个算法可以说是我个人心目中“稀疏奖励场景下最值得先试一把”的基线方法之一。我第一次接触 HER 是在做机械臂推物块任务的时候。仿真环境里一个方块摆在桌上机械臂要从某个初始位置把它推到目标位置。目标位置随机生成但问题在于目标成功的判定非常苛刻——方块中心点与目标点距离小于某个阈值才算成功。这意味着绝大多数 episode 里agent 从头到尾都拿不到一次正奖励。用 DQN 跑几百个 episode 下来Q 值几乎没有有效梯度整个训练就像在黑夜里面闭着眼睛摸路。后来我把 HER 接进去效果立竿见影训练曲线终于开始有了变化。如果你也被“训练半天 loss 不降、reward 恒为零”折磨过或者正准备做一个目标条件强化学习项目这篇文章值得你读完。我会把它背后的设计逻辑、实现细节、超参选择、工程坑位全部讲一遍最后附上一些我实测下来的经验供你直接抄作业。2. 为什么稀疏奖励会让 DQN、DDPG、SAC 集体失效2.1 稀疏奖励的本质不是“没有反馈”而是“反馈几乎永远不来”很多人刚接触强化学习时会把稀疏奖励简单理解成“reward 函数设计得不够好”似乎加个 shaped reward 就能解决。这个理解不能说错但没有触及问题的本质。在稀疏奖励设定下agent 面临的不只是“信号弱”而是“探索空间里成功轨迹的测度几乎为零”。我们用 Bit Flipping 这个经典 toy task 来说明。假设一个 10 位二进制向量初始为全 0目标 g 是一个随机 10 位向量。每一步可以翻转其中一位。只有当当前向量与 g 完全相等时reward 才为 1否则一律为 0。这个任务看起来简单但用随机策略去试想要恰好翻到目标状态概率是 2^10 分之一也就是大约千分之一。如果把位数加到 20 位概率直接降到百万分之一以下。绝大多数随机探索的 episode 里agent 连“靠近目标”这种渐进反馈都感受不到因为 reward 只在“精确命中”时出现。这种情况下基于时序差分学习的算法会出什么问题核心问题在于所有“未成功”的轨迹在奖励信号上完全等价。agent 学到的是一个几乎处处为零的 Q 函数或者说它根本无法区分“离目标已经很近”和“完全偏离方向”这两种状态。从梯度角度看有效样本太少方差太大训练基本是原地踏步。很多人误以为加大探索噪声就行实际测试你会发现要么探索到天荒地老要么好不容易碰到一次成功又因为经验回放里正样本比例过低瞬间被大量零奖励样本淹没。2.2 人类思维里的“事后聪明”为什么对算法有价值这里就需要引入 hindsight 这个概念的灵感来源了。我们人类在学习一项任务时其实有一种非常原始的学习机制做一件事失败了我们不会简单地把整段经历丢弃而是会回头看看“既然已经到了这里那么‘这里’能不能被我利用起来”。举个生活化的例子。你第一次学做菜想炒一份“青椒肉丝”结果火候没控制好肉炒老了青椒也软塌塌的。如果严格用“目标达成”来评判这顿饭是失败的。但你不会认为这段经历毫无价值你会告诉自己至少我知道了“火开太大、肉丝提前下锅”会导致什么结果下次我用同样的流程做一份“软炒肉丝”可能就成了。换句话说你通过“事后改写目标”把一次失败经历转换成了可用于训练的正面样本。HER 算法做的就是这件事——只不过它是让机器自动完成目标改写。一条轨迹没有达到预定目标 g但一定达到了某个实际状态 g。那么为什么不把这条轨迹重新标记成“目标是 g”的轨迹呢这样原本稀疏的奖励瞬间就变成了稠密信号因为轨迹的最后一步必然成功到达了 g最后一步的 reward 必然为 1。这个思想的精妙之处在于它没有改变任务本身也没有给环境增加人造的中间奖励而是通过改写经验回放里的目标标签让 agent 从“失败轨迹”中提取出“部分成功”的结构。学术上管这叫“relabeling”中文翻译成“重标记”。我个人更喜欢把它理解成重新定义问题让已发生的轨迹在某个新问题下成为最优解的一部分。3. HER 核心机制拆解重标记到底是怎么运作的3.1 从一条失败轨迹说起重写的不是答案是题目假设你有一个目标条件任务原始目标记作 g。agent 与环境交互一个 episode产生一条轨迹 τ (s_0, a_0, s_1, a_1, ..., s_T)。这条轨迹的原始奖励序列可能全是 0。现在 HER 要做的事情就是选择一个新的目标 g然后用 g 重新计算这条轨迹里每一步的奖励。具体流程可以拆成四步第一步按某个策略从当前轨迹中选出一个新目标 g。这个 g 必须是轨迹里实际访问过的某个状态通常是某个时间步的状态 s_t。第二步对于轨迹中的每个状态-动作对 (s_t, a_t)用新目标 g 重新计算奖励 rt reward_fn(s{t1}, g)。这里有个关键约束reward_fn 必须是“可以用目标作为输入直接计算”的函数。这也是为什么 HER 天然适合目标是“某个位置坐标”“某个物体位姿”“某个向量状态”这类结构化目标的任务而不是抽象语义目标。第三步把重新标记过的四元组 (s_t, g, a_t, rt, s{t1}, g) 作为一个新的经验样本存进回放缓冲池。第四步正常训练时原始的“未重标记”样本和“重标记后”的样本一起参与梯度更新。通常的做法是每条轨迹除了保留原来的一个样本序列之外还会额外生成 K 条重标记后的轨迹序列。K 一般取 4 到 8。这里最容易让新手迷糊的地方是重标记后输入给策略网络和目标网络的“目标”也变了。原来目标是 g模型学的是“在目标 g 下怎么做”重标记后目标变成了 g模型学的是“在目标 g 下怎么做”。同一批状态-动作数据在一个新问题的语境下被重新解读这正是 HER 能把失败经验“变废为宝”的原因。3.2 四种目标重采样策略对比final、future、episode、randomHER 论文里比较过四种从轨迹中选择新目标 g 的方式。我直接给结论和我的使用倾向。策略名称采样规则特点我的推荐度final直接取轨迹最后一个状态 s_T 作为新目标最简单最容易实现但只利用了一个状态点样本多样性偏低可作为快速上手的默认选项future对轨迹中每个时间步 t均匀采样一个未来时刻 t ∈ [t, T]取 s_{t} 作为新目标多样性最好每个时间步都有不同的“后续成功状态”学习效率最高论文里也是推荐方案强烈推荐作为首选episode从整条轨迹的任意状态中等概率采样一个 s_t比 final 多样但没有考虑时间先后关系可能导致“让过去的动作去解释未来的成功”逻辑稍弱一般作为对照实验可选random从所有已访问过的经验状态中随机采样几乎不保证“可达性”样本里会出现很多当前状态下根本够不着的目标训练时梯度冲突严重不推荐单独使用很多人第一次看到 future 策略时会产生一个疑惑如果我们用未来某个状态作为当前状态的新目标那不等于让 agent“预测未来”吗这不是泄露了未来信息吗注意这里的关键在于重标记后的样本并没有要求 agent“根据当前状态预测未来”而是要让 agent 学习“从当前状态出发如何到达那个未来状态”。这正是目标条件策略学习的基本设定给定当前状态和期望目标输出对应的动作。future 策略提供的样本恰恰是一组“当前状态 一个实际可达目标”的组合比 random 策略更符合“可学习”的要求。从数学上讲future 策略天然引入了“目标与状态之间的时间距离”信息相当于给每个状态-动作对分配了一个分布上更合理的可达目标。论文实验也验证了在大多数 gridworld、Bit Flipping、机械臂推动等任务上future 策略的收敛速度和最终成功率都优于 final 和 episode。3.3 为什么“重标记”能解决稀疏奖励问题一个直观解释为了让你彻底明白 HER 为什么有效我用 Bit Flipping 再做一个推演。假设当前状态 s 0000000000目标 g 0000010000。agent 随机翻转翻了很多步之后可能到达一个状态 s_T 0001010000。按原始目标看这个轨迹零奖励毫无用处。如果用 future 策略重标记我们会从这条轨迹中选若干个中间状态比如 s_{t1} 0000010000、s_{t2} 0001010000 等。对于 s_{t1}路径中会包含“如何从某个特定位翻转到目标位”的精确样本而且这个样本的最后一个动作之后状态恰好等于新目标reward 1。于是一条原本没有正奖励的轨迹被拆分成了多条带有“能够达成目标”信息的经验。agent 在这些新增经验上学习相当于获得了一个“从失败中提取局部成功”的课程。这个过程反复进行之后回放缓冲池里的正样本密度大幅提升TD 误差不再是普遍为零的状态Q 网络终于有了学习所需的信号梯度。这就是为什么 HER 在稀疏奖励任务里往往比单纯调大探索噪声、加奖励塑形都更管用。4. 手把手实现 HER伪代码、参数选择与工程落地4.1 一条完整轨迹的重标记流程切片下面是一段可以照抄到项目里的伪代码我按“单条 trajectory 处理”的粒度来写def relabel_trajectory(trajectory, original_goal, reward_fn, relabel_strategyfuture, K4): # trajectory: list of (state, action, reward, next_state, done) # original_goal: 本 episode 的原始目标 relabeled_samples [] T len(trajectory) states [t[0] for t in trajectory] actions [t[1] for t in trajectory] next_states [t[3] for t in trajectory] for t in range(T): # 按策略选择新目标 if relabel_strategy final: new_goal states[-1] elif relabel_strategy future: t_prime random.randint(t, T - 1) new_goal states[t_prime] elif relabel_strategy episode: t_prime random.randint(0, T - 1) new_goal states[t_prime] elif relabel_strategy random: new_goal random.choice(all_reached_states) new_reward reward_fn(next_states[t], new_goal) relabeled_samples.append( (states[t], actions[t], new_reward, next_states[t], new_goal) ) # 每条原始轨迹只保留 K 条额外重标记轨迹的容量 # 实际实现时常把整条轨迹切片成大列表存入 bufferK 决定占比 return relabeled_samples需要说明的是上面的代码是示意性的实际工程中你不会逐条生成 K 条轨迹而是把重标记产生的四元组批量加入经验池再通过采样比例控制 K 的效果。实现层面我建议把原始样本和新样本都放进去然后统一用同一个优先经验回放或普通随机回放来采样。注意重标记样本的 next_state 之后输入网络的目标字段也要替换成 new_goal这一步容易漏漏了之后整个训练目标就错乱了。4.2 训练循环里 HER 和其他算法的组装顺序HER 本身不是一个完整的强化学习算法而是一个经验回放层面的“数据增强”技巧。它可以和任何 off-policy 算法搭配最经典的是 DDPG后来大家也把它接到 SAC、TD3、DQN 上。我这边实际验证比较多的是 SAC HER 的组合效果稳定调参相对省心。在训练循环中HER 的介入时机是在“收集完一条轨迹”之后、“往 replay buffer 里塞数据”之前。伪代码顺序如下for episode in range(num_episodes): trajectory run_episode(agent, env, goal) original_samples encode_trajectory(trajectory, goal) relabeled_samples relabel_trajectory(trajectory, goal, reward_fn) replay_buffer.add(original_samples) replay_buffer.add(relabeled_samples) for update_step in range(updates_per_episode): batch replay_buffer.sample(batch_size) agent.update(batch)我一般把每条轨迹的重标记目标数量控制为原始轨迹的 4 倍也就是 K4然后在 sample batch 时不区分原始样本和重标记样本让它们按自然比例混在一起。实践下来这个设置比单独维护两个 buffer、按比例强制混合的效果更省事训练曲线也更平滑。4.3 关键参数怎么设K 值、目标空间维度、buffer 容量很多人会把注意力集中到算法本身忽略了 HER 对“目标空间度量方式”的敏感度。我总结三个最值得调的点第一K 值不宜过大。K 代表每条轨迹额外生成的重标记轨迹数。K 太小正样本增量不足稀疏奖励问题缓解不明显K 太大重标记样本会逐渐淹没原始样本导致 agent 在“重标记问题分布”上过拟合真实目标下的表现反而下降。我实测下来K4 是一个几乎不需要犹豫的默认值但如果你发现原始目标下的成功率上不去可以试试 K8 或 K2观察哪个方向有改善。注意这里的 K 不是翻倍涨就好我见过有人把 K 设到 32结果训练出来的策略在真实目标下几乎全失败——因为经验池里绝大多数样本都是“事后编造”的目标真实目标的分布反而被边缘化了。第二目标空间的设计比算法本身更重要。HER 的重标记逻辑默认目标空间和状态空间至少是强相关的。如果目标是一个抽象的离散索引比如任务编号或者是一个高维图像重标记后的样本很难带来有效的梯度信息。我建议你在做目标表征时尽量让目标向量处于一个连续、低维、距离有意义的空间。例如机械臂任务里用物体中心坐标作为目标而不是用“物体类别 ID”导航任务里用二维坐标作为目标而不是用“房间编号”。还有一点状态和目标最好做归一化尤其是不同维度量级差很大时比如坐标在 0~1 之间但角度是弧度制训练会省心很多。第三replay buffer 的容量要足够大。因为 HER 会把每条轨迹复制成多份如果 buffer 太小重标记后的样本会频繁覆盖早期数据造成训练不稳定。我通常把 buffer 容量设为普通任务的 2 到 4 倍至少能存下最近 20 万到 50 万条四元组。这个数字听起来大但在 GPU 训练下其实内存占用完全可以接受。5. 实践中真正会踩的坑和排查实录5.1 问题一HER 在目标空间过大时反而震荡前面说了 HER 能缓解稀疏奖励问题但它不是银弹。当你任务的目标空间维度很高、而且不同目标对应的最优策略差异巨大时HER 会表现出明显的训练震荡。我做过一个多指机械手翻转物体的任务目标是最终的物体位姿位置 四元数7 维。教训很直接7 维目标空间里future 策略采样出来的“可达目标”虽然物理上可达但不同目标之间的动作差异可能非常大共享一个策略网络后梯度方向互相打架loss 曲线来回震荡成功率一直上不去。遇到这种情况我的处理思路是降低目标的“有效维度”。需要明确一点并不是所有维度都需要通过重标记来学习。比如位姿目标里位置坐标可以重标记但朝向角度往往和具体动作耦合太深直接重标记反而引入噪声。我在实验里把目标拆成“主要目标 次要目标”只对主要目标做 HER次要目标用课程学习去逐渐逼近。这个方法不敢说最先进但在我的多指操作任务上确实比全目标空间重标记要稳定得多。5.2 问题二奖励函数泄露“未来信息”导致训练崩溃这个坑非常隐蔽。HER 重标记时要求 reward_fn 只依赖 next_state 和新目标不能依赖轨迹的其他信息。但很多人图省事会把奖励函数写成“如果这一整条轨迹的最终状态接近目标就奖励 1”或者用“当前 step 之后所有步的累计距离”来计算 shaped reward。这种设计在普通训练里可能没问题一旦叠加 HER就会产生严重后果重标记后的四元组里next_state 其实并没有真正达到新目标但 reward_fn 因为看到了未来信息错误地给了正奖励。agent 学到的是“我随便做一个动作也能得到奖励”的错觉训练直接崩溃。我排查这个问题的经验是写完 reward_fn 之后单独写一个单元测试随机生成一条轨迹分别用原始目标和重标记目标计算每一步的奖励检查奖励只取决于 (s_t, a_t, s_{t1}, g) 这四个变量。任何一丝“越权访问”都可能让你浪费好几个星期的训练时间。5.3 问题三重标记目标分布偏移如何缓解HER 通过重标记改变了训练时的目标分布但训练结束后我们真正关心的是原始目标分布下的表现。这两者之间的分布偏移是 HER 的老毛病。常见表现是训练过程看起来非常顺利重标记目标下的成功率很高但一换到随机新目标策略立刻拉胯。缓解这个问题的思路是在训练循环里保留一部分“纯净的原始目标经验”。实际操作上我有两个习惯一是保证原始样本不重标记且采样权重不要被人为压低二是定期在原始目标分布下做 evaluation而不是只盯着训练 loss。如果发现 eval 成功率曲线和训练成功率曲线之间缺口扩大就需要降低 K 值或者增加原始样本的采样权重。还有一种高级玩法是把 HER 和 prioritized experience replay 结合让缓冲区里那些“对原始目标更有信息量”的样本获得更高优先级。这个我在部分任务上试过提升不能说特别明显但在目标分布差异大的场景下确实能缓解偏移问题。注意优先级计算本身也要基于 TD 误差如果 reward 本身因为重标记而变得非常稠密TD 误差会普遍偏小这时要小心优先级区分度不够的情况。6. 从仿真到真实机器人HER 的进阶扩展与工程思考6.1 典型任务里的参数迁移经验我在机械臂推块、抓取、开门三类典型任务上都跑过 HER 的 baseline。推块任务最简单目标就是二维坐标直接用 SAC HERK4future 策略大概 500 个 episode 就能看到明显的成功率抬升。抓取任务的难度上升了一个台阶因为目标空间不仅有末端位置还有物体是否被夹住、夹持姿态等离散维度。我的经验是把目标拆成“位置目标”和“姿态目标”两部分位置目标用 HER 重标记姿态目标作为额外条件靠 reward shaping 去辅助学习。直接对高维混合目标做 HER 往往不如拆开做。开门任务是我测试过最贴近真实部署的场景。门把手位置是固定但带有微小扰动的目标是门开的角度。这一类任务有个工程细节重标记时千万不要使用整个门开角轨迹的全部状态作为目标池因为门开角度一旦超过某个阈值机械臂的动作空间会发生功能性变化比如需要换握法强行把后续状态作为当前目标会让策略学到不连贯的行为。6.2 与课程学习、行为克隆叠加时最容易犯的错HER 可以和课程学习叠加也可以先收集少量人类演示再用行为克隆做预训练。我自己试过的组合是“行为克隆预训练 SAC/HER 微调”。这里有个容易犯的错预训练阶段用真实任务目标微调阶段接入 HER 后重标记目标的分布和预训练分布差异太大导致行为克隆学到的先验知识被快速破坏。解决方法是在微调初期冻结策略网络前几层或者降低 HER 样本的采样权重等策略逐渐适应之后再放开。这个方法没有论文依据纯粹是我踩坑踩出来的工程经验但在没有更好方案之前我会一直沿用。另一个值得说的组合是 HER 优先级采样。优先级采样本身会让高频 TD 误差的样本被反复训练但 HER 重标记样本的 TD 误差天然比较小容易被优先级采样忽略这就抵消了 HER 增加正样本密度的优势。我的做法是分两个 buffer一个存原始样本一个存重标记样本训练时按比例从两个 buffer 里各采一半。这样既保留了重标记样本的多样性也能利用优先经验回放聚焦在难样本上。6.3 同类方法横评HER 和 hindsight 家族后来者HER 之后社区里出现了不少“事后反思”类的方法。我关注过的有 hindsight policy gradientHPG、VHE视觉 hindsight 经验回放、以及把 HER 用在模型预测控制里的思路。它们共同的思想原点都一样“在目标条件框架下通过后验信息重写一个更可达的目标”。HPG 的思路是把 HER 从 off-policy 扩展到 on-policy 策略梯度里因为原始 HER 依赖经验回放没法直接用在 PPO 这种 on-policy 算法上。VHE 则是针对图像目标用特征空间做重标记。如果你做的是机器人视觉抓取目标本身是图像块那 VHE 会比 HER 更合适。但如果你只是想快速验证“HER 在我的任务上到底有没有效果”我建议还是先把状态空间和目标任务定义好暂时不要引入视觉表征可视化排查会容易得多。7. 一点个人体会作为收尾从第一次在 Bit Flipping 上复现 HER 到现在我越来越觉得这个算法的价值不只是“解决稀疏奖励”而是给了我们一种看待失败数据的方式训练数据里那些“没达成原始目标”的轨迹并不是垃圾它们只是“在另一个目标下的成功样本”。做强化学习项目时很多人习惯把注意力放在调 reward、调网络结构上却忽略了经验回放本身就是一个可以大做文章的数据分布塑造环节。HER 只是其中一个技巧真正值得学习的是“如何重新解读已有数据”的思维方式。最后再分享一个小技巧无论你用哪种重标记策略训练开始前一定要先打印几条重标记样本人工检查一下“重新计算出来的奖励是否符合直觉”。这一步只需要几分钟但能避免很多后期难以定位的隐性 bug。希望这篇文章能帮你在自己的任务里少走几步弯路。
返回列表