资讯动态

MADDPG多智能体博弈对抗Python源码复现与调参避坑指南

发布时间:2026/9/28 11:39:02 来源:尧图企业网站定制
简介本资源为面向毕业设计与课程实践的多智能体博弈对抗算法源码包基于MADDPG多智能体深度确定性策略梯度实现适合具备一定机器学习、深度学习与强化学习基础的学生和研究人员用于理解连续动作空间下多智能体协作与对抗的完整训练流程。压缩包共13个文件以10个Python源码为主涵盖环境构建、智能体初始化、Actor-Critic网络搭建、经验回放与训练主循环等模块另含cfg配置文件、txt说明与md文档整体约12KB结构紧凑便于按模块阅读。代码中加入了详细中文注释可帮助读者对照算法原理梳理中心评论家与各智能体演员网络的实现细节并支持在此基础上修改参数、扩展场景或改进性能。目前已有122人学习下载可作为多智能体博弈方向毕业设计的重要参考起点。1. 从零复现 MADDPG 多智能体博弈对抗这套 Python 源码到底能跑出什么如果你正在做毕业设计选题落在「多智能体博弈对抗」上大概率绕不开 MADDPG 这个算法。它全称 Multi-Agent Deep Deterministic Policy Gradient是 OpenAI 在 2017 年那篇Multi-Agent Actor-Critic for Mixed Cooperative-Competitive Environments里提出的核心贡献就一句话把 DDPG 从单智能体扩展到多智能体用「集中训练、分散执行」的思路解决环境非平稳问题。这套 Python 源码加详细注释的组合本质上是给你一个能跑通、能改、能写进论文实验章节的完整工程骨架而不是一段孤立的算法伪代码。它适合谁适合已经学过强化学习基础、知道 Q-Learning 和策略梯度大概在干什么、但一上手多智能体就懵的本科生和低年级研究生。你会遇到的核心痛点无非三个环境怎么搭、每个智能体的 Actor 和 Critic 怎么共享信息、训练不收敛时到底该调哪个参数。这套源码的价值就在于把这三个问题用可运行的代码摊开给你看。下面我按「先立住理论、再动手复现、最后讲坑」的顺序把整个方案拆开讲清楚。2. MADDPG 的算法骨架集中训练分散执行到底怎么落地2.1 为什么多智能体不能直接套单智能体 DDPG单智能体强化学习有一个隐含假设环境是平稳的转移概率不随策略变化。但多智能体场景下每个智能体都在学习、都在更新策略从任意一个智能体的视角看其他智能体的行为一直在变环境就变成了非平稳的。你直接拿 DDPG 给每个智能体各训一份Critic 估计的 Q 值会剧烈震荡训练曲线基本是玄学。MADDPG 的解法是训练时让每个 Critic 看到全局信息也就是所有智能体的观测和动作拼在一起执行时每个 Actor 只用自己的局部观测做决策。这就是「集中训练、分散执行」CTDE。Critic 的输入维度是sum(obs_dim) sum(action_dim)Actor 的输入维度只有自己的obs_dim。这个设计让 Critic 能评估「在所有人当前动作下我这一步走得好不好」从而缓解非平稳。2.2 源码里四个核心模块的职责划分一套标准的 MADDPG Python 实现通常拆成四个文件或四个类。我按常见做法给你梳理清楚你拿到源码后可以对照着看模块职责关键输入输出Actor策略网络局部观测映射到动作输入 obs_dim输出 action_dim末层 tanhCritic价值网络全局状态动作映射到 Q 值输入全局 obsaction输出标量 QReplayBuffer存储所有智能体的转移元组存 (obs_n, action_n, reward_n, next_obs_n, done_n)MADDPG Agent组织更新逻辑、软更新、动作加噪协调上面三个暴露select_action和updateActor 末层用 tanh 是为了把动作压到 [-1, 1]如果你的环境动作范围不是这个区间需要在环境侧做缩放。Critic 的输入拼接顺序必须固定训练和推理时不能一个按 obs 在前、一个按 action 在前否则 Q 值全是错的。ReplayBuffer 存的是「所有智能体」的联合转移不是单个智能体的这一点是新手最容易搞混的地方。2.3 目标网络和软更新别小看这个 0.01MADDPG 沿用了 DDPG 的目标网络机制。每个 Actor 和 Critic 都有一份 online 网络和一份 target 网络。target 网络不参与梯度更新而是用软更新慢慢跟随# 软更新tau 通常取 0.01 for target_param, param in zip(target_net.parameters(), online_net.parameters()): target_param.data.copy_(tau * param.data (1.0 - tau) * target_param.data)tau这个参数看着不起眼但它决定了 target 网络跟随的速度。取 0.01 意味着每次只吸收 1% 的新参数目标值变化平缓训练稳定。如果你把它调到 0.1target 网络跟得太快Q 值目标抖动大容易发散调到 0.001学习信号传得太慢收敛要等很久。我一般先用 0.01 跑通再根据曲线微调。这个参数在源码注释里通常会有说明但很多人跑不通就是因为随手改了这个值。3. 把源码跑起来环境搭建与最小训练循环3.1 依赖安装与目录结构确认拿到压缩包解压后先别急着python main.py。第一步是确认依赖。MADDPG 的常见实现依赖torch、numpy、gym如果环境用的是 MultiAgent Particle Env还需要multiagent-particle-envs。我一般会先建一个干净的虚拟环境# 创建并激活虚拟环境 python -m venv maddpg_env source maddpg_env/bin/activate # Windows 用 maddpg_env\Scripts\activate # 安装核心依赖torch 按自己 CUDA 版本去官网选对应命令 pip install torch numpy gym pip install githttps://github.com/openai/multiagent-particle-envs.git装完之后pip list确认一下版本。这里有个血泪经验gym在 0.26 之后 API 改动很大env.step()返回值从 4 个变成 5 个很多老源码会直接报too many values to unpack。如果你拿到的源码是按老版本写的最省事的做法是pip install gym0.21.0别硬去改源码适配新 API毕业设计时间耗不起。3.2 环境初始化与智能体数量配置以经典的simple_tag场景为例这是一个追逃博弈若干个 predator 追一个 prey。环境创建和智能体初始化的代码通常长这样import gym import multiagent from maddpg import MADDPG # 创建环境simple_tag 是追逃对抗场景 env gym.make(simple_tag-v1) env.seed(42) # 获取环境基本信息 obs_dims [env.observation_space[i].shape[0] for i in range(env.n)] act_dims [env.action_space[i].shape[0] for i in range(env.n)] n_agents env.n # 初始化 MADDPG传入智能体数量和各自的观测/动作维度 maddpg MADDPG(n_agents, obs_dims, act_dims)env.n是智能体总数simple_tag里通常是 4 个3 个 predator 1 个 prey。obs_dims和act_dims是列表每个元素对应一个智能体的维度。注意不同智能体的观测维度可能不一样比如 prey 能看到所有 predatorpredator 只能看到彼此和 prey 的相对位置所以这里必须用列表而不是单个整数。如果你的源码里写死了维度换场景就会崩。3.3 训练主循环每一步该记录什么训练循环是整套代码的心脏。一个可复现的最小循环如下max_episodes 3000 max_steps 25 for episode in range(max_episodes): obs env.reset() episode_reward [0.0] * n_agents for step in range(max_steps): # 每个智能体根据自己的局部观测选动作加探索噪声 actions maddpg.select_actions(obs, noise0.1) # 环境推进一步拿到联合转移 next_obs, rewards, dones, infos env.step(actions) # 存入回放缓冲区注意存的是所有智能体的联合数据 maddpg.store_transition(obs, actions, rewards, next_obs, dones) # 每步都做一次更新也可以攒够 batch 再更新 maddpg.update() obs next_obs for i in range(n_agents): episode_reward[i] rewards[i] # 每 100 轮打印一次平均回报观察收敛趋势 if episode % 100 0: print(fEpisode {episode}, reward: {episode_reward})noise0.1是动作探索噪声的标准差训练初期可以大一点0.2~0.3鼓励探索后期调小0.05让策略稳定。max_steps25是每个 episode 的最大步数simple_tag默认就是这个值。maddpg.update()里会从 buffer 采样一个 batch计算 Critic loss 和 Actor loss反向传播。如果你发现训练几百轮 reward 完全不动先检查store_transition存进去的next_obs是不是真的下一步观测很多人在这里把obs和next_obs写反了导致 Critic 学的是错误的目标值。4. 参数调优与训练不收敛的排查手册4.1 学习率、batch size、buffer 容量的联动关系MADDPG 对超参比单智能体 DDPG 更敏感因为多个网络同时在更新。我一般用这套起点参数推荐值作用与调整方向Actor 学习率1e-4太大策略震荡太小收敛慢Critic 学习率1e-3通常比 Actor 大一个量级batch size1024太小梯度噪声大太大显存吃紧buffer 容量1e6太小样本重复太大早期样本过时gamma0.95博弈场景步数短不用 0.99tau0.01软更新系数别乱动Critic 学习率比 Actor 大是常见做法因为 Critic 要先把价值估计准Actor 才有靠谱的梯度方向。gamma0.95而不是 0.99是因为simple_tag每个 episode 只有 25 步折扣因子太大反而让远期回报权重过高不利于短期博弈策略的学习。4.2 用 TensorBoard 看三条曲线判断训练状态光看 reward 数字不够我习惯把三个量打到 TensorBoard每个智能体的 episode reward、Critic loss、Actor loss。判断标准很直接Critic loss 缓慢下降并趋于平稳说明价值估计在收敛。Actor loss 通常不大幅下降甚至可能上升这是正常的因为策略梯度目标是最大化 Q 值不是最小化 loss。如果 Critic loss 爆炸式增长到 1e6 以上基本是学习率太大或者 target 更新出了问题。from torch.utils.tensorboard import SummaryWriter writer SummaryWriter(runs/maddpg_simple_tag) # 在 update 返回 loss 后记录 writer.add_scalar(critic_loss, critic_loss, episode) writer.add_scalar(actor_loss, actor_loss, episode) writer.add_scalar(reward_agent0, episode_reward[0], episode)如果 Critic loss 一直不降先把 Critic 学习率砍到 1e-4 试试再检查 reward 的尺度。simple_tag里 predator 撞到 prey 有正向奖励撞到队友有负向奖励reward 范围大概在 [-10, 10]不需要额外归一化。但如果你换到自定义环境reward 动辄几百就得先做 scaling否则 Q 值目标太大网络学不动。4.3 避坑MADDPG 训练中最容易翻车的五个点现象一reward 从第一轮就一直是 0完全不动。原因动作没加噪声或者噪声加在了错误的地方。MADDPG 是确定性策略不加探索噪声的话所有智能体从始至终做同样的动作buffer 里全是重复样本。 解决确认select_actions里对每个动作加了高斯噪声且噪声只在训练时加测试时关掉。现象二训练到一半 reward 突然崩掉再也回不来。原因Critic 过估计导致策略跑偏或者 target 网络更新频率异常。常见于tau被误设成 1.0等于没有 target 网络。 解决检查tau是否在 0.001~0.01 之间并确认 target 网络参数是用copy_软更新而不是直接赋值。现象三显存爆了batch size 明明不大。原因Critic 输入拼接了所有智能体的 obs 和 action维度是sum(obs_dims) sum(act_dims)智能体数量一多全连接层参数量平方级增长。 解决减小隐藏层宽度比如从 256 降到 128或者用梯度累积模拟大 batch。现象四换了自定义环境后维度对不上报 shape mismatch。原因obs_dims和act_dims是按环境硬编码的新环境的观测结构不同。 解决在环境初始化后动态读取env.observation_space[i].shape[0]不要写死数字。现象五测试时表现远差于训练时。原因测试时忘了关噪声或者 Actor 网络没切到 eval 模式BatchNorm/Dropout 行为不一致。 解决测试前调actor.eval()并把噪声标准差设为 0。5. 从能跑到能写进论文实验设计与结果呈现技巧5.1 设计一组有说服力的对比实验毕业设计的实验章节不能只有一条 reward 曲线。我建议至少做三组对比MADDPG vs 独立 DDPG每个智能体各训各的、MADDPG vs 随机策略、MADDPG 在不同噪声下的表现。每组跑 3~5 个随机种子画均值加方差阴影。随机种子要固定env.seed()和torch.manual_seed()都要设否则结果不可复现答辩时被问到会很被动。import torch import numpy as np import random def set_seed(seed): torch.manual_seed(seed) np.random.seed(seed) random.seed(seed) env.seed(seed) if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed)5.2 用胜率而不是 reward 讲故事博弈对抗场景里reward 曲线有时候不够直观。simple_tag里你可以统计 predator 成功碰到 prey 的 episode 比例也就是胜率。胜率从 10% 涨到 70%比 reward 从 -50 涨到 -10 更有说服力。实现上就是在 episode 结束时判断infos里有没有捕获标志累加计数。这个指标在论文里画成柱状图比折线图更抓眼球。5.3 一个我踩过的坑别在最后一周才跑完整实验MADDPG 在simple_tag上跑 3000 episode用一块普通显卡大概要几个小时。如果你要跑 5 个种子 × 3 组对比就是十几个小时。我当年就是拖到最后一周才开始跑结果发现有个种子的曲线异常想重跑已经来不及了。后来我的习惯是代码一跑通立刻用 500 episode 的小规模实验验证流程确认没问题再挂全量。另外checkpoint 一定要每个几百轮存一次万一训练崩了还能从中间恢复不用从头再来。希望这些能帮到你少走点我当年走过的弯路。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑