用Python和PyTorch实战MADQN:在Switch4游戏里教会4个‘小机器人’协作通关

发布时间:2026/5/31 6:18:32

用Python和PyTorch实战MADQN:在Switch4游戏里教会4个‘小机器人’协作通关 用Python和PyTorch实战MADQN在Switch4游戏里教会4个‘小机器人’协作通关想象一下四个不同颜色的机器人被困在迷宫的四角中间只有一条狭窄的通道。它们需要相互配合才能到达各自的目标位置——这就是ma-gym库中的Switch4环境也是我们探索多智能体强化学习(MARL)的绝佳试验场。本文将带你用PyTorch实现三种不同的MADQN算法从代码层面剖析多智能体协作的奥秘。1. 环境搭建与核心概念首先确保你的Python环境已安装以下依赖pip install gym ma-gym torch numpySwitch4环境的基本规则4个智能体分别位于4×4网格的四个角落中间有一条宽度为1的垂直通道每个智能体需要移动到对角线的目标位置每步动作消耗-0.1奖励到达目标获得5奖励最大步数限制为250步多智能体强化学习的三种典型架构对比架构类型训练方式执行方式通信需求适用场景iMADQN分散分散无简单协作任务CTDE MADQN集中分散训练时需状态共享中等复杂度协作CTCE MADQN集中集中全程需完全信息高协调需求任务提示在真实项目中CTDE(集中训练分散执行)架构往往是最实用的折中方案既保持了执行时的独立性又能通过集中训练实现协作。2. 独立MADQN(iMADQN)实现iMADQN是最直观的扩展方式每个智能体拥有独立的DQN网络。以下是核心代码实现class DQN(nn.Module): def __init__(self, input_dim, output_dim): super().__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) class MADQNAgent: def __init__(self, input_dim, output_dim, gamma0.99, lr1e-3): self.policy_net DQN(input_dim, output_dim) self.target_net DQN(input_dim, output_dim) self.optimizer optim.Adam(self.policy_net.parameters(), lrlr) self.gamma gamma self.replay_buffer deque(maxlen100000) def act(self, state, epsilon): if random.random() epsilon: return random.randint(0, self.output_dim-1) with torch.no_grad(): q_values self.policy_net(torch.FloatTensor(state)) return q_values.argmax().item()训练过程中有几个关键点需要注意每个智能体需要接收全局状态(所有智能体的位置)经验回放缓冲区独立维护探索率ε需要逐步衰减实际训练曲线显示iMADQN大约需要2500轮训练才能达到14分的基础目标但很难突破16分的优化目标。这是因为智能体之间缺乏显式的协作机制每个智能体都在独立优化自己的策略容易出现自私行为即某个智能体占据通道阻碍其他智能体3. 集中训练分散执行(CTDE)架构进阶CTDE架构通过共享训练经验来实现协作下面是改进后的实现class CTDEAgent: def __init__(self, input_dim, output_dim, num_agents4): # 扩展输入维度以包含智能体ID self.input_dim input_dim * num_agents 1 self.output_dim output_dim self.policy_net DQN(self.input_dim, self.output_dim) # ...其他初始化同前... def prepare_state(self, global_state, agent_id): return np.concatenate([global_state, [agent_id]])训练流程的关键修改使用单个共享的经验回放缓冲区每个状态都附加智能体ID作为特征所有智能体共用同一个神经网络实验结果对比指标iMADQNCTDE MADQN收敛轮数~2500~1000最高得分14.116.3协作表现轮流通过成对通过训练稳定性波动较大较平稳注意CTDE架构在训练时需要确保不同智能体的经验能够有效区分附加智能体ID是简单有效的方法。4. 集中训练集中执行(CTCE)方案探索CTCE架构将多智能体问题转化为单智能体决策class CTCEAgent: def __init__(self, input_dim, output_dim, num_agents4): self.input_dim input_dim * num_agents self.output_dim output_dim * num_agents # 输出所有智能体的动作 self.policy_net DQN(self.input_dim, self.output_dim) # ...其他初始化同前... def act(self, global_state, epsilon): if random.random() epsilon: return [random.randint(0,4) for _ in range(4)] with torch.no_grad(): q_values self.policy_net(torch.FloatTensor(global_state)) return q_values.view(4, -1).argmax(dim1).tolist()CTCE的特点动作空间随智能体数量线性增长需要同时预测所有智能体的动作对全局状态信息依赖性强在实际测试中CTCE表现不如CTDE稳定主要原因包括联合动作空间过大(4个智能体各有5种动作组合数为625)错误动作的影响会相互放大难以学习细粒度的协作策略5. 调试与优化实战技巧基于实战经验分享几个提升MADQN性能的技巧奖励工程# 原始奖励 reward -0.1 per step 5 if reach goal # 优化后的奖励 reward -0.1 per step 5 if reach goal 0.5 if other agent reaches goal -0.3 if blocking the corridor网络结构优化class ImprovedDQN(nn.Module): def __init__(self, input_dim, output_dim): super().__init__() self.feature_extractor nn.Sequential( nn.Linear(input_dim, 128), nn.LayerNorm(128), nn.ReLU(), nn.Dropout(0.1) ) self.value_stream nn.Sequential( nn.Linear(128, 64), nn.ReLU(), nn.Linear(64, 1) ) self.advantage_stream nn.Sequential( nn.Linear(128, 64), nn.ReLU(), nn.Linear(64, output_dim) ) def forward(self, x): features self.feature_extractor(x) values self.value_stream(features) advantages self.advantage_stream(features) return values (advantages - advantages.mean())训练参数配置参考参数推荐值说明学习率3e-4使用Adam优化器批次大小128较大批次更稳定γ折扣因子0.99长期回报考量ε初始值1.0逐步衰减到0.1目标网络更新每100步软更新效果更佳缓冲区大小1e5覆盖多个回合在项目实践中我发现以下几个陷阱需要特别注意不要将不同架构的经验回放缓冲区混用智能体数量增加时适当扩大网络容量可视化训练过程对调试协作行为至关重要随机种子设置对结果复现性影响很大

相关新闻