
简介这是一份多智能体强化学习算法 MADDPG 的 Python 实现代码包面向正在学习或复现 MADDPG、DDPG 系列算法的开发者与研究人员。资源基于论文《Multi-Agent Actor-Critic for Mixed Cooperative-Competitive Environments》设计结合 DDPG 思想支持在混合协作与竞争的多智能体环境中训练策略包中还包含 MATD3 变体可对比单智能体与多智能体确定性策略梯度算法在不同场景下的表现。压缩包共 21 个文件约 24KB以 Python 源文件为主体另有配置文件、运行说明文本和编译缓存代码按环境构建、网络定义、经验回放、算法主体和主训练脚本等模块拆分结构清晰便于定位对应环节。资源已有 1305 人浏览学习适合希望在 MPE 等模拟环境中快速跑通 MADDPG 实验、进一步修改网络或奖励设置开展研究的读者。通过运行主程序可观察多智能体协作与竞争任务的训练过程并结合附带的说明文档和模型目录复现基础实验。单智能体算法跑不通多智能体任务你该认识一下MADDPG做多智能体强化学习MADRL的人基本都逃不开MADDPG这个名字。我第一次在合作式多智能体环境里直接套用DDPG时结果非常惨——智能体各自为政训练到后期直接发散根本不收敛。后来读了OpenAI那篇《Multi-Agent Actor-Critic for Mixed Cooperative-Competitive Environments》才明白问题出在哪里多智能体环境下每个智能体都在同时学习、同时改变策略对单个智能体来说环境是不断变化的传统单智能体算法里的“经验回放”机制会因此失效因为过去的经验很快就过时了。MADDPG解决的就是这一类问题。它全称是Multi-Agent Deep Deterministic Policy Gradient核心思路是“集中训练分散执行”。简单说训练时每个智能体的评判网络Critic能看到所有智能体的观测和动作相当于开了一个“上帝视角”但真正部署执行时每个智能体的决策网络Actor仍然只用自己本地的观测信息。这篇文章我会把它的原理、实现细节、容易踩的坑一次讲清楚适合刚入坑MADRL、想复现MADDPG或者已经在用但训练总不收敛的同学。1. 为什么多智能体环境会让普通强化学习失效1.1 非平稳性经验回放失效的根本原因在单智能体环境中智能体的状态转移只取决于环境本身和自己的动作环境是相对稳定的所以经验回放里存的历史样本仍然能反映当前环境的动态。但在多智能体环境中每个智能体都在学习、都在改变自己的策略对某个智能体来说其他智能体的策略变化等同于环境在变化。举个例子。在追逃场景里追捕者A学习到“向左包抄”的策略后逃跑者的状态分布就会变化因为逃跑者会针对追捕者的动作做出反应。追捕者B从经验池里抽出的旧样本可能是逃跑者还在“直着跑”的时候产生的拿这些样本更新策略得到的梯度方向其实已经过时了。这就是所谓的非平稳性问题non-stationarity。经验回放本质上假设环境是平稳的这一假设在多智能体场景里被打破算法自然就难收敛。1.2 简单套用DDPG/PPO会遇到的具体问题我曾经在一个简单的接力协作任务里试过直接用DDPG每个智能体独立训练一个Actor和Critic结果出现了几个非常典型的现象智能体学到中途突然退化明明上一轮已经能完成接力下一轮又完全失效。两个智能体为了抢同一个目标反复震荡谁也不让谁。性能曲线波动极其剧烈看起来像在“随缘学习”。这些现象的本质就是每个智能体的Critic只能看到自己的观测对其他智能体的行为一无所知。它对价值函数的估计建立在一个会移动的沙地上自然无法给出稳定的梯度信号。1.3 MADDPG的关键回应把“环境变化”装进Critic的输入里MADDPG的做法非常直接既然环境变化来自其他智能体的策略在变那就让Critic在训练时看到所有智能体的观测和动作。这样Critic在估计Q值时就把其他智能体当前的行为纳入了考量非平稳性带来的影响被显式建模。而Actor保持只用局部观测做决策这就保证了部署时每个智能体依然是一个独立、可执行的个体不需要中心控制器在运行时下发指令。这种设计思路也奠定了后续一大堆CTDECentralized Training with Decentralized Execution算法的基本范式。从MADDPG衍生出的变体和改进非常多理解它是理解整个MADRL算法家族的地基。2. 算法架构拆解集中训练、分散执行具体是怎么实现的2.1 Actor和Critic的结构差异MADDPG是DDPG的多智能体扩展所以它保留了Actor-Critic架构。这里最关键的一点是每个智能体都有自己的Actor和Critic但各个智能体的Critic不是共享的而是各学各的。假设有N个智能体每个智能体i的动作记作$a_i$观测记作$o_i$。Actor策略网络输入是$o_i$输出是确定性的动作$a_i \mu_i(o_i)$。它只依赖自己的观测训练和执行时都一样。Critic价值网络输入是$x (o_1, o_2, \dots, o_N, a_1, a_2, \dots, a_N)$输出是$Q_i(x, a_i)$。它看到的是全局信息所有智能体的观测和动作。为什么要让Critic看到全部观测和动作而不只是把其他智能体的动作加进去因为观测包含了环境状态信息比如位置、速度、剩余资源等这些信息对判断当前局面非常关键。只给动作不给观测Critic很难知道其他智能体现在处于什么状态Q值估计会失真。所以MADDPG默认使用$o_1, \dots, o_N, a_1, \dots, a_N$的全量拼接。2.2 它的Q函数更新规则和单智能体有什么不同单智能体DDPG中Critic的损失函数是$$L(\theta^Q) \mathbb{E}\left[\left(Q(s, a) - y\right)^2\right]$$其中目标值 $y r \gamma Q(s, \mu(s))$用目标网络算。MADDPG把这里的$s$换成了$x (o_1, \dots, o_N, a_1, \dots, a_N)$$s$换成了$x (o_1, \dots, o_N, a_1, \dots, a_N)$同时每个智能体i的Actor目标值用的是目标Actor输出的动作$$y_i r_i \gamma Q_i(x, \mu_1(o_1), \dots, \mu_N(o_N))$$注意目标Critic的输入里其他智能体的动作不是它们当前Actor的输出而是它们目标Actor的输出。这个细节很关键一定程度上缓解了目标网络更新时的非平稳性。2.3 策略梯度的推导直觉为什么Actor只用局部梯度Actor的更新遵循确定性策略梯度定理。对每个智能体i策略梯度是$$\nabla_{\theta_i} J(\mu_i) \mathbb{E}{x \sim D}\left[\nabla{\theta_i} \mu_i(o_i) \cdot \nabla_{a_i} Q_i^\mu(x, a_i) \big|_{a_i \mu_i(o_i)}\right]$$直觉上这条公式的意思是Actor想找一个能让Critic打分更高的动作。Critic已经经过训练知道在“给定所有人当前观测和动作”的情况下智能体i的动作值多少钱。所以Actor只需朝价值上升最快的方向调整自己的输出即可。因为Critic看过全局信息包括其他智能体的观测它给出的价值估计本身已经蕴含了“其他智能体可能的反应”所以Actor虽然只用局部观测做决策梯度方向却比单智能体版本更稳健。这就是MADDPG能够在合作、竞争、混合环境下都工作的原因。3. 训练流程与工程实现经验回放、目标网络和噪声策略3.1 训练流程的完整步骤实现MADDPG时最正确的训练循环应该是下面这个流程初始化每个智能体的Actor网络、Critic网络以及对应的目标网络分别记作 $\mu_i, Q_i, \mu_i, Q_i$。清空经验回放缓冲区。经验缓冲区里存的是转移五元组 $(o_1, \dots, o_N), (a_1, \dots, a_N), (r_1, \dots, r_N), (o_1, \dots, o_N), done$。每个回合开始前给所有Actor添加探索噪声通常用Ornstein-Uhlenbeck噪声或高斯噪声。环境步进得到上述五元组存入经验缓冲区。从缓冲区采样一个batch。对每个智能体i用目标网络计算目标值 $y_i$。更新Critic最小化$(Q_i(x, a_i) - y_i)^2$。更新Actor最大化$Q_i(x, \mu_i(o_i))$。软更新目标网络$\theta \leftarrow \tau \theta (1 - \tau)\theta$。重复4~6步直到策略收敛。有一点值得注意经验回放缓冲区中的五元组必须是完整的多智能体状态而不是单个智能体的状态和动作。我见过好几个新手实现把每个智能体的转移分开存结果Critic训练时根本拼不出完整的$x$算法当然学不出来。缓冲区里存的是整个系统的一步转移每个样本包含所有智能体的观测、动作和奖励。3.2 目标网络和软更新参数选择MADDPG沿用了DDPG的目标网络机制。目标网络的作用是让TD目标在一段时间内保持稳定避免Q值更新时出现“同时移动靶心”的震荡问题。多智能体场景下这个机制尤其重要因为非平稳性比单智能体更强如果目标网络更新太快训练必然发散。软更新系数$\tau$建议取0.01或0.001。我自己的经验是0.01在多数粒子环境任务上够用但如果任务奖励稀疏或者训练噪声大降到0.005会更稳定。$\tau$越大目标网络越接近实时网络训练越不稳定$\tau$越小学习越慢但不容易震荡。3.3 探索与利用的平衡DDPG输出的是确定性动作如果不加噪声Actor一旦收敛到某个区域就再也探索不出来新路径了。MADDPG常用两种噪声Ornstein-Uhlenbeck噪声时间相关适合惯性系统输出平滑。高斯噪声简单直接在某些任务上表现也不差。实际测试中OU噪声在连续控制任务里的探索更平滑但需要调$\sigma$和$\theta$两个参数高斯噪声只有一个$\sigma$更容易调。我一般先固定高斯噪声把一个简单合作任务跑通再换OU噪声精调这样能少走弯路。4. 复现和调参中遇到的坑从梯度爆炸到奖励误设计4.1 梯度爆炸问题及其处理MADDPG训练中最常见的问题就是loss突然变成NaN。批评网络的输入是所有智能体的观测和动作拼接维度比单智能体高很多深层网络很容易出现数值不稳定。处理手段是梯度裁剪。我在每个Critic的更新里都加了clip_norm数值设为0.5或1.0。某些实现里还会给Actor也加裁剪但我发现Actor一般不需要因为它的梯度是价值函数对动作的导数数值通常不会爆炸。真正容易爆炸的是Critic的TD loss特别是奖励尺度很大或者奖励设计有误的时候。4.2 奖励设计不当几乎等于白训MADDPG本身不包含任何奖励重塑机制但它对奖励的敏感度非常高。在多智能体任务里如果每个智能体的奖励完全独立比如“每个智能体各自到达自己的目标点”没有共享、没有对抗那MADDPG和独立DDPG没有太大区别因为智能体之间几乎不存在交互。如果任务有合作成分我强烈建议在共享奖励上叠加大小的个体奖励。纯共享奖励会导致个体贡献不明确Critic很难给每个Actor提供有区分度的梯度纯个体奖励又会让大家各自为政不配合。合适的做法是设定一个团队目标比如“任何一个智能体到达终点团队都得1分”再给每个智能体一个小的过程奖励比如“离终点近了奖励0.01”这样Actor能感知到自身行为的影响Critic也能学到全局价值。4.3 一个典型的多智能体环境配置对比MADDPG论文里用的实验环境是粒子环境MPEMulti-Agent Particle Environment里面有几种典型任务。我整理了一份简要对比表任务类型智能体数量动作空间奖励结构训练难度Cooperative Communication2离散通信动作完全共享奖励中等Predator-Prey3个追捕者、1个逃跑者连续追踪者共享奖励逃跑者独立奖励较难Physical Deception2个合作者、1个对手连续合作者共享奖励对手独立奖励困难Keep-Away2个合作者、1个对手连续合作者共享奖励对手独立奖励中等偏难需要注意一点MADDPG原始论文里对离散动作任务做的是Gumbel-Softmax近似让离散动作可微从而复用连续策略的梯度。如果你直接在离散动作上实现MADDPG会遇到Actor输出一个概率分布但Critic接收的是采样后的离散动作梯度无法回传的问题。可以选择把Critic的输入改为所有智能体动作的logits拼接也可以在Actor输出层用Gumbel-Softmax代替普通softmax让整个网络端到端可微。我建议在简单任务上用Gumbel-Softmax效果直接且不用改Critic结构。4.4 和其他CTDE算法的区别与联系很多人拿MADDPG和QMIX、MAPPO做对比。它们都属于CTDE框架但适用场景不同MADDPG适合连续动作、中小规模智能体数量。QMIX适合离散动作、完全合作的场景因为它基于价值分解把团队的Q值分解成每个智能体的Q值之和需要严格的单调性约束。MAPPO适合高维状态、大规模智能体但需要处理策略梯度的方差问题对并行效率要求更高。如果你面对的是粒子环境这类小型任务MADDPG是首选基线如果是星际争霸、谷歌足球这类高维环境MAPPO会明显优于MADDPG。5. 一些基于实操的改进思路5.1 集成TD3的多智能体版本MADDPG的Critic存在高估问题DDPG系列都有这个问题。后来的MATD3算法把TD3的“双Critic取最小”拓展到多智能体场景配合目标策略平滑有效缓解了价值高估。我的经验是在奖励比较稀疏或任务难度高的环境里用MATD3替换MADDPG收敛速度和最终得分都有显著提升。MADDPG适合快速验证环境、跑通流程MATD3适合认真对待实验效果时使用。5.2 参数共享与注意力机制的取舍MADDPG的Critic输入维度随智能体数量线性增长。智能体一多Critic的隐藏层参数会变得非常大训练成本成倍增加。如果需要对所有智能体共享一套Actor和Critic网络可以减少参数量但需要注意各智能体的观测维度是否相同且共享参数的训练容易出现策略同质化导致所有智能体学会做一模一样的事。注意力机制比如ATT-MADDPG能解决部分维度问题但实现复杂度较高。5.3 我建议的调参顺序如果你打算从零复现MADDPG我建议按这个顺序来调先让整个训练循环跑通用一个简单合作任务比如两个智能体同时向中心点靠拢确认loss不NaN、reward能上升。再调噪声系数和$tau$观察探索能力和稳定性。然后调Critic网络结构比如隐藏层数量、激活函数看看Q值变化是否平稳。最后再改环境和奖励设计做真实任务测试。顺序不要颠倒。很多人一上来就调网络结构结果loss爆炸都不知道是哪里出的问题浪费大量时间。5.4 用经验池采样时要注意样本分布MADDPG的Critic在训练时看到的是全量观测和动作拼接。如果你在做并行采样多个环境的经验混在一起经验池里不同的任务进度、不同的智能体组合状态会造成样本分布非常宽。我推荐根据训练阶段调整经验池大小。早期可以大一点保存更多探索样本后期训练趋于稳定时适当缩小让网络更快跟上当前策略的分布。6. 实际使用感受我自己的经验是MADDPG最大的价值在于它是一个非常优秀的多智能体算法入门框架结构清晰、原理直观、可扩展性强很多改进版本都是在它的结构上做加法。但它不是万能的尤其是在大规模智能体、高维连续控制的场景下直接使用它的效果并不理想你需要根据任务特点选择合适的变体或更新一代的算法。在做实际项目前先花时间搞清楚你的任务是合作、竞争还是混合动机这比一头扎进调参重要得多。如果你正在复现MADDPG并遇到不收敛的问题先检查经验回放缓冲区有没有保存完整的全局转移再看目标网络更新是否太频繁最后检查奖励值设计有没有提供有效的梯度信号。把这三步走完大部分问题都能定位。祝你好运。本文还有配套的精品资源点击获取