ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

MADDPG多智能体强化学习实战:从DDPG到博弈对抗的Python实现与调参指南

MADDPG多智能体强化学习实战:从DDPG到博弈对抗的Python实现与调参指南 简介MADDPG多智能体深度确定性策略梯度博弈对抗算法的Python源码及实验成果包面向人工智能、机器学习方向的高校学生、科研人员及强化学习入门开发者。资源内置ma-gym多智能体环境库覆盖combat战斗、predator_prey追捕等经典博弈与协作场景可直接用于训练演示、算法对比也可作为课程设计、毕业设计的基础框架。压缩包共91个文件核心为76个Python源码涵盖MADDPG.py、DDPG.py、network.py、buffer.py等主程序及经验回放、网络结构模块另含10个gif训练动图、1个ipynb交互式演示、1个md说明文档与配置信息整体仅3.26MB。目前已有92人浏览学习。从算法模型、训练逻辑到环境配置链路完整训练过程可视化动图直观呈现收敛效果便于理解MADDPG在多智能体博弈中的工作机制适合调参实验、科研探索与项目初期演示参考。1. 把MADDPG从论文变成可跑的代码这份资源到底给了什么如果你正打算做多智能体博弈对抗相关的研究或课设大概率听过 MADDPG 这个名字。它是 OpenAI 提出的多智能体强化学习基线算法专门解决传统 DDPG 在对抗博弈里环境非平稳、智能体互相干扰导致收敛困难的问题。这份名为「Python 实现的 MADDPG 多智能体博弈对抗算法源码及实验结果.zip」的资源就是把论文里的伪代码落成了可以实际训练、测试的 Python 工程。解压之后你会发现它不只是孤零零一个算法文件而是带了一整套配套环境库 ma-gym里面包含了 predator_prey、combat、switch、pong_duel 等多个博弈场景还有训练主程序、DDPG 单智能体基线、经验回放 buffer、网络定义、测试脚本和运行日志。适合刚接触多智能体强化学习的学生用来对标 DDPG 理解 MADDPG 的改进点也适合需要快速出实验结果的从业者直接改改参数跑自己的场景。接下来我会按“源码结构 → 运行方法 → 结果解读 → 避坑 → 迁移扩展”的路径把这个资源的成色和坑位一次性给你交代清楚。2. 拆解源码结构MADDPG核心组件与环境配套2.1 目录与文件角色从zip解压后先看清这张地图拿到压缩包后先别急着双击运行花几分钟看清楚目录结构比什么都重要。这个包的根目录下同时存在两个层次的代码一层是 MADDPG 算法本身的实现另一层是 ma-gym 环境库源码里也带了 ma-gym-master.zip 和已经解压好的 ma_gym 目录。核心算法文件直接放在根目录下文件名角色说明MADDPG.py多智能体强化学习主算法包含 agent 的创建、训练循环、目标网络更新DDPG.py单智能体 DDPG 算法用于对照实验也是 MADDPG 的基座network.py定义 Actor 和 Critic 神经网络结构包括 MLP、RNN 等可选层buffer.py经验回放缓冲区存储并采样 (状态、动作、奖励、下一状态) 四元组main.py训练入口负责加载环境、初始化算法、执行多轮 episodetest.py 与 test_env.py测试脚本验证训练出的模型与环境本身是否正常rl_utils.py软更新soft update、噪声生成等辅助函数ceshi.py个人调试脚本用于快速跑通流程ma_gym 环境库的目录层级是重头戏ma_gym/envs/下包含了 lumberjacks伐木工多人收集、combat团队对战、predator_prey捕食者-猎物最经典的对抗博弈、switch开关切换、checkers跳棋、traffic_junction交通路口、pong_duel乒乓球对抗。每个环境目录内是__init__.py加上环境实现文件顶层还有wrappers/观测与环境预处理和monitor.py策略可视化记录。这份资源相当于把“算法 环境 工具链”整合在了一个压缩包里少了你自己去 GitHub 凑齐依赖的麻烦。2.2 MADDPG算法核心DDPG基座、Buffer与network.py的搭建逻辑MADDPG 的全称是 Multi-Agent Deep Deterministic Policy Gradient思路是“中心化训练去中心化执行”。每个智能体有自己的 Actor 网络只基于自身观测输出确定性动作但训练时 Critic 网络可以拿到所有智能体的状态和动作从而评估当前策略在全局环境下的 Q 值。这样做的好处是训练阶段解决了环境非平稳问题——因为 Critic 看到了全局不会因为别的智能体策略变化而产生错误的梯度信号。在代码里DDPG.py 实现了最基本的那一套Actor 基于状态输出动作Critic 将状态和动作拼接后输出 Q 值经验回放 buffer 采样小批量更新再用tau参数做软更新把目标网络参数一点点贴合在线网络。MADDPG.py 则在这个基础上做了三重修改第一为每个智能体单独维护一组 Actor-Critic第二Critic 的输入改为全局拼接后的状态和所有智能体的动作第三奖励设计允许每个智能体有自己的 reward 函数不要求完全一致。network.py里定义网络结构时我建议你重点看两个地方一是build_mlp函数它决定了每个智能体的隐藏层层数和神经元数量默认配置对简单博弈够用但遇到高维观测时需要加深二是是否启用了 RNN 层如果环境部分可观测比如 switch 场景里智能体看不到全局开关状态就要靠循环网络记忆历史观测。buffer.py的实现相对标准但它记录数据时用了next_obs_all这种全局下一观测字段这是 MADDPG 的 Critic 更新需要的不能把它和单智能体 buffer 混用。2.3 ma-gym环境库六个场景提供了博弈对抗的测试场ma-gym 环境库是这个资源里容易被低估的一部分。很多人下载焦点全在算法实际上没有适合多智能体博弈的环境算法跑起来就没有对比意义。以predator_prey为例环境里定义了一个二维栅格世界猎物与捕食者同场运动捕食者每个时间步决定上下左右移动或静止猎物同样有自己的策略默认是随机逃逸也可以换成交互式智能体。这个场景直接对应博弈对抗里的“合作围捕”与“目标逃避”是验证 MADDPG 收敛能力的标准试金石。combat环境则更偏团队对抗两队智能体在栅格地图上互相攻击初始位置、攻击范围、血量衰减都写死在 env 文件里。traffic_junction是交通路口的车辆协同考验多智能体在共享空间下的避碰策略。这些环境都遵循 gym 的接口规范你可以直接用env.reset()、env.step(actions)来驱动也支持渲染成 gif源码里 static gif 目录和 scripts/record_environment.py 就是干这个的。环境层面还挂了wrappers用来改写观测空间、增加时间限制、标准化奖励等这些包装器是训练多智能体时最容易出 bug 的地方后面避坑章细说。3. 动手运行从环境配置到第一个训练结果3.1 环境准备Python版本、依赖安装和pyvenv.cfg的提示我在复现这个资源时用的是 Python 3.8 和 3.9 两个版本都能顺利跑通。注意压缩包里有一个pyvenv.cfg文件这是虚拟环境配置文件说明原开发者在 venv 里装过依赖如果你直接用系统 Python请先确保安装了必要的库。常见依赖是 numpy、torch、gym 和 matplotlib其中 gym 的版本需要与 ma-gym 的接口匹配老代码通常兼容 gym 0.26 以下版本新版本 gym 改了 API 容易报 Warning但不影响本次训练核心。我一般会先新建一个干净的虚拟环境避免和项目里的.cfg打架python -m venv maddpg_env source maddpg_env/bin/activate # Windows 下执行 maddpg_env\Scripts\activate pip install numpy torch gym matplotlib然后进入解压后的根目录把 ma-gym 库安装到环境里。常见做法是对ma-gym-master目录执行可编辑安装pip install -e ./ma-gym-master这里的-e是 editable 模式之后你在 ma_gym 里改环境代码不需要重新安装就能生效。装完之后在 Python 里执行import ma_gym能成功导入就说明环境库已经挂上了。千万别跳过这一步直接运行main.py大概率会提示找不到ma_gym.envs模块。3.2 快速启动用main.py跑起MADDPG训练环境配好之后我建议先用默认参数跑一个最小 demo确认整个链路是通的。源码里的main.py已经封装好了主要入口常见用法是直接指定环境名和训练轮数python main.py --env predator_prey --episodes 5000如果你的 main.py 没有实现命令行解析也可以直接改文件末尾的__main__区块把环境名和总回合数硬编码进去然后python main.py。跑起来后你会看到类似这样的输出Episode: 100, Total reward: -85.4 Episode: 200, Total reward: -62.1 Episode: 300, Total reward: -48.9 ... Episode: 5000, Total reward: 126.3reward 从负值慢慢转正说明智能体正在从“乱撞”变成“有策略地围捕”。在这个过程里MADDPG.py的train函数会依次做这些事重置环境、循环执行act选出动作、调用env.step得到奖励和下一状态、把数据塞进 buffer、每积累一定步数后采样一个小批量更新每个智能体的网络。你要观察的核心指标就是每个 episode 的总奖励以及结束步数越短说明越快完成任务。启动训练前有一步容易被忽略检查test_env.py。如果新版 gym 的 Space 接口有变化这个测试脚本可能会报维度不对。我每次拿到新环境都会先跑一遍python test_env.py确认env.observation_space和env.action_space能够被正确读取再进训练环节能省掉很多排错时间。3.3 修改网络与超参数让训练更稳的常用调参清单如果你希望在这份源码基础上调出自己的结果重点参数基本都在MADDPG.py的初始化函数和main.py顶部常量里。我整理了最值得动的几个量以及它们在代码中的影响参数常见取值范围影响学习率1e-4 到 1e-2太高会导致 Q 值爆炸太低收敛极慢批大小 batch_size256 到 1024越大越稳定但显存占用高经验池容量 buffer_capacity1e5 到 1e6过小会让旧经验反复干扰训练折扣因子 gamma0.9 到 0.99越大越看重远期收益软更新系数 tau0.001 到 0.01越小目标网络更新越慢越稳定探索噪声 sigma0.1 到 0.3初始探索强度后期应下降以predator_prey为例如果你想追求稳定收敛而不是快速出图我会建议把batch_size调到 512tau设为 0.005训练周期至少 20000 个 episode。很多博客用 5000 episode 给出漂亮曲线但那通常是把环境尺寸调小了或者人为降低了猎物逃跑速度。如果你发现 reward 一直不涨先检查 noise 是不是太大导致策略被噪声淹没再检查 Critic 输入拼接时是否把动作维度搞错了。network.py中隐藏层默认是[128, 128]两层全连接这在简单栅格场景里够用。如果换成traffic_junction这种需要更多上下文的环境我一般会改成[256, 256]同时把recurrentTrue打开让每个智能体用自己的历史观测来推算其他智能体的位置。别小看这个开关它直接影响 MADDPG 在部分可观测环境下的表现。4. 实验结果怎么看收敛曲线与对抗行为分析4.1 训练日志与reward曲线先判断收敛还是发散训练完成之后你需要面对的第一个问题是“这结果到底算好还是算坏”资源里没有附带现成的训练曲线图但源码里的main.py通常会把每个 episode 的累计奖励打印或保存下来。我会把这些奖励值导出到 CSV再用 matplotlib 画成平滑曲线。如果曲线整体趋势向上而且后段波动幅度收窄就说明 MADDPG 学到了稳定的策略如果曲线一直横向抖动没有任何上升迹象那大概率是超参数没配对或者环境奖励太稀疏。判断收敛不能只看最后阶段的绝对值还要看训练过程中是否出现“突然掉坑”。比如训练了两千个 episode 之后 reward 突然从 50 跌到 -100然后再也爬不起来这种情况常见于经验回放池里混入了太多早期“垃圾经验”或者在更新时把 Actor 的探索噪声一步调得过低。我处理这类问题的方法是降低学习率或者让噪声按sigma max(0.1 * (1 - t / total_time), 0.01)线性衰减而不是立刻归零。还有一种隐蔽的假收敛reward 曲线很好看但跑test.py时智能体在随机初始化状态下表现极差。这说明训练时智能体只是记住了固定开局下的最优路径没有真正学会泛化博弈策略。要验证的话我会在测试阶段把环境初始位置设为随机比如修改predator_prey里的reset()函数让猎物初始位置在整张地图随机采样再看模型是否依然有效。4.2 不同场景下的博弈行为从predator_prey到combat这个资源最有价值的地方在于它把 MADDPG 绑定了多个博弈对抗场景你可以直接观察同一套算法在不同奖励结构下的行为差异。以predator_prey为例训练好的捕食者策略通常是“分头包抄”一个捕食者从左侧逼近另一个从右侧绕后而不是所有捕食者都往猎物当前位置冲。这是因为 Critic 在训练时学到了如果多个捕食者挤在同一格附近会重复浪费步数而协作围捕能更快抓住猎物。combat场景则展现了另一种模式团队内的智能体会根据自身血量自动调整攻击倾向血量低的会更倾向于后撤到安全区血量高的则主动追击。这种行为不是人为设定的完全是奖励函数中个体奖励和团队奖励加权后Critic 通过梯度信号引导出来的。我在实际跑的时候会把combat的团队奖励系数从 0.5 调到 1.0观察智能体是否变得更加“牺牲自我”——这正是多智能体博弈里最值得调的一个旋钮。switch场景是这几个环境里最考验可观测性的一个。它要求智能体去拨动某个开关但单个智能体看不到开关当前是开还是关。如果不打开network.py的 RNN 开关MADDPG 在这种环境下会表现得很差因为它的 Critic 虽然能看到全局但 Actor 输入只有局部观测所以必须记住历史信息才能推理出开关状态变化。用这份资源做实验你可以同时对比“有 RNN”和“无 RNN”两种情况把这个差异写进课设报告里会比单纯贴代码显得深入很多。5. 多智能体强化学习的避坑指南常见问题与排查5.1 坑1训练不收敛reward始终在负数附近震荡现象跑了三五千个 episode累计奖励一直在 -100 到 -50 之间横跳没有任何上升趋势。原因最常见的是学习率过大导致 Actor 更新过猛策略在每次更新后剧烈变化其次是经验池太小旧经验被频繁覆盖导致 Critic 反反复复忘掉之前学的东西。解决先把 Critic 和 Actor 的学习率都降到 1e-4然后检查buffer.py的容量设置确保至少能存下 10 万个时间步的数据。我还会把batch_size提高到 512并且让每个 episode 结束后强制更新几次而不是攒很多步才更新一次。5.2 坑2运行报错ModuleNotFoundError: ma_gym.envs或No module named ma_gym现象输入python main.py后直接退出提示找不到 ma_gym 模块或某个具体环境名。原因没有把 ma-gym 安装到当前 Python 环境或者安装时用了错误的目录。压缩包里既有ma-gym-master文件夹也有一个ma-gym-master.zip有些朋友只解压了算法部分忘了解压环境库。解决先确认ma_gym目录存在于你当前运行的目录下然后执行pip install -e ./ma-gym-master。如果还报错检查环境名是否写错比如predator_prey在ma_gym/envs下真实存在而combat对应的目录是combat不要带_env后缀。5.3 坑3GPU 显存溢出或 CPU 训练慢到怀疑人生现象TORCH 报 CUDA out of memory或者 CPU 模式下一个 episode 要好几秒5000 个 episode 遥遥无期。原因MADDPG 是多智能体算法每个智能体都有自己的 Actor 和两个 Critic在线与目标如果同时开 6 个智能体模型数量翻倍显存压力比单智能体大很多。解决优先减小batch_size比如从 1024 降到 256其次把隐藏层从[256, 256]收缩到[128, 128]。如果没有 GPU就老老实实把环境尺寸调小比如把predator_prey的 grid size 从 10x10 改成 7x7这会直接降低观测维度与动作组合空间训练速度能快好几倍。5.4 坑4测试时表现远不如训练仿佛换了个模型现象训练代码里打印的 reward 已经很高但用test.py或渲染成 gif 后智能体表现得像没学过一样。原因测试时没有关掉探索噪声导致确定性策略被噪声污染或者测试环境重置时随机种子不同而模型只在训练时那几种开局下有效。解决在测试模式下把动作选择改成policy self.actor(obs)直接取输出不要加任何噪声。同时固定测试环境的随机种子比如在test_env.py开头调用env.seed(42)。还有一个常见做法是把测试智能体的初始位置固定几组分别验证鲁棒性。5.5 坑5结果无法复现两次训练曲线完全不同现象完全相同的代码和超参数两次训练得到的 reward 曲线差异很大甚至趋势都不同。原因没有设置全局随机种子。PyTorch、NumPy、Python 自带的 random 模块各有一套随机数生成器只要有一个没固定训练结果就不可复现。解决在main.py最开头加这么几行import random import numpy as np import torch random.seed(42) np.random.seed(42) torch.manual_seed(42) if torch.cuda.is_available(): torch.cuda.manual_seed_all(42)需要注意即使设置了这些种子某些环境在gym.make时还会引入自己的随机源最好也在env.seed(42)上加一道保险。以后每次跑新实验我都强烈建议把随机种子、参数配置、代码版本一起记进实验表格不然三个实验贴在一起根本说不清差异是来自算法还是来自随机性。6. 进阶把MADDPG迁移到自己定义的博弈对抗场景如果只是跑通现有的 predator_prey那这份资源的价值还没完全榨干。真正值得做的是把自己任务抽象成多智能体博弈环境然后复用这套 MADDPG 代码训练。我会在ma_gym/envs/下新建一个目录比如my_soccer里面放一个my_soccer.py类继承gym.Env。核心是实现四个方法reset()返回初始观测step(actions)接收所有智能体的动作并返回全局奖励render()用来可视化close()清理资源。环境写好之后关键是把观测空间设计成 numpy 数组形状为(num_agents, feature_dim)。MADDPG.py 里读取观测的代码通常是这样obs env.reset() obs_all np.vstack(obs) # 所有智能体的观测拼接如果你的智能体观测维度不同比如一个智能体有雷达数据另一个只有位置信息直接拼接会出问题。常见做法是统一用多层感知机把每个智能体的观测映射到相同的特征维度然后再拼接。你可以复用network.py里的build_mlp函数为不同智能体分别建立输入编码器这是对源码最常用的扩展方向。训练自己的环境时还有一个值得实验的技巧给每个智能体设置差异化奖励。比如在对抗博弈里攻击方奖励设计为“对敌方造成伤害 0.5自己存活 0.1”防守方奖励设计成“拦截攻击 1.0失血 -0.3”。MADDPG 允许每个 agent 的reward函数独立这种差异化奖励会让对抗行为更鲜明。我在迁移场景时通常会先用单智能体 DDPG.py 跑一遍简单版本确认环境步进和奖励逻辑没 bug再切到 MADDPG.py 上多智能体训练。这样一旦训练失败你能清楚地知道问题是出在环境还是出在多智能体协调上。测试迁移效果时我会先把render()打开人工看一眼动作是否符合直觉再用record_environment.py录制一段运行过程。从那以后我每次迁移新场景都强制走一遍“环境自测、单智能体试跑、多智能体调参、可视化复盘”这四个步骤这套流程帮我避开了至少五次“看似在训练、实则环境在报错”的翻车。希望这个思路也能帮到你少走弯路。本文还有配套的精品资源点击获取
返回列表