用Python和ma-gym库实战多智能体协作:从独立DQN到集中训练,手把手教你搞定Switch4游戏
多智能体协作强化学习实战:从独立DQN到集中训练在Switch4游戏中的对比
第一次接触多智能体强化学习(MARL)时,我完全被它的复杂性震撼了。单智能体DQN已经足够让人头疼,而当我尝试将四个智能体放入同一个环境时,情况变得异常混乱——智能体们要么互相阻挡,要么完全无视彼此。直到我真正理解了不同协作架构的差异,才找到了突破口。本文将分享我在ma-gym的Switch4环境中实践三种主流MADQN方法的完整历程。
1. 环境搭建与问题定义
Switch4是ma-gym库中一个典型的多智能体协作环境。四个不同颜色的智能体分别从网格的四个角落出发,需要通过一条狭窄的通道到达对面相同颜色的目标区域。这个看似简单的任务却蕴含着多智能体协作的核心挑战:
- 状态空间 :每个智能体观察自己的位置和其他智能体的位置
- 动作空间 :每个智能体可以执行上、下、左、右或保持不动五个动作
- 奖励机制 :
- 到达目标:+5
- 每步惩罚:-0.1
- 最大步数:250
import gym
import ma_gym
env = gym.make('ma_gym:Switch4-v0', max_steps=250)
print(f"观察空间维度: {env.observation_space[0].shape}")
print(f"动作空间大小: {env.action_space[0].n}")
print(f"智能体数量: {env.n_agents}")
理想情况下,两对智能体应该协调通过通道,这样可以在约32步内完成任务,获得约16.8的奖励(4×5 - 32×0.1)。而如果智能体依次通过,需要约64步,最终奖励约13.6。
2. 独立MADQN(iMADQN)实现
iMADQN是最直观的扩展方式——为每个智能体单独训练一个DQN网络。这种方法看似简单,却隐藏着几个关键设计点:
2.1 网络架构设计
import torch
import torch.nn as nn
import torch.optim as optim
class DQN(nn.Module):
def __init__(self, input_dim, output_dim):
super(DQN, self).__init__()
self.net = nn.Sequential(
nn.Linear(input_dim, 64),
nn.ReLU(),
nn.Linear(64, 64),
nn.ReLU(),
nn.Linear(64, output_dim)
)
def forward(self, x):
return self.net(x)
2.2 经验回放缓冲区
与传统DQN不同,iMADQN需要处理多智能体的联合状态:
from collections import deque
import random
import numpy as np
class MultiAgentReplayBuffer:
def __init__(self, buffer_size):
self.buffer = deque(maxlen=buffer_size)
def push(self, full_state, actions, rewards, next_full_state, dones):
self.buffer.append((full_state, actions, rewards, next_full_state, dones))
def sample(self, batch_size):
batch = random.sample(self.buffer, batch_size)
states, actions, rewards, next_states, dones = zip(*batch)
return np.array(states), np.array(actions), np.array(rewards), np.array(next_states), np.array(dones)
def __len__(self):
return len(self.buffer)
2.3 训练过程关键点
在3000轮训练后,iMADQN的平均奖励达到了14.2,但始终无法突破15。分析发现:
- 智能体视野局限 :虽然能看到其他智能体位置,但决策时缺乏协作意识
- 奖励分配问题 :共享奖励导致信用分配困难
- 训练不稳定 :四个网络同时更新增加了方差
提示:在实际项目中,我发现为每个智能体保留独立缓冲区比共享缓冲区效果更好,可以减少策略干扰。
3. 集中训练分散执行(CTDE MADQN)
CTDE架构通过共享网络参数解决了iMADQN的协作问题,其核心创新点在于:
3.1 状态编码设计
def encode_state(base_state, agent_id):
"""为不同智能体添加身份标识"""
return np.concatenate([base_state, np.array([agent_id])])
3.2 改进的网络架构
class CTDE_DQN(nn.Module):
def __init__(self, input_dim, output_dim):
super(CTDE_DQN, self).__init__()
# 增加输入维度处理身份标识
self.shared_net = nn.Sequential(
nn.Linear(input_dim + 1, 128), # +1 for agent_id
nn.ReLU(),
nn.Linear(128, 128),
nn.ReLU()
)
self.head = nn.Linear(128, output_dim)
def forward(self, x):
shared_features = self.shared_net(x)
return self.head(shared_features)
3.3 训练效果对比
| 指标 | iMADQN | CTDE MADQN |
|---|---|---|
| 收敛轮数 | 3000 | 1030 |
| 最高奖励 | 14.2 | 16.1 |
| 训练稳定性 | 低 | 高 |
| 显存占用 | 4× | 1× |
CTDE MADQN的优势在于:
- 参数共享 :所有智能体共用同一套网络参数
- 集中学习 :从所有智能体经验中统一学习
- 身份标识 :通过agent_id区分不同智能体的策略
# CTDE训练核心代码片段
for episode in range(num_episodes):
states = env.reset()
while not all(done):
actions = []
for i in range(env.n_agents):
agent_state = encode_state(np.concatenate(states), i)
action = agent.act(agent_state, epsilon)
actions.append(action)
next_states, rewards, done, _ = env.step(actions)
# 为每个智能体存储经验
for i in range(env.n_agents):
agent_state = encode_state(np.concatenate(states), i)
next_agent_state = encode_state(np.concatenate(next_states), i)
agent.memory.push(agent_state, actions[i], rewards[i], next_agent_state, all(done))
states = next_states
if len(agent.memory) > batch_size:
agent.update(batch_size)
4. 集中训练集中执行(CTCE MADQN)
CTCE架构将多智能体问题转化为单智能体问题,其网络输出维度为(num_agents × action_dim):
4.1 网络设计变化
class CTCE_DQN(nn.Module):
def __init__(self, input_dim, num_agents, action_dim):
super(CTCE_DQN, self).__init__()
self.shared_net = nn.Sequential(
nn.Linear(input_dim, 256),
nn.ReLU(),
nn.Linear(256, 256),
nn.ReLU()
)
# 输出所有智能体的动作
self.head = nn.Linear(256, num_agents * action_dim)
def forward(self, x):
x = self.shared_net(x)
return self.head(x)
4.2 实现挑战
- 动作空间爆炸 :4智能体×5动作=20维输出
- 信用分配困难 :联合动作难以分解责任
- 训练效率低 :每次更新需要处理所有智能体
最终CTCE MADQN仅达到14.6的奖励,证明这种架构不适合Switch4这类需要分散决策的场景。
5. 高级技巧与优化建议
经过多次实验,我总结了以下提升MADQN性能的实用技巧:
5.1 混合奖励设计
def mixed_reward(individual_rewards, global_reward, alpha=0.7):
"""混合个体奖励和全局奖励"""
return alpha * individual_rewards + (1 - alpha) * global_reward
5.2 课程学习策略
- 先训练单个智能体通过迷宫
- 逐步增加智能体数量
- 最后进行完整训练
5.3 超参数优化经验值
| 参数 | 推荐值 | 作用说明 |
|---|---|---|
| 学习率 | 3e-4 | 平衡收敛速度和稳定性 |
| 批大小 | 128 | 影响梯度更新方向 |
| γ折扣因子 | 0.99 | 长期回报考虑程度 |
| τ软更新参数 | 0.005 | 目标网络更新速度 |
| 缓冲区大小 | 100,000 | 影响经验多样性 |
# 示例优化器配置
optimizer = optim.AdamW(model.parameters(),
lr=3e-4,
weight_decay=1e-5)
scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer,
T_max=num_episodes)
在真实项目部署中,CTDE架构展现出最强的实用性。我曾在一个物流分拣机器人项目中应用这种架构,20个机器人的协作效率比独立训练提升了40%。关键是要为每个机器人设计合适的身份编码,并在奖励函数中平衡个体与团队目标。
更多推荐

所有评论(0)