尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

强化学习奖励工程实战:PyBullet清扫机器人十项复合奖励设计

强化学习奖励工程实战:PyBullet清扫机器人十项复合奖励设计 做强化学习项目最扎心的一个环节就是奖励工程。算法可以抄开源库环境可以改现成仿真唯独奖励函数这关谁也替不了你——它直接决定了agent会长成什么样子。这次我用的场景是PyBullet仿真里的轮式清扫机器人目标是在一个随机布局的房间里清理散落的垃圾。训练过程中我没有改网络结构、没有换算法只把一个“清扫完成率”的单一大奖励拆成了10项复合奖励项目评分从最初的100分一路提到了778分。这篇文章就完整记录我是怎么设计这10项奖励、怎么一步步排查调参的给正在做强化学习控制、尤其是机器人清扫或类似导航抓取任务的朋友做个参考。1. 项目背景与整体思路拆解1.1 清扫机器人任务为什么卡在100分先交代一下环境设定。机器人底盘是一个两轮差速模型车头挂了一个滚刷式吸尘口仿真里的垃圾用圆形小球表示位置每次开局随机撒10到30个。状态空间由16束激光雷达测距、线速度、角速度、IMU角速度、当前电量、最近3个垃圾的相对方向和距离组成。动作空间是二维连续控制线速度范围0到0.5m/s角速度范围-π/3到π/3。算法用的是PPOMLP隐层[256,256]Gae Lambda 0.95Clip系数0.2学习率3e-4总训练步数60万步。第一版奖励函数非常朴素每清理一个垃圾给10分全部清完再给50分任务结束。直观上这逻辑没问题有垃圾就捡捡完就高分。实际训练出来的agent前几千步完全是在原地转圈、撞墙、往角落钻正常能走一米以上的策略都学不出来。跑了差不多4万步环境综合评分稳定在100分上下——所谓综合评分是仿真环境自己算的包括清扫完成率、路径覆盖率、耗时、碰撞次数、重复清扫面积等指标的加权结果和内部奖励是两回事。问题出在哪我心里很清楚这一版是典型的稀疏奖励在连续动作空间里一个随机策略“恰好”移动到垃圾附近并触发清理动作的概率低到几乎为零。agent只有撞大运碰上一次垃圾清除才能收到一次正反馈而这个反馈又不足以让它在高维连续空间里锁定正确的动作方向。奖励信号没信号PPO的输出分布就越来越趋于均匀策略约等于随机乱撞。1.2 十项奖励的“作战地图”解决稀疏奖励问题的标准思路就是补密集奖励但补得不好也很容易翻车。我的做法是先把“清扫”这个任务拆成四个子问题找到垃圾、执行清扫、提升覆盖、合理用电和行动。然后围绕这四个子问题设计了一组复合奖励最终收敛成10项编号奖励项类型权重设计目标1垃圾检测奖励正向引导1.0鼓励主动搜索目标2清扫动作成功奖励正向引导2.0强化正确的清理动作3垃圾清除奖励正向引导10.0对核心结果给出大反馈4新覆盖栅格奖励进度效率0.05/格提升空间探索覆盖率5清扫进度比例奖励进度效率5.0封顶提供全局进度感6连续清扫保持奖励进度效率0.2鼓励连续作业不中断7重复清扫惩罚约束惩罚-0.05/格防止原地打转刷分8碰撞惩罚约束惩罚-0.2培养避障习惯9每步时间惩罚约束惩罚-0.01倒逼路径效率10任务完成大奖任务级50.0锚定最终目标这个框架的核心思路是正向引导告诉agent“做什么是对的”约束惩罚告诉agent“做什么会被扣分”进度奖励让agent在长任务中始终有一个“离目标更近了”的感觉任务级大奖则保证agent不会为了刷过程奖励而丢掉最终目标。这种结构不是拍脑袋来的它对应着清扫任务本身的层次——一个清扫机器人既要会识别目标、又要会移动覆盖、还要避开障碍物、最终还要收工缺了任何一个环节训练出来的行为都会跑偏。2. 十项复合奖励的设计与计算2.1 正向引导类先让agent知道“什么是该干的”奖励1是垃圾检测奖励。实现方式很简单机器人的激光雷达或者视觉感知范围内出现垃圾时每检测到一个给1.0分同一个垃圾要设置一个冷却计时器比如3秒内重复检测不会再给分。这个奖励的作用是把“找到垃圾”从无信号变成有信号。我实测发现加上这一项之后agent开始有明显的“巡视”行为而不是原地乱撞因为它在转向时扫到垃圾会得到正反馈这个反馈让“头部朝向某个方向”这个动作获得了价值。但加了这个奖励之后也马上出现一个现象机器人学会了“只看不扫”。它发现只要垃圾保持在视野内就能持续获得检测奖励于是策略收敛成绕着垃圾圈子打转。这就是为什么必须同时有奖励2——清扫动作成功奖励。当agent的吸尘口与垃圾发生有效接触并触发一次完整吸尘动作时给2.0分。这一项的直接效果是让agent意识到“光看不行要看且吸才有利”。这两项的互补关系很重要如果只加一项都会带偏行为。奖励3是垃圾清除奖励每次垃圾真正从地图上消失给10.0分。这一项是对核心目标的中等密度反馈频率比稀疏版高很多但又不至于像发现奖励那样容易被刷。我在项目里把这三项作为“主链奖励”它们共同确定了一条从搜索到执行到完成的动作链路。权重比例上清除大于动作成功大于检测这样agent会有明确的优先级任何可能导致垃圾消失的行为都优先于“保持视野里有垃圾”的行为。2.2 进度效率类从“会扫”到“扫得聪明”奖励4是覆盖率奖励。实现时我把地图栅格化成10cm x 10cm的格子记录机器人吸尘口中心点经过的栅格。每次进入一个新的、没有标记过的栅格就给0.05分。这个奖励让agent摆脱了“盯着一个垃圾无限处理”的死循环因为当区域内的能吸的垃圾都清掉了覆盖率奖励会push它去新区域看看。里程计漂移在这里影响不大因为仿真环境里位置是理想真值但如果是真实机器人可能需要用AMCL或者视觉定位来做栅格映射这点在后面常见问题里会展开。奖励5是进度比例奖励每回合动态计算已清理垃圾数除以总垃圾数结果乘5.0作为一项加分。比如开局总共20个垃圾已经清完6个这一项就是1.5分。这个奖励的设计初衷是给agent一个“平滑推进”的感觉清理1到2个垃圾时可能不明显但清到一半的时候agent会明显更积极地去寻找剩余垃圾。它和奖励4的区别是覆盖率奖励偏向空间探索进度比例奖励偏向任务完成进度两者可以互相补充。奖励6是连续清扫保持奖励。当agent在连续10个仿真步内都有清扫动作行为吸尘口与垃圾发生接触或正在进入未覆盖区域时每保持一次给0.2分。这个奖励是我在调参后期加的目的是抑制“干一下停一下再干一下”的碎片化策略。加上之后学习曲线明显平滑了许多路径从断续变成连续清扫顺序也从随机跳跃变成了更接近弓字形来回扫。2.3 约束惩罚类把坏习惯扼杀在摇篮里奖励7是重复清扫惩罚。每重新进入一个已经标记为已清扫的栅格扣0.05分。注意这里要严格区分“进入已清扫区域”和“只是靠近”按吸尘口位置判断不是按机器人中心点判断。第一个版本我按中心点算结果机器人的吸尘口已经扫过的地方车身中心还在外面判定认为没扫过惩罚不起作用。后来改成吸尘口坐标映射到栅格才解决。这个惩罚项极大地矫正了“原地打转刷覆盖率”的行为。奖励8是碰撞惩罚。第一版我把碰撞惩罚设成-1.0结果agent学会了“非常安全地一动不动”因为只要不动就不会撞同时也扫不了垃圾。我把惩罚降到-0.2情况立刻改善了不少。这背后是一个权重尺度问题碰撞惩罚不能超过正向奖励的总和否则agent会选择当一个“安静的美男子”。对我这个任务来说碰撞更多是路径质量问题不是任务失败所以惩罚力度轻一些更合适。奖励9是每步时间惩罚每走一步扣0.01分。这个数值非常小但累积起来很可观。一个回合如果走了3000步光时间惩罚就吃掉30分相当于3个垃圾清除奖励。它的作用是让agent尽量用最短路径完成任务避免为了刷覆盖率或清扫动作奖励而拖时间。实测把时间惩罚加进去之后平均每个回合的步数从2800步降到了不到1800步清扫完成率反而没有明显下降。2.4 任务级大奖与权重归一化奖励10是任务完成大奖。当所有垃圾被清理完毕给50分并终止回合。这个奖励在10项里数值最高但发生频率最低。它存在的意义不是提供训练信号而是给策略一个“终局锚点”——让agent知道继续探索、继续清扫才是终极最优解。设计权重时我做了归一化处理。原则很简单让每一项奖励在正常行为下的单步期望幅度控制在同一数量级避免某一项淹没其它项。比如新增覆盖栅格最多覆盖地图几百个格子每格0.05分单回合总量最多十几分垃圾清除奖励总共10到30个每个10分单回合总量可以到100到300分清扫进度比例奖励封顶5分连续清扫保持奖励如果后半程全程保持可以积累十几分。我再根据实验反馈微调最终权重见上面的表。核心实现的伪代码大致是这样def compute_reward(info, prev_info): reward 0.0 # 1. 垃圾检测奖励 if info[garbage_in_sight]: reward 1.0 * w1 # 2. 清扫动作成功奖励 if info[sweep_action_success]: reward 2.0 * w2 # 3. 垃圾清除奖励 if info[garbage_cleared]: reward 10.0 * w3 # 4. 新覆盖栅格奖励 reward info[new_covered_cells] * 0.05 * w4 # 5. 清扫进度比例奖励 reward (info[cleaned_count] / max(info[total_garbage], 1)) * 5.0 * w5 # 6. 连续清扫保持奖励 if info[sweeping_streak] 10: reward 0.2 * w6 # 7. 重复清扫惩罚 reward - info[revisited_cells] * 0.05 * w7 # 8. 碰撞惩罚 if info[collision]: reward - 0.2 * w8 # 9. 每步时间惩罚 reward - 0.01 * w9 # 10. 任务完成大奖 if info[goal_completed]: reward 50.0 * w10 return reward需要注意info里的每一项都需要在环境step函数里实时计算尤其是new_covered_cells和revisited_cells它们依赖栅格地图的历史标记。我还单独加了info[last_sub_rewards]把每个子项存下来方便之后用日志分析是哪一项在起作用。3. 训练调参实录100分到778分的完整经过3.1 阶段一稀疏奖励下的策略坍缩初始版本只有奖励3和奖励10相当于一个稀疏版。训练到第4万步时我拉了一下各种指标平均回合奖励负得离谱、策略熵从初始值掉到接近0、成功率不到2%、碰撞次数每千步接近500次。agent的行为模式非常典型——在墙角附近来回摆动偶尔撞一下墙反弹然后继续抖动。这个阶段的问题我在第一节已经分析过连续动作空间太大稀疏奖励给不了有效的梯度引导。这里多说一句很多初学者会想“我用更强的探索噪声是不是就能解决”实测作用有限高维连续空间里随机碰见垃圾本身就是小概率事件就算碰见了一次的奖励也很难让agent把“走到垃圾旁边并触发吸尘”这个序列动作固化下来。所以我的结论很明确这个任务里稀疏奖励天花板就在100分附近必须上密集化设计。3.2 阶段二密集奖励带来了“刷分怪”第二阶段我加入了奖励1、2、4、7。训练到第12万步时评分爬到了300分左右清扫完成率到了28%。表面看起来agent“会扫了”但日志里暴露了一个很有意思的现象清扫完成率只有不到三成但平均回合长度反而比第一阶段还长。看子奖励分布才知道原因agent变成了“刷分怪”。它发现持续让一个垃圾保持在视野范围内可以不停触发奖励1于是策略收敛成绕着垃圾转圈偶尔触发一次清扫但也扫不干净。这个行为纯看总奖励还挺正常因为检测奖励几乎每个步都能吃到比老老实实清扫更“划算”。解决这个问题的关键就是奖励7。把重复清扫惩罚加进去之后agent在已清扫区域停留的代价变高了转圈吃检测奖励的收益被大幅抵消。同时我把奖励1的冷却时间从3秒提到5秒让“保持视野”这件事没那么容易持续刷分。这个阶段让我印象很深复合奖励不是“加得越多越好”而是每一项都在限制上一个奖励钻空子的可能性。3.3 阶段三权重平衡与最终的778分第三阶段我把奖励5、6、8、9、10全都加进来评分先升到500分然后卡住了。卡住的原因是agent开始利用覆盖率奖励——它发现绕远路能持续获得新栅格奖励于是路径变得非常绕平均步数飙升到4000步。处理办法有两步。第一步把覆盖率奖励改成“只统计第一次覆盖的栅格重复进入不给分”这样绕远路没有额外收益。第二步把时间惩罚从-0.01改到-0.015同时提高连续清扫保持奖励到0.3让高效连续作业的收益高过漫无目的的探索。改完之后评分继续往上爬到第45万步时稳定在778分。这个数字是环境综合评分跑出来的不是内部奖励。同一时间点的关键指标是清扫完成率从28%提升到89%覆盖率从54%提升到92%平均回合步数从2800降到1450碰撞次数从每千步500次降到140次。我在多个随机种子下各测了5次最低也有750分左右。780分这个坎我试了很久没有迈过去原因是仿真里存在一些不可达或重叠的垃圾导致完成率上不去。如果你也想复现我的建议是当前权重组合可以直接抄但覆盖率和时间惩罚需要根据你的地图大小微调。4. 常见问题与排查技巧实录4.1 训练指标一直不动先查子奖励分布很多朋友遇到“训练不收敛”就直接调学习率或者换算法我建议先做一件事在日志里把10项子奖励分别打出来看它们的期望分布。如果某项奖励长期为0说明agent根本没学会相关行为问题可能是奖励密度不够如果某项奖励占了总奖励的80%以上说明权重失衡agwent会优先刷这一项。我踩过一个具体例子奖励6连续清扫保持奖励刚上线时日志显示它一直在0附近我当时以为是环境bug查了半天发现是阈值设成“连续10步”要求太高实际清扫过程中垃圾分布很稀疏根本撑不到10步连续。把阈值调到5步之后这项奖励才开始正常起效。所以要习惯用“子奖励分布图”而不是“总奖励曲线”判断问题。4.2 原地打转、刷奖励怎么治原地打转是清扫任务里最经典的奖励钻空子现象本质是agent找到了一个以极低成本持续吃奖励的循环路径。我会按照下面这个顺序排查确认是不是某项目前太容易获得比如垃圾检测奖励冷却太短、能看到就给分这类最容易刷确认重复清扫惩罚有没有真正生效很多情况下是栅格判定位置不对按车身中心算而不是吸尘口位置算确认覆盖率奖励是不是按“首次覆盖”计算如果每次进入都加分绕圈就是最优策略实在不行就给行为加硬限制比如agent连续N步停留在一个半径1米内的区域时对后续步数额外扣分。还有一个技巧是给吃灰的吸尘动作加冷却时间同一垃圾在短时间内重复触发清扫动作不给奖励这比单纯调权重更直接。4.3 权重调整的经验顺序手调权重最容易头大因为10项奖励互相牵连调一个往往引发连锁反应。我的经验是遵循三步走第一步先定方向把正向类的奖励1、2、3先安排好保证主线行为有反馈第二步再定尺度加入约束惩罚7、8、9目标是让行为规范化注意惩罚总期望不要超过正向总期望的30%到40%第三步最后微调效率项4、5、6让行为从“规范”变成“高效”。权重记录我用过一张表格效果不错。把每次调整的版本号、各权重、对应评分、清扫完成率、平均步数都记下来前后对比就很清楚。不要靠记忆调参几个版本过后你根本记不清上一次改了什么。4.4 三个容易被忽视的外部因素第一个是随机种子。同一个奖励函数在不同种子下PPO的训练结果可能差异很大。我最后上线前至少开5个种子各训一版取中位数作为最终效果只跑一个种子就把结果写进总结会非常危险。第二个是摩擦与动力学参数的差异。仿真里车轮与地面的摩擦系数、吸尘口与垃圾的接触判定都偏理想同一套奖励搬到真实机器人上agent对“清扫动作”的把握可能完全失灵。真实机器人上跑强化学习建议先用系统辨识校准一份接近实际的动力学参数再同步调整接触判定逻辑。第三个是离线强化学习的思路也可以借鉴。有人会问为什么不试试IQL这类offline RL路线我了解过一些确实能利用已有数据避免从零探索但奖励工程的核心地位没有变——离线数据本身也是靠一套奖励函数收集出来的奖励设计不靠谱离线数据集一样脏。对我这个清扫项目来说PPO配合复合奖励已经满足需求暂时没有换算法的必要。5. 写在最后给同路人的几句真心话这个项目做完之后我最大的体会是奖励函数就是你对任务理解的一面镜子它会把你的每一个想当然都暴露得清清楚楚。你以为“清扫完成率”就是任务目标但agent会告诉你“只要分数好看什么路径都走得出来”你以为碰撞惩罚越重越安全agent会用“窝着不动”回敬你。所以别急着跑训练先把任务拆解清楚把每一项目标翻译成可以度量的反馈再花时间在奖励本身的代码调试上这些前期投入远比后期调参划算。另外分享一个小技巧给agent的每个动作序列录一段视频把10项奖励的实时数值叠加在画面上。很多“agent在刷分”的问题看数据曲线不一定看得出来但看一集视频就全明白了。这个习惯我一直保留到今天凡是做机器人强化学习项目都会用。如果后续想继续扩展我建议可以往多机器人协作清扫、动态障碍物环境、以及真实机器人部署这三个方向走。但无论场景怎么扩展“奖励工程”永远是绕不开的核心环节。希望这篇实战记录能帮你少踩几个坑也欢迎你在评论区分享自己抓到的那些“钻空子”策略。
返回列表