简介:这是一份面向多智能体强化学习研究者的MADDPG算法配套环境资源,内置多种典型粒子场景(如追捕、协作搬运等),用于验证协同与竞争策略,适合正在学习MADDPG或需要标准化测试平台的开发者使用。压缩包共24个文件,以Python源码为主(21个py),另含README说明、环境配置文件等,整体仅32KB,轻量易部署。资源已有1397人学习,代码中提供环境定义、智能体模型、训练循环及可视化工具,结构清晰,支持调整智能体数量、视野范围、目标位置等参数,方便研究者定制实验、对比算法性能,是深入理解多智能体交互与策略学习的实用工具。
1. 为什么讨论MADDPG,总绕不开“环境”这个词
我最早接触MADDPG的时候,犯过一个很典型的错误:拿到论文出的代码,先把算法结构、网络更新逻辑、Replay Buffer这些核心模块翻了一遍,心想“这算法也没多复杂啊”,然后直接往自定义环境里一扔,结果训练根本收不敛。后来我才意识到,在MADDPG这类多智能体强化学习里,环境并不是算法之外的附属品,它决定了你能否观察到多智能体协作、博弈、通信这些核心现象,也直接决定了你的实验结论站不站得住脚。
MADDPG的全称是Multi-Agent Deep Deterministic Policy Gradient,核心思路是在Actor-Critic框架下,每个智能体的Critic可以获取所有智能体的观测和动作,从而缓解环境非平稳性问题。这个机制听起来很优雅,但它有个隐含前提:环境的智能体数量、动作维度、观测类型都要和Critic的输入结构匹配。所以环境设计本质上是在回答“你要验证什么问题”这件事。
我在本文里想做的,是把MADDPG实验里常见的几类环境——从论文里最常用的MPE粒子环境,到SMAC、Multi-agent MuJoCo、PettingZoo这些更有挑战性的平台——逐一拆开来看。每个环境对应什么研究问题、动作空间怎么设置、训练时有什么坑,都会涉及。如果你是刚入门多智能体强化学习的研究生或者工程师,这篇文章可以帮你省掉不少选环境的试错成本。
2. 最经典的MPE粒子环境逐个拆解
很多读过MADDPG论文的人,第一次复现代码时用的都是OpenAI的MPE,全称Multi-Agent Particle Environment。它本质上是一个2D粒子世界:智能体是一个个圆形粒子,在世界里移动、碰撞、与地标交互,所有坐标都是连续值。为什么MADDPG选它做基准?因为粒子环境能极其干净地控制变量——你想研究通信,就开communication开关;你想研究对抗,就加对手;你想研究协作,就把目标函数设计成共享奖励。这种“搭积木”式的场景设计,对算法分析来说是巨大的优势。
2.1 simple与simple_spread:入门必写的两个场景
simple这个场景最简单:一个智能体,一个地标,目标是指数逼近地标。它的观测空间是智能体自身位置和地标位置的连线向量。很多教程把它当作“MADDPG能跑通的Hello World”,但说实话,单智能体场景不太能体现MADDPG的优势——它本质上是DDPG也能解决的问题。我建议直接跳到simple_spread。
simple_spread是三个智能体、三个地标的协作场景,目标是让每个地标都被至少一个智能体覆盖,同时智能体彼此之间不要碰撞。这里有几个值得注意的细节:第一,每个智能体的奖励是它到最近地标距离的负值,所以如果两个智能体同时冲向同一个地标,后到那个就会拿到很低的奖励,这倒逼智能体学会分配任务;第二,观测空间里包含所有地标的位置,但不包含其他智能体的意图,所以智能体必须从其他智能体的位置变化中推断协作策略。我在实际训练中发现,如果Replay Buffer大小设置得太小(比如低于5000),这个场景很容易出现“三个智能体全部挤向一个地标”的局部最优,因为早期的随机探索让它们形成了不好的行为惯性。建议buffer容量至少10万起步,探索噪声用Ornstein-Uhlenbeck过程而不是简单的高斯噪声,收敛速度会有可感知的提升。
2.2 simple_adversary与simple_push:对抗博弈设计的教科书
simple_adversary是我个人非常喜欢的一个场景,它把多智能体强化学习里的“对抗博弈”讲得很透彻。场景里有1个对手、1个猎物、1个地标,但只有对手知道地标的真实位置。猎物的目标是靠近地标,对手的目标是靠近猎物(因为跟随猎物就等于间接找到了地标)。这个设置的精妙之处在于:猎物得到的观测中根本不含地标坐标,它必须学会“解读对手的运动轨迹”来判断地标在哪里。MADDPG在这个场景里的表现比DDPG单独训练每个智能体要好很多,原因是Critic共享了全局信息,让猎物可以从对手的行为中“蒸馏”出有用信号。
simple_push则更复杂一些:两个智能体(一个推者、一个被推者)和一个地标。推者要把被推者推到地标位置,被推者要逃跑。这个场景里动作维度和物理碰撞的影响更大,智能体不能“穿墙”,只能靠真实的推力交互实现目标。我在跑simple_push的时候发现,训练的稳定性对随机种子非常敏感,同一个超参数换一个seed,收敛曲线能差出一倍。所以我的习惯是每个场景至少跑5个随机种子,取中位数画曲线,不要只是单次运行就下结论。
2.3 simple_tag与simple_world_comm:通信与欺骗的微妙平衡
simple_tag是MPE里最激烈的对抗场景:3个红色追捕者、1个蓝色逃跑者,追捕者要围堵逃跑者,逃跑者要躲避追捕。这里有个很反直觉的现象:逃跑者的体力和速度参数如果设置得和追捕者一样,MADDPG训练出来的追捕策略往往倾向于直接“冲撞”而不是“围堵”,因为围堵需要更长时间才能看到正奖励。要让逃跑者学会真正的“蛇皮走位”,需要把逃跑者的最大速度调高一些,让追捕者必须协作才能抓到它。
simple_world_comm则是在simple_tag基础上加了通信信道和一些地域限制。智能体可以通过一个低维通信向量互相“喊话”,但这个通信向量不是免费的——它占用动作维度,且通信内容可以被对手窃听。这个场景非常适合研究“对手感知下的通信策略”,我在测试中观察到,MADDPG的智能体确实会学会在不同情境下发送不同类型的通信向量,但如果你强制通信向量维度设置过大(比如超过10维),智能体会倾向于“什么都想说”,反而导致策略收敛变慢。通常3到5维的通信向量就够用了。
3. 走出粒子世界:SMAC、MAMuJoCo、PettingZoo这些环境能带来什么
MPE虽然好用,但它有个明显的短板:动作空间是连续的低维控制,智能体同构性强,环境规模偏小。如果你研究的问题是分层决策、大规模异构智能体协同、或者离散动作下的团队配合,MPE就有点力不从心了。这也是为什么近些年越来越多的论文开始用SMAC和Multi-agent MuJoCo作为补充实验环境。
3.1 SMAC:星际争霸2征服者地图,从连续控制走向离散决策
SMAC,全称StarCraft Multi-Agent Challenge,是建立在星际争霸2上的多智能体对战环境。它把游戏抽象成一组“战斗小场景”:每个场景里有若干我方单位和敌方单位,单位类型有近战、远程、治疗等区分,每个单位要么移动,要么攻击某个敌人,动作空间是离散的。为什么MADDPG在这类环境上表现不如MAPPO、QMIX这些算法?根本原因在于MADDPG的Critic需要接收所有智能体的观测和动作,一旦智能体数量达到十几二十个,Critic的输入维度会爆炸,而且离散动作空间让确定性策略梯度的计算不再那么自然。我见过一些强行在SMAC上跑MADDPG的实验,效果通常不太理想。但如果你就是想做“MADDPG的变体改进”,SMAC仍然是一个很好的试金石,它能帮你暴露算法在规模扩展性上的短板。
3.2 Multi-agent MuJoCo:物理引擎支持的具身多智能体控制
Multi-agent MuJoCo(简称MAMuJoCo)是把MuJoCo里的单个机器人模型“切分”成多个部分,每个部分由一个独立智能体控制,比如把蚂蚁的每条腿分别交给一个智能体。这个环境的优势是物理仿真更真实,动作空间在高维连续空间里,智能体之间共享同一个身体,必须学会协调发力才能让身体前进。MADDPG在MAMuJoCo上表现相对MPE要吃力一些,因为高维连续动作空间加多智能体协作会让Critic的训练方差变大。我的经验是,在MAMuJoCo上使用MADDPG时,梯度裁剪和更小的学习率是必须的,否则很容易出现loss爆掉然后策略直接退化的现象。另外,把每个智能体的观测里加入邻接智能体的局部信息(类似Graph Neural Network的思路)会比单纯全局Critic更有效,这一点在很多改进论文里已经验证过了。
3.3 PettingZoo:把整个环境库打包到你面前
PettingZoo是Farama Foundation维护的多智能体环境库,可以理解为Gym的“多智能体版本”。它内部集成了粒子环境、经典的Atari双人游戏、棋牌类游戏、物流调度环境等几十种场景,API风格接近Gym,迁移成本很低。我特别推荐它的一点是ParallelEnv接口:MADDPG这类算法天然适合并行环境交互——所有智能体同时决策、同时执行,而PettingZoo的ParallelEnv正好贴合这个逻辑,省去很多为转接数据格式写的胶水代码。
不过PettingZoo也有个让人头疼的地方:环境版本更新相当频繁,不同版本间的API变动不小。我踩过一个具体的坑:之前用某个版本的pettingzoo.mpe时,环境返回的观测是字典格式,而另一个版本又变成了数组格式,导致MADDPG代码里的经验回放逻辑全部要改。所以如果你在网上找了一个MADDPG开源实现,记得先检查它锁定的PettingZoo版本,尽量别用最新版直接跑旧代码。
4. 环境选型怎么定?先想清楚你要验证什么结论
这个问题我经常被问到:“博主,我想研究多智能体强化学习,应该从哪个环境开始?”我的回答通常是:先别问环境,先问你自己,你想通过实验得出什么结论。
不同的研究问题需要环境具备不同的“验证力”。我用一张表来梳理一下环境和研究问题的对应关系:
| 你想验证的结论 | 推荐环境 | 原因 |
|---|---|---|
| 多智能体协作任务分配 | simple_spread | 场景简洁,共享奖励,便于可视化分析 |
| 对抗博弈中的信息隐藏 | simple_adversary、simple_push | 信息不对称是环境的天然属性 |
| 通信协议的学习 | simple_world_comm | 显式通信信道,可调节通信代价 |
| 大规模异构单元协同 | SMAC | 单位类型丰富,动作离散,规模可扩展 |
| 高维连续运动控制 | Multi-agent MuJoCo | 物理引擎逼真,动作空间高维连续 |
| 算法基准横向对比 | PettingZoo | 多种环境统一API,对比公平性好 |
如果你是刚入门做研究,我建议的路径是:先用simple_spread跑通MADDPG的完整流程——数据收集、集中式训练、分布式执行、画学习曲线。然后换到simple_adversary,体验一下“环境信息不对称”对算法的影响,再决定要不要往SMAC或MAMuJoCo方向深入。这条路走下来,你对多智能体强化学习的直觉会比直接套一个复杂环境要扎实得多。
这里我特别提醒一点:不要一开始就追求“环境越难越有成就感”。环境复杂度的增加,往往意味着训练时间的指数级增长和大量无法预料的调参问题。我在实验室见过太多人第一天就把SMAC跑起来,结果一个月都在纠缠“为什么我的奖励毫无上升趋势”,最后连算法本身都没吃透。
5. 搭建MADDPG环境时,我踩过的坑和最后留下的配置
写到这里,我应该把maddpg环境搭建和运行过程中那些“代码之外”的教训分享一下。这些东西论文里不会写,但你会100%遇到。
5.1 版本问题:Python、PyTorch、OpenAI Gym三方博弈
MADDPG的开源实现大多是2017到2018年之间的代码,那会儿OpenAI Gym还在用gym.make、环境ID是字符串的时代。你如果直接用最新版Gym去跑老代码,会碰到一个经典报错:AttributeError: module 'gym.envs' has no attribute 'make',甚至干脆找不到multiagent这个环境。
我的建议是:要么创建一个干净的conda环境,锁定Python 3.8 + PyTorch 1.8左右 + Gym 0.21(这套组合我自己验证过可以稳定跑通MPE);要么找那些已经适配新版Gym的fork版本。使用conda创建环境的命令很简单:
conda create -n maddpg python=3.8 conda activate maddpg pip install torch==1.8.1 pip install gym==0.21.0注意:不要在同一环境下同时装多版本Gym,我也见过有同学想通过改环境变量来绕过版本冲突,结果某个包运行时会默默加载到错版本,然后出现各种奇怪的维度不匹配错误,极难排查。
5.2 训练稳定性问题:种子、归一化和奖励尺度
MADDPG训练不稳定的情况普遍存在,但很多时候不是算法的问题,而是环境交互的“数字卫生”没做好。我踩过比较深的一个坑是:粒子环境中状态值的尺度差异过大。simple_adversary里,智能体坐标的数值范围在[-1, 1]之间,而奖励计算涉及距离差,一旦环境初始化时有几个智能体恰好相距很远,早期样本的reward会大得离谱,导致Critic的loss在头几千步内震荡剧烈。
解决办法是加一个一维的Reward Scaling:把每个时间步的奖励除以一个常数(比如10或100),或者用Running Mean统计奖励的均值和方差做归一化。MPE场景里,最简单的处理就是把reward乘一个0.1系数,训练曲线的平滑度会有非常明显的提升。
种子的问题,我前面提到过:MADDPG对随机种子很敏感。因为Replay Buffer的初始采样随机性、网络参数初始化随机性、探索噪声随机性三者叠加,会让不同种子的收敛路径差别很大。我的建议是,每个配置至少跑5个种子,用平均回报和方差画曲线。如果某个种子效果特别差,先查这个种子下的探索噪声在早期是否积累了极端样本,必要时可以给噪声过程加一个衰减系数,让探索力度随时间下降。
5.3 自己写环境时要注意什么
如果你最终要面对的是一个自定义的MADDPG环境(比如机器人队形控制或者交通信号协同),自己写环境时的关键约束是MADDPG的训练框架对环境的接口要求。你需要确保环境提供以下几个接口:
- 每个智能体在每一步都能拿到独立的观测,并且观测维度要固定;
- 环境实现
reset()后返回所有智能体的初始观测; step(action_dict)接收一个字典,键为智能体ID,值为动作向量;- 每一步返回观测、奖励、done、info四个元素,且done要区分全局终止和局部智能体终止。
另外,一个经常被忽略的细节是“智能体的相对编号稳定性”。MADDPG的Critic在训练时将每个智能体的观测和动作拼接成一个大向量的顺序是固定的。如果你的环境每次reset()时智能体ID的排列顺序是随机的,Critic就会学到完全混乱的映射,导致训练发散。我遇到过一个真实案例:环境里智能体是动态加入和退出的,结果网络输入维度直接不匹配。所以如果你要设计动态数量智能体的环境,需要在MADDPG框架之外先做维度对齐,比如用注意力机制替换拼接。
6. 结合我的实际经验,给新手的一个环境起步策略
最后说一下我个人的起步建议,算不上什么高大上的方法论,但确实能帮你少走弯路。
第一步,先把MPE里最简单的simple场景跑通一次完整的训练和可视化过程,哪怕它不需要多智能体协作。这一步的作用是确认你的代码链路没问题,环境安装成功,画图脚本能输出保存的轨迹。
第二步,立刻切换到simple_spread,把训练脚本里的环境名改掉,观察三智能体是否学会了“分工占点”。如果智能体总是挤在一起,优先检查探索噪声系数是否过大、奖励是否在正确的尺度上。这个场景能跑出稳定的协作行为后,你对MADDPG的直觉就不会再是“背公式”了。
第三步,尝试调低MPE环境里的num_landmarks或者num_agents,构造一个不平衡的配置,比如2个智能体覆盖4个地标。这种“不对称”的配置对算法是个很好的压力测试。如果你能做到让两个智能体在不对称任务下依然稳定协作,再去碰SMAC或者MAMuJoCo都不迟。
我在实际跑实验时,还有一个长期保留的习惯:每次训完一个环境,会把环境和算法的超参数组合记录到一个固定的表格里。因为MADDPG实验涉及的超参数太多了——actor学习率、critic学习率、探索噪声、reward缩放、buffer容量、batch size、tau——每次实验都重新翻代码回忆参数是一件极其消耗精力的事情。这个小习惯帮我省下了大量重复排查的时间。
多智能体强化学习这个方向,算法更新换代非常快,但环境作为“实验的锚点”,它的重要性不会改变。无论你最后是去研究MAPPO、QMIX,还是在MADDPG的思路上做改进,理解环境的结构、理解环境与算法之间怎么相互制约,都是一项值得长期积累的基本功。希望这篇环境拆解能帮你把MADDPG的实验起点踩得稳一点。
本文还有配套的精品资源,点击获取