首页 / 资讯中心 / 文章详情

多智能体强化学习路径跟随:从奖励设计到调参实战拆解

多智能体强化学习路径跟随:从奖励设计到调参实战拆解 ★ FEATURED ARTICLE
简介面向MATLAB/Simulink开发者的多智能体强化学习示例包聚焦自主路径跟踪控制场景。资源通过试错式学习训练两类智能体分别借鉴演员-评论家控制器与车道保持辅助技术思路适合需要快速上手强化学习建模、仿真与调参的中高级研究者和工程师。压缩包共7个文件、约595KB包括4个.m脚本智能体创建、参数配置、环境重置、1个.mat预训练模型、1个.slx系统级仿真模型以及1个.mlx交互式训练脚本其中.m脚本覆盖两类智能体的构建与奖励/学习率等关键超参设定.slx构建了多智能体与环境的交互拓扑结构清晰便于按模块拆解复现。该资源已有1128人学习读者既能借助.mlx观察完整训练流程也可直接加载预训练.mat模型验证效果并在此基础上修改状态空间、动作边界或奖励函数开展二次实验是探索多智能体协同路径跟踪的高效参考。1. 强化学习碰多智能体路径跟随一个示例把最难的问题拆成骨架先讲一个实际场景某物流枢纽的地面分拣区同时有3台AGV小车要沿着各自的路径把货物送到对应进出口。你用强化学习单独调一个agent跟路径跑了两百回合就收敛可三个agent放进同一个场地既要避让彼此又不能撞墙原来那套观察和奖励直接失灵。这个示例解决的就是从单车能跑到多车不乱的跨越。它把多智能体RL里最关键的观察构造、奖励分担和训练管理做成了一份可直接打开复现的骨架适合已经跑通过单智能体路径跟随、正被多车协同困扰的开发者。2. 这个示例到底在做什么观察空间、奖励函数与训练流程的逐层拆解2.1 观察空间与动作空间每个agent到底看到了什么多智能体路径跟随的第一公里不是算法而是每个车能看到什么。在这个示例里每辆车是平面运动学模型状态由位置x、y和航向角theta组成。控制输入是转向角steering和加速度accel这是连续动作空间所以这个场景下最常见的选择是DDPG或TD3这类连续控制算法而不是DQN。观察向量是最值得先读懂的部分。常见构造如下观察分量含义维度x_rel当前点与目标点的x偏差1y_rel当前点与目标点的y偏差1vx / vy当前速度在两轴上的分量2heading_err目标点相对航向与当前航向的差1path_idx当前跟踪到的路径点编号1other_agents其余agent在本车坐标系下的相对位置2×(N-1)把路径点坐标直接丢进观察并不是好主意因为路径坐标系一变网络就要重新学。示例里用的是相对量把绝对坐标转换成偏差和误差角这是路径跟随任务能泛化到不同路径的关键。动作空间的设计同样是连续量steering转向角归一化到[-1, 1]对应实际机械的横摆角accel加速度归一化到[-1, 1]负值代表刹车/倒车很多人第一次跑这个示例会疑惑为什么路径跟随不直接用PID而要训RL最直接的回答是PID参数是固定的而RL策略会自己权衡我现在偏离大不大、前方弯道多急、旁边有没有车这些条件一旦变化RL策略比固定增益更鲁棒。代价是训练不稳定第4章专门讲这个。2.2 奖励函数的设计逻辑路径跟随的收敛靠的不是误差惩罚这个示例的奖励函数值得逐项拆因为多车协同能不能收敛几乎全看奖励怎么分担。单agent跟踪一条路径的典型奖励每个仿真步先给一个小的负激励例如-0.01让agent学尽快结束任务避免原地打转。当本车与下一个目标点的距离小于阈值如0.1 m时给一个阶段性正奖励如10并推进到下一个路径点。横向位置偏差超过允许范围如0.5 m时给一个负惩罚如-1。多agent版本在此基础上叠加两项安全距离惩罚两车距离小于安全半径如1.0 m时每个相关agent都收到负奖励如-5。共享目标奖励所有agent到达终点后整组额外获得一个奖励用来抑制谁先到谁占便宜的局部最优。这里有个重要细节奖励要做个体全局的拆分。如果只用个体奖励训练出来的策略会倾向先堵住别人再去自己的目标点如果全局奖励权重太大能力强的agent会等弱的agent整体变拖沓。经验比例是个体奖励占70%到85%全局奖励占15%到30%。另外奖励在时间轴上的分配也要注意。阶段性的10如果给得太频繁agent会只盯着最近的下一个点忽略远处的大转弯如果给得太稀信用分配就更难。常见做法是每个路径点给相同的阶段性奖励只在终点给一个明显更大的值例如50。2.3 训练主循环从环境交互到策略更新的完整闭环示例的训练脚本不是简单调一个rlTrainingOptions就结束它把环境封装成多agent环境再交给训练管理器。多agent训练主循环的逻辑是初始化N个agent的策略网络与各自的经验池。每个episode开始时环境重置所有车辆到各自起点并选择一组路径。每个时间步各agent拿到各自观察向量分别输出动作。环境按N个动作同步推进一步注意是同步推进不是逐个推进。环境返回每个agent的下一步观察、个体奖励、以及是否终止。每条transition分别存入对应agent的经验池。每个agent按自己的mini-batch更新actor和critic。同步推进这一点容易被忽略。如果先把agent A的动作执行了再执行agent BB看到的对方位置就是旧数据多车避让策略会被学歪。示例在Simulink里用统一的采样时间步进所有agent在同一个tick更新状态这个设计在你自己搭环境时也要保持。主循环结构示意如下for ep 1:maxEpisodes obs reset(env); % 返回 N×1 的观察cell for t 1:maxStepsPerEpisode actions cell(N,1); for i 1:N actions{i} selectAction(policy{i}, obs{i}, noise); end [nextObs, rewards, done] simStep(env, actions); % Simulink同步推进一步 for i 1:N pushExperience(agent{i}, obs{i}, actions{i}, rewards{i}, nextObs{i}, done); updateIfReady(agent{i}); % 到达batch size才更新 end obs nextObs; end end这段逻辑里最值得注意的是每个agent各自的经验池是独立的共享经验不会让训练更容易反而会让策略趋同、失去多样性。updateIfReady这种分批更新方式比如每50个transition更新一次能减少梯度震荡。示例里真正的更新是交给内置训练器来做的但理解这个主循环能帮你debug。3. 把示例跑起来从加载模型到超参数逐项校准3.1 环境准备与工作区加载要复现这个示例需要MATLAB的Reinforcement Learning Toolbox和Simulink版本不能太旧。先打开示例所在文件夹把路径加入工作区cd(你的示例解压目录); openExample(rl/MultiAgentPathFollowingExample); % 如果通过官方示例安装器安装 MultiAgentPathFollowingData; % 生成本文要用的路径点与车辆参数 open_system(MultiAgentPathFollowingModel); % 打开Simulink模型第一句可能因安装方式不同而报错如果用不是官方示例安装器直接跳过openExample运行后面的数据脚本和模型打开命令就够了。运行数据脚本后工作区里会出现几个关键变量路径点数组如pathPoints是一个P×2矩阵、车辆参数结构体如vehParam包含轴距、最大转向角等。建议先打印一下这两个变量的尺寸和范围确认路径点坐标没有超出你预期的场地范围。Simulink模型里一般会有RL Agent模块和Environment模块。打开前先检查模型是否有Enable/Disable的子系统切换多agent示例通常用一个子系统的多个实例表示不同车辆每辆车共用一套环境函数、但各自带独立的状态。改动任何常数之前先跑一次原版的验证脚本确认原始参数下能出结果再谈改参数。3.2 超参数表逐项说明为什么lr要设成这个量级示例自带的一组超参数是经过调校的先别急着改。逐项看它们各自的职责和合理调节范围超参数示例典型值调整方向注意事项Actor学习率1e-4收敛慢但稳时保持或略降超过3e-4容易策略震荡Critic学习率5e-4训练初期方差大可降Critic过拟合会导致奖励虚高经验池容量1e6内存不足再降太小会让策略遗忘旧经验MiniBatchSize128行动作空间大时可升到256每次更新用时的增长接近线性折扣因子0.99任务周期长保持0.99以上低于0.95会变短视目标平滑系数1e-3波动大时降到5e-4目标网络软更新速率探索噪声标准差0.2训练中后期降到0.1固定不变会导致收敛后仍在抖learning rate的量级问题值得多说两句。DDPG这类actor-critic算法actor和critic的学习率通常差一个数量级critic偏快、actor偏慢。因为critic负责先估准价值函数actor再沿着价值函数的梯度走如果actor学得太快它会在critic还没估准的时候就跑到价值函数错误的高地上去。噪声标准差是很多人忽略的构造。0.2是针对动作归一化到[-1,1]来说的如果你的动作范围是[-5,5]同样的0.2噪声就太小了要同步放大。示例里把噪声加在动作层而不是参数空间层这个选择对连续控制的复现友好——参数空间噪声在每步不重采样时不现实。3.3 开始训练与中断恢复训练面板上的四个关键读数训练命令通常长这样trainOpts rlTrainingOptions(... MaxEpisodes, 3000, ... MaxStepsPerEpisode, 1024, ... ScoreAveragingWindowLength, 20, ... StopTrainingCriteria, AverageReward, ... StopTrainingValue, 800, ... SaveAgentDirectory, fullfile(pwd,agents)); train(trainingManager, trainOpts);训练开始后控制台每隔一段会打印当前episode的奖励、平均奖励、平均步数。我在真实项目中只盯四个读数不看别的平均奖励它的趋势比单集波动重要平均步数如果接近MaxStepsPerEpisode上限说明这个agent还没学会主动完成路径经验池利用率长期填不满就说明模拟步进太慢需要减少MaxStepsPerEpisode或者开并行是否出现NaN一旦出现基本是模型状态发散或Simulink求解器步长不合适不是超参数问题。中途断掉不要慌。DDPG训练时所有状态都存在工作区和agent对象里下次可以接着训% 下次接着训时直接加载上次保存的agent目录 agentData load(fullfile(pwd,agents,SavedAgent.mat)); train(agentData.agents, trainOpts); % trainOpts里MaxEpisodes按剩余量调整这里有个血泪经验训练中断恢复时建议把经验池一起保存。只保存网络权重而丢掉经验池恢复训练的前500个episode基本是在重新热身高成本区效果远不如不中断。示例自带的SaveAgentDirectory默认只存档agent对象如果经验池字段还在agent对象里就没事但如果你自定义封装把经验池放在外部一定要一并save。多agent训练还有一个实际瓶颈Simulink单步仿真往往要几百毫秒几千个episode下来可能跑一整夜。如果示例支持并行训练优先开Parallel Computing Toolbox设置numWorkers不小于4。并行之后每个worker跑一个episode但要注意经验池和agent对象每轮结束后要同步回主worker不然会瞎忙。我在4个worker的设置下跑同样的任务3000个episode从22小时缩到5小时多性价比很高。4. 多智能体路径跟随训练的常见问题排查四类翻车现象和对应的药4.1 所有agent训练到某一轮后奖励不再增长现象前几百个episode奖励稳步上升跑到约800轮左右开始横盘甚至略微下降再训几千轮也没起色。原因这个现象和单agent训练里的策略过早坍缩不太一样。多agent场景里更常见的原因是探索噪声的方差随时间衰减后agent已经找到了一个局部稳定解——比如绕远路但能到这个解的奖励比乱撞高但远低于最优解。DDPG的动作噪声一旦变小它很难自己跳出这个盆地。解决在训练中期强制做一次噪声重置。具体做法是把探索噪声的标准差从0.2调回0.3同时把actor学习率临时降到5e-5跑100轮后再恢复。另一种更直接的办法是用checkpoints取历史策略挑一个表现好的模型接着训而不是在当前这个死局上继续。如果示例的SaveAgentDirectory按episode自动存档就派上用场了。4.2 单agent能收敛、多agent一起训就发散现象把示例里的agent数量改回1训练一切正常改成3几个episode后奖励直接打穿下限之后再也回不来。原因我在这个问题上吃过亏本质不是算法坏了而是两个agent在同一个时间步采取了冲突动作导致环境状态跳到训练分布之外。比如两个车都朝同一个目标点加速距离小于安全半径触发惩罚而且这个状态又被写进了各自经验池策略越学越怕靠近任何东西最终车停在原地。解决第一道防线是加安全落回逻辑。当两车距离小于阈值时由环境直接修正动作比如强制减速到接近零而不是只给负奖励。第二道防线是把这类危险状态从经验池里剔除或降低它的采样权重。示例自带环境里不一定内置这个机制但你在改造版本中务必加上。4.3 路径跟随时车辆出现锯齿形摆动现象训练后评估车能跟着路径走但轨迹呈明显锯齿状横向偏差在±0.3m左右震荡看起来像醉酒驾驶。原因锯齿摆动的高发原因是奖励函数里到点给大奖励的频率太高导致agent学会了频繁切换目标点方向而控制动作本身没有平滑约束。另一个原因是对转向动作完全没有惩罚策略会让转向角高频大幅变化。解决在奖励里加动作变化率惩罚例如r_new r_old - alpha * abs(steer(t) - steer(t-1))alpha取0.05到0.1。改这个要重训但通常很快见效。示例里如果没加这项可以在自定义改写时补上。还有一个偏门原因Simulink采样的时间步太大比如0.1s以上让转向控制在一个步长里过度响应把固定步长降到0.02s或更小锯齿会明显减轻。4.4 训练完的agent在测试时表现远差于训练时现象训练过程中评估曲线很好但把agent部署到另一组路径上测试平均奖励跌去一半以上甚至撞上障碍物。原因这是过拟合到训练路径点分布了。示例里路径可能是固定的agent学会了在这几条路径的绝对坐标附近的表现而不只是跟随逻辑。观察空间里如果保留了绝对坐标x、y原始值或path_idx网络很容易依赖这些特征做捷径决策。解决一是把路径集增大并随机平移旋转让agent不能靠记坐标二是检查观察里是否可以直接去掉path_idx。路径点序号是个很强的身份特征去掉通常会提升泛化。示例的验证脚本一般会换一条新路径做评估如果你发现大跌优先怀疑观察里的绝对量不要先怀疑网络容量。5. 把这个示例改成自己的任务路径生成、动作空间与调度约束的三个改造点5.1 把固定路径换成动态路径从workspace变量到运行时更新示例里路径点往往以矩阵形式放在工作区Simulink模型在运行前从工作区读取。要改成动态路径我一般会写一个路径生成函数在每个episode开始时重新生成路径并灌进环境function pathPoints generateRandomPath(numPoints, bounds) % 随机生成一条光滑路径用三次样条插值噪声点保证曲率连续 ctrlPts rand(numPoints, 2) .* bounds; t linspace(0, 1, numPoints*5); pathPoints spline(1:numPoints, ctrlPts, t); pathPoints [pathPoints(1,:); pathPoints]; % 保持起点不变方便车辆初始定位 end这段函数的核心是用样条插值代替直线连接否则车辆在折线拐点处需要无穷大的转向角。路径生成完以后把每个路径点的期望朝向也算出来放进一个额外的列后续奖励函数用得上。动态路径下要先验证路径数量、间隔距离和车辆初始位置不冲突否则训练刚开始就出现死局。5.2 动作空间改造转向驱动与速度驱动两种构型的选择示例默认输出转向角加加速度这是转向-速度双通道构型。但实际项目里有两种常见变体纯转向驱动速度固定只输出转向角。适合分拣区匀速小车动作维度降为1训练更快但少了一个避险手段。纯速度驱动沿着固定轨迹只调速度适合已经完成路径规划、只需要调速的场景。双通道转单通道的改法是直接把输出层维度改成1同时在环境step里把加速度口接到常数0。反过来如果改成纯速度就需要在环境中预设一条路径让agent只能改变沿路径的前进速度。这些改动都要改环境的step函数而不是只改网络输出层。还有一个容易踩的点如果动作变少了探索噪声标准差的取值范围也要跟着收敛。单通道动作的噪声方差建议等比缩小到双通道的0.5倍以下否则动作边界频繁被打穿训练方差变大。5.3 多agent调度约束如何加入安全距离惩罚如果项目里agent数量多于3个比如6台小车在同一个交叉区调度只靠示例那套两两避让的惩罚就不够用了。建议把安全约束扩展为三部分两两距离惩罚原始DDPG奖励里已有。区段占用约束把路径分成若干段同一时刻同一段只能有一个agent违反就给强惩罚。这个比距离惩罚更防堵车。优先级偏置在奖励里按agent的任务优先级乘一个系数优先级高的agent接近目标点的奖励权重更大。分段占用计算逻辑可以这样写function penalty segmentOccupancyPenalty(pathIndices, segLen, penaltyPerAgent) % pathIndices各agent当前所在路径段编号 % segLen路径总段数 occCount histcounts(pathIndices, 1:segLen1); occupied occCount 1; penalty sum(occupied) * penaltyPerAgent; end调用时注意histcounts的边界段编号从1开始bin要写成1:(segLen1)才能不丢最后一段。这个函数每步调用一次计算量不大但注意它对所有agent返回同一个惩罚值多agent奖励回传时按统一值发给所有agent避免某一方单独背锅。这类改动的共性坑是奖励比例需要重新调。距离惩罚和区段惩罚同时存在时个别agent可能会学到停在入口不进去的消极策略因为进去就有机会触发碰撞惩罚。遇到这个情况把到达目标的奖励提高让完成目标的收益高于回避所有风险的收益多跑几个随机种子验证。6. 训练完成之后验证策略的稳定性与上线前的最后检查训练收敛不是终点路径跟随要落地重点在测试阶段。我每次训练完会做三件事。第一用蒙特卡洛方法验证策略稳定性。因为DDPG有探索噪声训练结束时保存的策略如果是带噪声的测试时必须关掉噪声再评估。用10组随机种子、每组换一条新路径记录每组的完成时间和平均横向偏差统计这10组结果的均值和方差。方差大说明策略对路径分布敏感要回头检查第5章观察空间里的绝对量而不是加更多训练。第二检查边界行为。把车辆的初始横向偏差人为加到偏离路径1米开外看策略能不能拉回来把初始航向角偏转±45度看策略会不会在起步直接原地打转。边界测试很残酷但能暴露奖励函数的死角。有一次我在测试里发现车在某个特定初始角度下会先倒车再转弯虽然不是错误但明显不高效在生产环境会让人觉得策略不可靠后来我在奖励里增加了一个对后退动作的小惩罚才改掉。第三把训练好的agent导出成部署形式。如果是Simulink环境会生成一个独立的评估模型把所有RL agent模块替换成无噪声推理模式如果是生成代码的场景要提前确认推理不依赖MATLAB运行时的工具箱函数否则部署阶段会很被动。我一般会提前用一个固定输入检查导出模型的输出与训练时代结果一致误差控制在1e-3以内再继续。从那以后我每次训练完都强制自己走一遍这个流程关噪声、换路径、测边界、看导出一致性。多agent路径跟随很多失败翻车都是倒在最后这一公里前面奖励设计做得再好少了这步都觉得悬。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站