☰
强化学习奖励工程实战:从100分到778分的清扫机器人调参实录
2026/9/28 17:56:52 网站建设 项目流程

1. 从100分到778分:一个清扫机器人的奖励工程实录

第一次跑通清扫机器人的强化学习训练时,我盯着屏幕上的曲线看了很久。100分出头的回合奖励,机器人像个没头苍蝇一样在场地里乱转,扫过的区域不到三成,撞墙倒是撞得挺勤快。那会儿我一度怀疑是不是PPO的超参没调好,学习率、裁剪系数、熵系数来回试了个遍,折腾了快一周,曲线还是那个死样子。

后来我把训练日志拉出来逐帧回放,才发现问题根本不在算法本身。机器人不是学不会清扫,而是我给的奖励信号压根没告诉它“什么叫扫干净”。稀疏奖励下,它只有把整个场地扫完才能拿到一个正反馈,中间过程全是零。这种设定下,智能体跟买彩票没什么区别,随机探索到天荒地老也未必能撞上一次有效路径。

这篇文章就是记录我怎么从那个100分的坑里爬出来,用10项复合奖励把分数推到778分的完整过程。涉及到的核心是强化学习奖励工程,算法用的是PPO,场景是机器人清扫,但里面关于稀疏奖励破局、奖励项权重设计、训练稳定性排查的思路,放到机械臂控制、交通信号调度、多智能体协作这些场景里同样适用。如果你正在做强化学习落地,尤其是那种“仿真里跑得挺好、真机上完全不能用”的项目,这篇应该能帮你省下不少试错时间。

2. 奖励工程的整体设计思路

2.1 为什么稀疏奖励是清扫任务的死穴

清扫任务有一个很讨厌的特性:它的成功条件天然是稀疏的。你定义“扫完整个区域”为成功,那智能体在完成之前拿不到任何有效梯度。假设场地是10米乘10米,机器人每步移动0.1米,理论上要走几百步才能覆盖完。在这几百步里,只有最后一步有奖励,前面的动作对最终回报的贡献几乎被稀释到零。

这不是PPO的问题,换SAC、CQL、IQL来都一样。稀疏奖励下的信用分配问题,本质上是让智能体在没有任何中间信号的情况下,自己悟出“往左转比往右转更接近目标”。这就像教一个从没见过扫把的人扫地,只在他扫完整个屋子后才说一句“对了”,中间他无论怎么挥扫把你都面无表情。换谁都学不会。

我试过最直接的办法:把奖励改成“每扫一格给一分”。结果机器人学会了在原地反复扫同一块区域,因为那样刷分最快。这就是典型的奖励黑客行为,智能体找到了奖励函数的漏洞,用最小代价换取最大回报,但完全偏离了设计意图。

所以奖励工程的核心矛盾在于:信号太稀疏学不动,信号太密集又容易被钻空子。我的解法是设计一组复合奖励,让每个奖励项负责一个具体的子目标,同时通过权重和衰减机制防止智能体走捷径。

2.2 10项复合奖励的构成逻辑

我把清扫任务拆成了几个可量化的维度:覆盖效率、碰撞规避、动作平滑度、能量消耗、重复清扫惩罚、边界遵守、转向合理性、速度适配、清扫连续性、终局奖励。每一项对应一个奖励函数,最后加权求和。

这10项不是拍脑袋想出来的,而是按照“先保证能跑,再保证跑得好,最后保证跑得像人”的递进逻辑设计的。前3项解决基本可行性,中间4项优化行为质量,后3项处理边界情况和终局条件。

具体来说,覆盖效率奖励鼓励机器人探索新区域,碰撞惩罚让它学会避障,动作平滑度防止它抽搐式移动。重复清扫惩罚专门对付原地刷分,边界遵守防止它跑出场地,转向合理性避免它原地打转,速度适配让它在直道加速、弯道减速。清扫连续性奖励连续清扫动作,终局奖励在任务完成时给一个大额正反馈。

每一项的权重不是固定的,而是随着训练阶段动态调整。前期覆盖效率权重高,鼓励探索;后期碰撞惩罚和重复清扫惩罚权重上升,逼它精细化。这个动态调权的思路后面会详细讲。

2.3 为什么选PPO而不是SAC或CQL

算法选型上我最终用了PPO,但中间试过SAC和CQL。SAC在连续动作空间下样本效率确实高,但它的最大熵目标会让策略保持一定的随机性,这在清扫任务里表现为机器人时不时抖一下,动作不够干净。CQL适合离线数据,但我这是在线训练,用不上它的保守性优势。

PPO的优势在于训练稳定、超参不敏感、容易复现。它的裁剪机制天然限制了策略更新幅度,不会因为某个batch的奖励异常就把策略带偏。对于清扫这种需要精细动作控制的任务,PPO的确定性策略在推理阶段表现更可控。

当然PPO也有坑,比如优势函数估计的偏差问题。我一开始用GAE的时候lambda设成了0.95,后来发现清扫任务的回合长度变化很大,固定lambda会导致长回合的优势估计偏差累积。改成动态调整lambda之后才稳定下来。这个细节后面在问题排查部分会展开。

3. 核心奖励项的数学形式与实操细节

3.1 覆盖效率奖励:让机器人主动探索

覆盖效率奖励的设计目标是鼓励机器人访问未清扫区域。最直接的做法是用栅格地图记录每个格子的清扫状态,机器人每进入一个未清扫格子就给正奖励。

数学形式是这样的:假设场地被离散化为N个格子,机器人当前位置为p,如果p对应的格子未被清扫,奖励为r_coverage = α * (1 - coverage_ratio),其中coverage_ratio是当前已清扫格子占总格子的比例。这个设计的好处是前期奖励大,后期随着覆盖率上升奖励自然衰减,避免机器人为了刷分反复清扫已覆盖区域。

但这里有个坑:如果机器人站在两个格子交界处,可能会反复触发“进入新格子”的判定。我的处理方式是给每个格子加一个冷却时间,同一个格子在T步内只计一次奖励。T设为50步,实测下来既能防止刷分,又不会影响正常清扫节奏。

另一个细节是覆盖率的计算频率。每步都算一次覆盖率会拖慢训练速度,我改成每10步更新一次。机器人在10步内清扫的新格子数累积起来,一次性给奖励。这样既保证了信号密度,又控制了计算开销。

3.2 碰撞惩罚:从硬约束到软惩罚

碰撞惩罚看起来简单,给个负奖励就完了。但实际做的时候,负奖励的大小很讲究。给太小,机器人不在乎,照样撞;给太大,机器人会变得过度保守,离墙八丈远就开始绕路,清扫覆盖率上不去。

我试过三档:-1、-5、-10。最终选了-5,配合一个碰撞后的冷却期。机器人撞墙后,接下来20步内碰撞惩罚减半,防止它在墙角反复撞、惩罚累积到失控。

碰撞检测本身也有讲究。仿真环境里用的是激光雷达点云,但点云有噪声,偶尔会误报。我的做法是连续3帧检测到碰撞才判定为真碰撞,单帧触发只记录不惩罚。这个去抖逻辑在真机迁移时特别重要,因为真实传感器的噪声比仿真大得多。

还有一个容易被忽略的点:碰撞惩罚应该和速度挂钩。高速撞墙的惩罚应该大于低速轻触。我加了一个速度因子,最终碰撞惩罚为r_collision = -5 * (1 + v/v_max),其中v是碰撞时的速度,v_max是最大速度。这样机器人会学会在靠近障碍物时主动减速。

3.3 动作平滑度奖励:防止抽搐式移动

动作平滑度奖励的目的是让机器人的动作序列连贯,不要一步左转90度、下一步右转90度。实现方式是对相邻两步的动作差值做惩罚。

具体来说,设当前动作为a_t,上一步动作为a_{t-1},平滑度奖励为r_smooth = -β * ||a_t - a_{t-1}||^2。β取0.1,这个值是我试出来的。太大机器人会变得反应迟钝,太小起不到平滑效果。

这里有个细节:角速度和线速度的平滑应该分开处理。线速度的变化可以稍微剧烈一点,因为机器人需要快速启停;角速度的变化要更平滑,否则机器人会像陀螺一样转来转去。我的做法是给角速度差值乘一个1.5的系数,加大惩罚力度。

实测下来,加了平滑度奖励后,机器人的动作轨迹从锯齿状变成了平滑曲线,清扫覆盖率提升了约15%。这个提升不是来自更聪明的决策,而是来自更稳定的执行。

3.4 重复清扫惩罚:对付奖励黑客

重复清扫惩罚是专门用来对付原地刷分的。没有这个惩罚的时候,机器人发现待在同一个区域反复扫可以稳定拿覆盖奖励,虽然每次拿的不多,但胜在安全无风险。这种行为在强化学习里叫“局部最优陷阱”。

我的设计是维护一个访问计数器,记录每个格子被清扫的次数。如果某个格子的清扫次数超过阈值K,后续每次清扫给负奖励。K设为3,也就是说一个格子被扫3次以上就开始扣分。

惩罚力度是递增的:第4次扫扣0.5分,第5次扣1分,第6次扣2分,以此类推。这种递增惩罚比固定惩罚更有效,因为它给机器人一个“及时止损”的信号,越早离开损失越小。

但这里有个边界情况:如果场地本身很小,或者机器人被卡在角落里,它可能被迫反复扫同一个格子。我的处理是加一个“被困检测”,如果机器人连续50步都在同一个3x3区域内移动,就触发一个随机传送,把它扔到场地另一个位置。这个机制有点粗暴,但实测下来比让它在角落里耗到回合结束要高效得多。

3.5 终局奖励与回合终止条件

终局奖励的设计相对简单:当覆盖率超过95%时,给一个+50的大额奖励,同时终止回合。这个阈值不能设成100%,因为总有一些边角格子机器人可能永远扫不到,设100%会导致回合永远不结束。

回合终止条件除了覆盖率达标,还有两个:最大步数限制和碰撞次数超限。最大步数设为2000步,防止机器人无限徘徊;碰撞次数超过50次也终止,说明策略已经崩了,继续跑下去只是浪费算力。

终局奖励的数值需要和中间奖励匹配。如果终局奖励太大,机器人会只盯着终局,忽略中间过程;太小又起不到激励作用。我试过+20、+50、+100,最终+50效果最好。这个值大概相当于机器人正常清扫100步累积的中间奖励,既显著又不至于压倒一切。

4. 训练流程与调参实录

4.1 环境搭建与仿真配置

仿真环境用的是PyBullet,选它是因为轻量、Python接口友好、支持并行环境。场地是一个10米乘10米的矩形区域,四周有墙,中间随机放置若干障碍物。机器人模型是一个两轮差速驱动的清扫机器人,带一个前向激光雷达和一个底部清扫传感器。

并行环境数设为16,这个数字是显存和CPU核数平衡的结果。太少样本收集慢,太多每个环境的batch size被压缩,梯度估计方差大。16个环境配合PPO的batch size 2048,实测下来训练速度和质量比较均衡。

观测空间包括:激光雷达的24维距离读数、机器人当前速度(线速度和角速度)、当前位置坐标、以及一个局部栅格地图(机器人周围3米范围内的清扫状态,分辨率0.1米,共60x60维)。局部地图用卷积网络提取特征,和其余观测拼接后送入策略网络。

动作空间是连续的:线速度范围0到1米每秒,角速度范围-1.5到1.5弧度每秒。动作经过tanh激活后缩放到这个范围。

4.2 奖励权重的动态调整策略

10项奖励的初始权重是我根据经验设的,但固定权重跑下来效果一般。前期机器人需要大胆探索,覆盖效率权重应该高;后期需要精细化,碰撞和重复清扫惩罚应该加重。

我实现了一个简单的线性调权方案:训练前20%的步数里,覆盖效率权重从1.0线性降到0.5,碰撞惩罚权重从0.5线性升到1.0,重复清扫惩罚从0.3升到1.0。中间60%保持稳定,最后20%再微调一次,把平滑度奖励权重提高,让最终策略的动作更干净。

这个调权方案不是最优的,但比固定权重好很多。实测下来,动态调权让最终覆盖率从87%提升到了94%,而且训练曲线更平滑,没有出现中期崩溃。

调权的节奏很关键。调太快,机器人来不及适应新权重,策略会震荡;调太慢,前期探索不充分,后期精细化不够。我试过5%、10%、20%三个节点,20%最稳。

4.3 PPO超参的最终配置

PPO的超参我调了大概两周,最终配置如下:学习率3e-4,裁剪系数0.2,熵系数0.01,GAE的lambda动态调整(前期0.95,后期0.9),折扣因子0.99,batch size 2048,mini-batch size 256,更新轮数10。

学习率3e-4是PPO的经典值,但清扫任务的动作空间比较精细,我试过1e-4和5e-4,1e-4收敛太慢,5e-4中期震荡,3e-4最平衡。

熵系数0.01是为了保持一定的探索性。太小机器人会过早收敛到局部最优,太大策略太随机。0.01这个值让机器人在训练前期保持探索,后期逐渐确定性化。

GAE的lambda动态调整是个小技巧。清扫任务的回合长度变化大,短则几百步,长则上千步。固定lambda在长回合下会导致优势估计偏差累积。我的做法是回合长度超过500步时lambda降到0.9,否则保持0.95。这个改动让训练后期的value loss明显下降。

4.4 训练曲线解读与阶段性特征

训练曲线大致分三个阶段。第一阶段是0到50万步,奖励从100分缓慢爬到200分左右,机器人学会了基本移动和避障,但清扫效率很低,覆盖率在30%到40%之间徘徊。

第二阶段是50万到150万步,奖励从200分快速上升到500分左右。这个阶段机器人开始理解覆盖奖励,主动探索新区域,覆盖率提升到70%以上。碰撞次数明显下降,动作也平滑了很多。

第三阶段是150万到300万步,奖励从500分缓慢爬到778分。这个阶段提升主要来自细节优化:重复清扫减少、边界处理更合理、终局奖励触发更频繁。覆盖率稳定在94%到96%之间。

778分是300万步时的峰值,之后曲线基本平了,偶尔有小幅波动。我没有继续训练,因为覆盖率已经接近理论上限,再训下去边际收益很低。

5. 常见问题与排查技巧实录

5.1 奖励不升反降的排查思路

训练中期奖励突然下降是最让人慌的。我遇到过两次,第一次是150万步左右,奖励从500分掉到300分,持续了大概10万步才恢复。排查下来是重复清扫惩罚权重调得太快,机器人来不及适应,策略崩了。

排查这类问题的第一步是看value loss和policy loss。如果value loss突然飙升,说明奖励信号出了问题;如果policy loss飙升,说明策略更新幅度过大。我的经验是value loss先动,policy loss后动,所以盯value loss能提前预警。

第二步是回放失败回合的视频。我那次回放发现机器人在场地边缘反复横跳,明显是被重复清扫惩罚逼得不敢进已清扫区域,但又找不到新区域,陷入了死循环。解法是降低惩罚权重,同时加一个“探索奖励”,鼓励它往未访问区域移动。

5.2 机器人原地打转的解法

原地打转是清扫任务的高频问题。原因通常有三个:角速度惩罚不够、覆盖奖励设计有漏洞、或者激光雷达观测有盲区。

我的排查顺序是:先看角速度惩罚权重,如果低于0.05,大概率是惩罚不够;再看覆盖奖励,如果机器人打转的区域恰好是未清扫区域,那说明它在刷覆盖奖励;最后检查激光雷达,如果某个方向的距离读数一直是最大值,可能是传感器盲区,机器人误以为那边没有障碍。

解法对应也有三个:加大角速度平滑惩罚、给覆盖奖励加冷却时间、在盲区方向加虚拟障碍。我最终三个都用了,原地打转的问题基本消失。

5.3 仿真到真机的迁移损耗

仿真里跑778分,真机上可能只有400分,这个损耗主要来自三个方面:传感器噪声、动力学差异、地面摩擦变化。

传感器噪声的处理方式是在仿真训练时就加入噪声,激光雷达读数加高斯噪声,清扫传感器加随机丢包。动力学差异通过域随机化处理,机器人的质量、轮子摩擦系数、电机响应延迟都在一定范围内随机。地面摩擦变化比较难模拟,我的做法是在仿真里随机切换几种摩擦系数,让策略学会适应。

迁移时还有一个坑:真机的控制频率和仿真不一样。仿真里是50Hz,真机可能只有20Hz。控制频率降低会导致动作不平滑,我的解法是在真机部署时加一个低通滤波器,把高频动作分量滤掉。

5.4 常见问题速查表

问题现象可能原因排查方法解决方案
奖励不升反降权重调整过快看value loss曲线放慢调权节奏
原地打转角速度惩罚不足检查角速度权重加大平滑惩罚
反复扫同一区域覆盖奖励无冷却回放视频确认加冷却时间
碰撞次数居高不下碰撞惩罚太小统计碰撞频率加大惩罚并加速度因子
训练后期震荡学习率过大看policy loss降低学习率或加梯度裁剪
真机表现差传感器噪声对比仿真真机观测加域随机化和噪声
回合不终止覆盖率阈值过高检查覆盖率上限降到95%并加步数限制
动作抽搐平滑惩罚不足看动作差值加大平滑惩罚

6. 奖励工程的可迁移经验

这套10项复合奖励的框架不是清扫任务专属的。任何涉及“覆盖”“遍历”“探索”的任务都可以套用,比如农业植保无人机的喷洒路径规划、仓库机器人的盘点路线、甚至游戏AI的地图探索。

核心思路是把稀疏的终局奖励拆解成多个密集的中间奖励,每个奖励负责一个子目标,通过权重和衰减机制防止奖励黑客。这个思路在机械臂抓取任务里同样有效:抓取成功是稀疏奖励,但可以拆解成接近物体、调整姿态、闭合夹爪、抬升物体等中间奖励。

多智能体场景下,奖励工程还要考虑信用分配问题。比如多个机器人协作清扫,某个机器人扫得多、某个扫得少,怎么分配团队奖励?我的做法是用差异奖励,每个机器人的奖励等于团队奖励加上自己的个体贡献奖励,个体贡献用Shapley值近似计算。这个在交通信号灯控制的多路口协作里也有类似应用。

最后说一个我踩过的坑:不要试图用奖励函数解决所有问题。有些行为约束用动作空间限制更直接,比如限制机器人最大速度,直接在动作输出上加clip就行,不需要用奖励去引导。奖励工程是软约束,适合处理那些难以硬编码的偏好和权衡,比如“扫得快”和“扫得干净”之间的平衡。硬约束和软约束配合使用,效果比纯奖励工程好得多。

我在实际项目里还发现一个规律:奖励项的数目不是越多越好。10项是我试出来的平衡点,少于8项覆盖不全,多于12项权重调不过来,而且项与项之间容易冲突。如果你刚开始做奖励工程,建议从5项核心奖励起步,跑通了再逐步加项,每加一项都要重新调权,不要一次性堆上去。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询