ARTICLE DETAIL

资讯详情

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

Hindsight三重解读:强化学习HER、机器人操控与决策偏差

Hindsight三重解读:强化学习HER、机器人操控与决策偏差 从“hindsight”这个词展开不同背景的人会想到完全不同的东西。做强化学习的想到的是Hindsight Experience Replay事后经验回放做机器人的想到的是Meta开源的Hindsight视觉操控系统做产品和战略的想到的是后见之明偏差hindsight bias。有意思的是这三条线在“以终为始”这个核心理念上是完全打通的。这篇文章就把这三层一起拆开从算法原理讲到工程实操再延伸到产品决策里的思维陷阱最后附上我从实验中挖出来的那些坑。1. 事后经验回放HER把失败重新定义成成功1.1 稀疏奖励问题到底有多难先说一个我在强化学习里看了无数次的现象你写了个智能体去控制机械臂抓物体模拟器都搭好了网络结构也调得差不多了结果训练了好几个小时奖励曲线纹丝不动。你检查reward、检查log、检查每个state是否合法都觉得没问题但智能体就是什么都学不会。问题往往不在实现细节而是出在稀疏奖励sparse reward上。机械臂推物体这个任务如果设定是“物体到达目标位置才给reward1否则一律0”那么在一万个step里智能体大概有9990步拿到的都是0。它完全没有梯度信号看不到自己哪个动作离目标更近只能靠随机探索去碰那个几乎不可能碰到的目标点。指望一只瞎猫碰到活耗子的概率基本等于用随机策略跑出连续N步完美轨迹这种概率在状态空间稍微大一点的时候就是天文数字。传统的解决办法无非这么几种设计密集奖励dense reward比如用距离变化量作为每一步的reward用课程学习curriculum learning从简单任务过渡到难任务或者用更好的探索策略比如ICM、RND。这些方法都有各自的代价。密集奖励需要大量的任务定制和调参换个任务就得重新设计一次而且容易让智能体钻“reward hacking”的空子。课程学习的课程序列本身就需要大量人工设计。探索策略则没有从根本上解决“样本利用率低”和“回放经验缺乏有效学习信号”的问题。我当时的需求很简单要在尽量不改任务、不写复杂reward的情况下让一个稀疏奖励的场景能跑起来。这时候注意到了一个思路很反直觉的算法就是Hindsight Experience ReplayHER它的玩法和前面那些都不一样。1.2 HER的核心机制事后目标重标注HER的思路一句话就能概括过去失败的trajectory换个目标来看就是成功的。比如你让机器人推一个杯子到A点结果它推出了好远的轨迹最后杯子停在B点。从“目标A点”来看这条轨迹完全失败但如果把目标重新定义为B点那这条轨迹就是一条完美执行的成功轨迹因为它的终点就是目标点。于是这条轨迹从“废数据”变成了一条附带正向奖励的有效经验。具体的实现流程也很清晰。强化学习agent在环境中跑episode时会存下来一条完整的轨迹数据包括每一步的state、action、reward、next_state、goal。传统做法是原封不动地存入replay buffer然后抽样训练。HER的做法是在每条轨迹结束后以某个概率通常0.5左右额外生成一条虚拟轨迹随机选一个“事后目标”通常是这段轨迹最终达到的状态或者n步之后达到的状态然后把原始轨迹里的goal全部替换成这个事后目标奖励也相应地重新计算一遍。因为新目标就是轨迹实际到达的地方所以这条虚拟轨迹里每一步的reward都变成了有效信号尤其是终点附近会有明显的正奖励。换句话说HER用“重新设定目标”的方式把原本稀疏的奖励信号变得极其稠密。这种做法的厉害之处在于它不改变任务本身也不改变奖励函数只是改变回放数据的“视角”。训练的时候从buffer里同时采样原有经验和新生成的“事后经验”网络就能在这些相对容易达成的目标上先学会“怎么让状态发生改变”然后逐步逼近真正的目标。我当时在二维导航任务上这个bool reward到达目标给1否则0的稀疏设定下验证普通DQN跑了5万步reward还是0加了HER之后3万步左右就能稳定收敛。这种对比非常直观HER不是改善了探索而是显著改善了对已有数据的利用效率。1.3 目标重标注的采样策略HER看似简单但里面有比想象多的细节尤其是“事后目标从哪采”这一步直接决定了最终效果。我在实验里试过几种不同的策略和论文里对比的结果基本一致。第一种是直接把episode的最终状态当作事后目标这种最简单逻辑上也最符合“事后怎么都能圆”的思路但对那些“绕远路”的轨迹来说它会产生一个偏差因为真正有用的轨迹不一定要跑完全程才能学。第二种是从轨迹剩余部分的k步后采样论文中称之为future策略这种通常效果更好因为它在“轨迹正在往某个方向发展”的过程中采样目标让agent能学到更细粒度的时间关联。第三种是混合策略随机选择episode最终状态或者未来的某个中间状态。从我的实际测试来看设定为future策略、k值取轨迹剩余长度的1/4左右效果比较合理太远了会退化成最终状态采样太近了目标变动太小对学习帮助有限。还有一个重要的超参数是“替换目标的概率”论文推荐0.5我实测下来0.3到0.5之间差别不大但超过0.8之后效果明显下降。原因也不难理解如果replay buffer里全是“事后目标”重写过的轨迹那原始目标对应的真实任务就会被稀释agent对真正的goal分布反而不敏感了。所以保持“真实目标经验”和“事后目标经验”在buffer里大致均衡是平稳训练的前提。还有一个容易被忽视的点HER对goal的形式有要求。如果goal直接就是state的一部分那用“最终状态”做新目标非常自然但如果goal是抽象的、与state不是同一个空间比如“走到某个颜色区域”这种语义目标就不能简单用最终状态替换。更一般的做法是维护一个或多个goal representation空间把state投影到goal空间之后再替换。也就是说用HER之前先想清楚goal的表示是什么以及新目标能不能被“看到”。2. 用HER训出一个“会推杯子”的智能体实操记录2.1 环境与代码框架搭建纸上谈兵差不多够了直接进入实操环节。我用的是一个简化的二维平面机器人推杯子任务类似OpenAI Gym的FetchSlide或自定义的PointEnv目标是一个圆形的目标点机械臂末端是球形任务是推一个方块到目标点。这个环境的好处是状态空间低维、可视化简单、训练速度快方便观察算法行为。先定义环境。state是3维向量物体位置(x,y)、速度(vx,vy)goal是2维向量目标点坐标action是{左、右、前、后、停止}四维的离散动作或者连续动作reward用稀疏方式设计def compute_reward(achieved_goal, desired_goal): distance np.linalg.norm(achieved_goal - desired_goal) return float(distance 0.15) # 达到阈值给1否则给0这里0.15是目标判定半径半径越小任务越硬但HER仍然可以处理只是训练曲线会更偏后段陡峭。接着写网络和训练循环。我用了Double DQN作为基础学习器神经网络是简单的三层MLP隐藏层各256个节点ReLU激活Adam优化器学习率1e-3。Replay Buffer用一个容量100万的循环队列。训练循环的伪代码如下for episode in range(MAX_EPISODES): trajectory [] obs env.reset() goal env.goal # 目标位置 while not done: obs_flat concat(obs, goal) action agent.act(obs_flat, epsepsilon) next_obs, reward, done, info env.step(action) trajectory.append((obs, action, reward, next_obs, done)) obs next_obs # HER以0.5的概率重写目标 if np.random.rand() 0.5: # 从未来状态里采样k步后的状态作为新目标 k 50 new_goal trajectory[-k][3][:2] # 取轨迹中某步的next_obs位置 for trans in trajectory: new_obs concat(trans[0], new_goal) new_next_obs concat(trans[3], new_goal) new_reward compute_reward(new_next_obs[:2], new_goal) buffer.add((new_obs, trans[1], new_reward, new_next_obs, trans[4])) else: # 原始轨迹照常存入 for trans in trajectory: obs_flat concat(trans[0], goal) next_flat concat(trans[3], goal) buffer.add((obs_flat, trans[1], trans[2], next_flat, trans[4])) # 每10步训练一次每次采样128 train_agent_on_buffer(buffer)在这个代码里有一个容易被忽略的细节当我把轨迹的goal替换成新goal之后不仅original_step的obs里拼接的goal要换成新目标奖励也要用新目标重新算一遍而且next_obs里同样要拼接新目标。如果只改了obs里的goal而没改next_obs里的goal网络会学到“state和goal的拼接在下一个时刻突然变了”导致严重的训练不稳定。2.2 训练曲线观察与参数敏感性训练过程我记录了一个三路对比一条是纯DQN一条是DQNHER替换率0.5一条是DQNHER替换率0.9。结果大致在意料之中。纯DQN在10万episodes内几乎学不到任何东西最终成功率小于5%。DQNHER0.5大概在第3万episodes时成功率开始突破20%第6万episodes时稳定在80%以上。DQNHER0.9早期学习速度很快但最终成功率只停在60%左右证明了我之前说的“真实目标被稀释”的问题。我还要专门试了一下k值的影响。k1时学习速度特别慢因为事后目标只取未来1步目标太接近当前状态给不出足够的学习信号k50时效果最好k200时稍微变慢但差距不大k500超过轨迹长度的一半时效果明显变差基本退化成了最终状态采样。这里值得注意的是HER并不完全替代高水平的探索机制。如果智能体完全不移动什么轨迹都不产生HER就只能重写毫无变化的轨迹也学不出什么。所以动作选择里保留一定的\varepsilon-贪心探索还是有必要的。在我这个场景里epsilon从0.4线性衰减到0.05衰减速度为每5000episodes降0.01效果不错。另外网络结构也不是完全无脑加宽就好。我在256维MLP上试过推到512维训练速度反而略微下降参数量大了、采样效率没跟上而缩小到128维高评价指标明显下降。对低维连续状态来说256维是一个性价比很高的折中。2.3 可视化调试的经验搞强化学习的日常免不了盯着训练曲线看半天但我强烈建议在这个基础上再叠加一层“目标方向可视化”也就是在环境里把每个episode的goal和achieved goal画一条连线再把agent看到的obs包括拼接的goal的部分维度打点。这样你就能直观看到HER是否在学习“朝目标方向逼近”。我第一次跑HER的时候发现一个奇怪的现象成功率明明已经90%以上了但可视化里的轨迹仍然歪歪扭扭并不像规划出来的路径。后来才意识到agent学到的不是“最优地走直线”而是“只要最终能到达目标附近就行”。这个现象要想清楚HER天然允许走弯路因为它不惩罚路径长度只要到达就算成功。如果你的任务要求最短路径HER需要叠加一个路径长度容忍项或者在replay buffer里保留更高质量的轨迹比如人类示范轨迹。3. 从算法到系统Meta Hindsight的视觉操控方案3.1 用“逆向演示”教机器人干活同样是hindsight这个词在机器人社区里还对应着另一套有趣的技术Meta AI开源过的Hindsight系统。它不是强化学习算法而是一个完整的机器人学习系统通过RGB摄像头拍摄人类演示操作让机器人学习如何完成任务。Hindsight这个名字在这里的含义是“事后回顾”——系统不是从初始状态出发预测未来而是从目标状态出发反向推演过去。机器人观察人类示范的完整操作过程包括手臂运动、手掌位置、物体状态变化然后构建出“从目标到初始状态”的逆向轨迹预测模型。在推理阶段机器人看到当前状态会在“逆向轨迹”上匹配最接近的状态依次回溯执行对应的动作从而完成任务。这套思路和HER有明显的神似之处都是把“终点”当学习的锚点。区别在于HER是在奖励信号的层面重写经验而Hindsight是在运动轨迹的层面倒推动作序列。后者更贴近真实物理世界的约束要考虑碰撞、摩擦力、关节限位等一堆控制层面的问题。我个人的理解是把Hindsight当作一个“轨迹归因控制”的组合系统会更合适。它算出达到目标需要经过哪些中间状态再通过闭环控制逐步逼近这些中间状态。因为有了明确的目标点和中间点稀疏奖励问题也被间接绕过了——每个中间状态都是一个子目标相当于自动构建了一条密集奖励的课程链。3.2 视觉感知与闭环修正不可忽视的细节在Hindsight这类系统里视觉感知的准确度直接决定成败。摄像头标定如果出偏差机器人看到的“物体位置”和真实位置差几厘米学习的轨迹再完美也没有用。我建议任何人在复现这类系统时第一件事不是调网络而是用棋盘格标定摄像头到机器人基座的坐标变换确认重投影误差在毫米级以下。还有姿态估计的鲁棒性。如果物体遮挡、光照变化、或者目标物体是镜子之类的高反光材质视觉模型很容易丢失跟踪。常见的应对方案是用多视角摄像头做交叉验证或者在时序上做平滑滤波。我当时测试一个简单的抓取任务时发现光照一变准确率掉到七成以下后来在预处理里加了直方图均衡恢复到九成以上。这类小技巧在论文里不会写但实际项目里很救命。闭环修正则是另一个关键。逆向轨迹给出的是“手应该到哪里”的期望但如果机械臂的控制器是开环的实际执行路径会不断累积误差最后和目标点差一大截。我一般会在每个控制周期比如50Hz做一次视觉反馈的位姿修正用PID或者简单的比例控制把误差拉回来。强烈的建议是不要把视觉模型和运动控制做成两个完全独立的模块而是让控制层可以读取视觉的不确定性在置信度低的时候自动降低移动速度。3.3 应用场景的边界在哪里Hindsight最适合的任务类型是“多功能固定场景中的重复操作”例如桌面垃圾分类、流水线零件分拣、家庭场景中的倒水或开关抽屉。它不需要海量数据因为人类示范就是数据而且逆向推理本身就提供了隐式的奖励信号这点在真实机器人上很关键。它不擅长的是那些目标状态不可观测的任务。比如“把螺丝拧到底”这种目标用视觉很难判断是否到位或者“递给你一杯水”目标是动态的、在另一个人的手上这类就不适合纯视觉的hindsight方案需要加入力矩传感器或触觉反馈。另外可解释性也会是个问题。逆向轨迹预测本质上是一个端到端的映射如果机器人学出来的轨迹在视觉上很怪异比如绕了一个大圈工程师很难判断是视觉误差还是控制策略的问题。我建议在实际部署时在轨迹层面做一个简单的分析工具把每个中间状态的期望位置和实际到达位置一起可视化能大幅降低排查问题的难度。4. 后见之明偏差产品决策里的隐形杀手4.1 复盘为什么总是“马后炮”跳出技术范畴hindsight这个词在认知心理学里是后见之明偏差hindsight bias意思是事情结束后人们倾向于认为“我早就知道会这样”。这个偏差在职场上太常见了一个功能上线后转化率跌了复盘会上不少人开始说“我一开始就觉得这个设计有问题”一个项目延期了会说“当时评估的时候就感觉时间不够”。这个偏差之所以危险是因为它扭曲了我们对自身决策质量的判断。如果每次事后都觉得“一切尽在掌握”我们就会逐渐失去对不确定性的敏感度开始轻视风险。我见过不止一个团队把连续几次的项目成功归因于“团队执行力强”但其实可能只是市场运气好等到真正遇到黑天鹅的时候复盘体系又无法准确识别问题因为每个人都活在“事后合理化”的幻觉里。用工程视角来描述这件事就是你在做决策的时候没有记录概率分布所以事后你无法还原当时的置信度自然也没法科学评价决策过程的好与坏。4.2 用“决策日志”抵抗后见之明我自己的应对方法非常朴素就是在每个项目启动阶段写一份决策日志Decision Log。不用什么复杂的工具一个文档、一个表格就够了但要记录几个关键字段当时面临的核心不确定性是什么我对成功概率的主观估计是多少我是依据哪些假设做了这个选择如果失败我预期可能的原因是什么上线之后再把这些字段逐条拿出来做对照。假设我说“有80%的把握”实际数据出来如果真的成了说明预估还算合理如果失败了就要重点看是哪条假设被证伪。这个过程中最关键的是不要用结果来重写日志。无论结果好坏当时的记录都是你判断决策质量的唯一素材。另外一个好用的工具是premortem也就是“预先验尸”在项目正式启动前假设这个项目——不管大家多么信心满满——已经以一种可悲的方式失败了然后让每个人写下“导致失败的原因”。这本质上是在决策尚未定型时强制团队把思路从“成功谋略”切换到“失败归因”效果比复盘会强得多因为复盘会是在结果已定的时候进行的批判性思考会被“我好像早知道”污染。4.3 从“事后归因”到“事前预判”可复用的经验如果你把后见之明这个过程和技术中的HER对比会发现很有启发的相似性HER是对过去的轨迹“重新标注目标”让失败经验变得有效产品决策里也可以做类似的事——对过去的决策“重新标注前提”把模糊的“觉得会是这样”变成清晰的“如果前提A成立则选择B”。我最近在团队里推行了一个轻量级的习惯每周复盘时不在“结果好/坏”的维度上做评价而是在“决策时是否有依据、依据是否可靠”的维度上做评价。结果是好的但如果纯粹是碰运气这个项目仍然是一个需要警惕的样本结果不好但如果决策逻辑清晰、依据扎实这就只是一个运气问题。长期坚持下来团队对风险的感知会比以前准很多。具体的检查清单可以是这样的这个需求我们是否给用户创造了一个明确的解决路径我们假设的用户真实痛点有没有被验证过团队是对结果负责还是对决策质量负责如果某个环节只能凭感觉我们有没有设计一个低成本验证手段这些问题在项目开始前就应该覆盖而不是等到数据出来后再问一堆“当时怎么没注意”。5. 踩坑实录与速查手册5.1 训练HER时最容易翻车的五个细节第一没有在next_obs里替换目标直接导致Q值估计不一致训练曲线要么不上扬要么剧烈震荡。第二目标判定半径设得太小比如0.05绝大部分轨迹的reward依然是0HER的“事后成功”效应被削弱很多建议从任务可操作空间尺度的10%~20%开始调。第三replay buffer容量设太小HER生成的经验很快被冲掉训练中期就会出现学习停滞。第四对离散动作环境使用HER时建议保留较高的初始exploration比率。我当时观察到如果epsilon从0.1开始即使有HER训练速度也明显变慢因为agent几乎没有产生多样化轨迹的能力值得重写的经验在快速减少。第五是和算法无关但同样致命的把HER拼接进obs的goal数据没有做normalization。因为state和goal可能是不同的数量级比如position从0到10goal offset从-2到2如果不做归一化网络会天然放大某个维度的影响导致学习方向偏斜。5.2 参数速查表下面这个表格是我在多个环境中试过比较省心的默认配置可以直接作为起点再调不一定最优但至少能先跑起来参数推荐默认值备注目标替换概率0.50.3~0.7可接受超过0.8会稀释真实目标事后目标采样策略future k-stepk取轨迹剩余长度的1/4左右replay buffer容量1e5~1e6容量太小会削弱HER收益奖励判定半径任务空间10%~20%越小任务越困难折扣因子gamma0.95~0.99稀疏奖励任务建议偏大探索算法epsilon-greedy或OU-noise初始exploration须足够高更新频率每10步采样128训练可根据环境调节5.3 排查清单训练不收敛时按顺序查如果训练卡在某个成功率上不去我通常最习惯按照这个清单一步步过先看reward曲线是否长时间完全平坦如果是检查trajectory里是不是根本没有成功经验——HER只能重写已有的轨迹如果没有多样性它也无能为力这时需要提高探索率或降低任务难度。然后看模式崩溃问题成功率突然上升又突然归零往往是buffer里高回报经验比例过高降低replay比例或调整替换概率。再看目标表示的维度是不是过稀疏。如果goal有10个维度但大部分维度与任务完成无关建议先做维度压缩HER在最关键的2~3个维度上学习效果最好。最后检查网络容量和batch size。低维环境不需要很大的网络但batch size若太小比如32Q值更新方差很大也会导致训练不稳。5.4 系统部署层面的常见问题在真实的机器人项目里常见的坑比仿真里多得多。第一个就是“仿真到现实的鸿沟sim-to-real gap”在仿真里训出来的策略到了真实机械臂上会因为延迟、摩擦、视觉噪音而崩溃。抵消这个问题的办法是在训练中加入领域随机化比如随机化目标的颜色、光照、摩擦力让模型不是过度依赖某一个视觉特征。第二个常遇到的是控制频率不稳定。如果用Python做视觉推理推理速度可能波动到不定时导致控制信号的时间间隔不规则。我的做法是把视觉推理放到单独进程里用共享内存传递结果主控进程以固定50Hz执行位置控制这样能把不确定性限制在可控范围内。第三个问题是数据标注成本。拿人类演示来训练Hindsight系统核心其实是标注“动作意图”而不是标注“像素标签”。建议一个微量样本学习策略先用几段高质量的演示建立基线然后在机器人生成的新数据里用弱监督方式自动标记成功与失败例如最终位置和方向以此持续迭代模型。6. 从经验中学到的事说了这么多hindsight这个概念的三个面向其实指向同一个教训复盘不是回到过去证明“我早就知道”而是把过去的数据改造成对未来有用的信号。HER的做法是重写目标让失败轨迹变成有效经验Hindsight视觉系统的做法是从终点逆推运动轨迹产品决策的做法则是用决策日志把模糊的事后归因变成清晰的事前预判。我在第一次跑通HER实验的时候看到曲线从0爬升到90%以上的那一刻其实受到的冲击不只是“算法好使”而是那种“把失败重新命名成成功”的视角转换。后来做产品需求复盘时我也会反复提醒自己不要问“这个决策为什么错了”而要问“当时的信息和假设是否足以支撑这个决策”只有后者能帮你在下一次做更好的选择。如果你现在正要开始一个稀疏奖励的任务、或者在两个方案之间犹豫不决我的建议是别急着写复杂代码或做完美计划。先花十分钟把目标重写一次把“如果现在不成功我凭什么说它不是一次有效的尝试”写下来这个简单的动作价值可能比训练三小时还大。最后再分享一个小技巧强化学习实验里模型不收敛时别急着加各种复杂机制先把replay buffer里的数据打印出来看看如果数据本身没有有效信号再高级的算法也帮不了你。判断信号是否存在的最笨方法是可视化一个episode的轨迹和目标点看到轨迹在目标点附近有聚集然后再去调算法细节效率会高很多。
返回列表