1. 项目概述:从零理解团队对称随机博弈与DelAC
最近在复现和梳理多智能体强化学习(Multi-agent Reinforcement Learning, MARL)领域的一些前沿工作,一个名为“DelAC”的框架引起了我的注意。这个标题“DelAC: A Multi-agent Reinforcement Learning of Team-Symmetric Stochastic Games”信息量很大,它直接点明了三个核心:方法名(DelAC)、应用领域(MARL)、以及要解决的具体问题(Team-Symmetric Stochastic Games)。简单来说,DelAC试图为一种特殊的、具有团队内部对称性的随机博弈场景,设计一套高效的学习算法。
这听起来有点绕,让我用更直白的话解释一下。想象一个足球比赛,我们关注的是其中一支队伍。在这支队伍内部,前锋、中场、后卫虽然位置和具体任务不同,但他们共享一个最高目标:赢得比赛。同时,队伍内部可能存在某种“对称性”——例如,两个边锋的角色和决策逻辑在很大程度上是相似的,都涉及边路突破、传中或内切。传统的MARL算法在处理这种场景时,往往把每个智能体当作完全独立的个体来训练,或者进行简单的参数共享,这忽略了智能体之间这种结构化的相似性(对称性),导致样本效率低下、策略难以泛化,并且无法利用这种对称性来稳定训练。DelAC正是瞄准了这个痛点,它通过一种新颖的“演员-注意力-评论家”(Actor-Attention-Critic)架构,让智能体在保持个体特异性的同时,能够隐式地学习和利用团队内部的对称结构,从而在复杂的随机博弈环境中实现更优、更稳定的协同。
如果你正在研究多智能体协同、博弈论与机器学习的交叉领域,或者你的项目涉及需要智能体团队合作且内部存在角色相似性的场景(如多机器人编队、智能交通调度、游戏AI战队),那么深入理解DelAC背后的思想与实现细节,将会为你打开一扇新的大门。它不仅是一个算法,更是一种处理特定多智能体系统结构先验的有效范式。
2. 核心问题拆解:什么是团队对称随机博弈?
要弄懂DelAC,必须先彻底理解它要解决的“Team-Symmetric Stochastic Games”到底是什么。这需要我们拆解几个关键概念:随机博弈、团队、以及最核心的对称性。
2.1 随机博弈:多智能体交互的动态舞台
随机博弈是马尔可夫决策过程(MDP)在多智能体场景下的自然扩展。它提供了一个标准的数学模型,用于描述多个智能体在不确定环境中进行序贯决策的交互过程。一个随机博弈通常由以下几个要素定义:
- 智能体集合:N个智能体。
- 状态空间 S:所有可能的环境状态集合。
- 动作空间 A_i:每个智能体i可采取的动作集合。联合动作空间为 A = A_1 × ... × A_N。
- 状态转移函数 P(s' | s, a):在状态s下,所有智能体采取联合动作a后,环境转移到状态s'的概率。
- 奖励函数 R_i(s, a, s'):智能体i在状态s下执行联合动作a并转移到s'后获得的即时奖励。
- 折扣因子 γ:用于计算未来奖励的现值。
每个智能体的目标是学习一个策略 π_i(a_i | s),以最大化自身期望的累积折扣奖励。在多智能体环境中,由于其他智能体的策略也在不断变化,环境从每个智能体的视角看是非平稳的,这构成了MARL的核心挑战。
2.2 团队目标与个体目标的权衡
“Team”在这里意味着智能体们共享一个全局的团队回报(Team Reward)。这与完全竞争或混合动机的博弈不同。在团队随机博弈中,通常假设存在一个全局奖励函数 R_team(s, a, s'),所有智能体都依据这个相同的信号进行学习。也就是说,大家的终极目标是一致的。例如,在足球模拟中,团队的共同奖励可能是进球得分、控球率等。
然而,仅仅共享团队奖励并不够。智能体个体仍然需要做出决策,并且它们观察到的局部信息(局部观测 o_i)、可执行的动作可能不同。这就引出了“信用分配”问题:团队的成功或失败,具体应该归因于哪个智能体的哪个决策?DelAC需要在其框架内有效地解决这个问题。
2.3 对称性:提升学习效率的关键结构先验
“Symmetric”是DelAC论文标题中最精妙也最关键的部分。这里的对称性并非指智能体完全同质(那样问题就退化为单智能体或参数共享的多智能体了),而是指一种“团队内部”的对称性。更具体地说,它通常指的是置换对称性。
假设团队中有多个智能体扮演相似或相同的角色。例如,在一个“狼羊草”的简化生态模拟中,有多只“狼”。这些狼在团队中扮演相同的捕食者角色,它们的目标(捕捉羊)、能力(移动速度、攻击力)和对世界的感知方式在本质上是相同的。那么,如果我们任意交换两只狼的“标识”(ID),整个团队的目标函数和动态过程应该是不变的。这就是一种置换对称性。
从数学上讲,这种对称性意味着,对于智能体索引的某个置换变换σ,团队的联合价值函数和状态转移动力学在该变换下是不变的。这种结构先验蕴含着巨大的价值:
- 样本效率:一个智能体学到的经验,可以潜在地被具有对称角色的其他智能体所利用。
- 策略泛化:学习到的策略能够更好地泛化到团队规模变化或角色轮换的场景。
- 训练稳定性:对称性约束可以作为一种正则化,减少策略空间的搜索范围,避免智能体学习到一些怪异、不协调的行为模式。
传统方法如参数共享(所有智能体共用同一个策略网络)强制了一种硬对称,但牺牲了智能体根据其独特观察做出细微调整的能力。DelAC的目标是设计一种柔和的、数据驱动的方式来学习和利用这种对称性,而不是强行施加。
3. DelAC框架深度解析:Actor-Attention-Critic的协同设计
DelAC的全称是“Decentralized Actor-attention-Critic”,其核心创新在于将注意力机制巧妙地融入到了去中心化的执行者-评论家框架中,以自动捕捉和利用智能体间的对称关系。下面我们来拆解它的三大组件。
3.1 去中心化执行者:基于局部观测的个体策略
与许多中心化训练分布式执行(CTDE)的框架一致,DelAC的每个智能体i在执行阶段,拥有一个去中心化的演员网络(Actor)。这个网络以智能体自身的局部观测 o_i 为输入,输出其个体动作 a_i 的概率分布(或确定性动作)。
π_i(a_i | o_i; θ_i)这里,θ_i 是智能体i的演员网络参数。关键点在于:DelAC并不要求这些θ_i相同(即不是硬参数共享)。每个智能体可以有自己的网络参数,这使得它们能够适应各自独特的观察视角。对称性的约束,将通过后续的注意力机制和评论家网络来软性地施加。
3.2 注意力机制:动态构建智能体关系图
这是DelAC的灵魂所在。为了能让智能体在训练时考虑到同伴,又不引入中心化控制器,DelAC为每个智能体引入了一个注意力模块。这个模块的作用是,让智能体i学会“关注”其他智能体中哪些与自己当前决策最相关。
具体实现通常如下:
- 查询(Query)、键(Key)、值(Value)的生成:每个智能体j(包括i自己)将其编码后的局部观测特征 h_j 通过不同的线性变换,生成查询向量 q_j、键向量 k_j 和值向量 v_j。
- 注意力权重计算:对于智能体i,它用自己的查询向量 q_i 去与所有智能体(包括自己)的键向量 k_j 进行点积,然后通过softmax归一化,得到一组注意力权重 α_{i,j}。
其中 d_k 是键向量的维度。权重 α_{i,j} 代表了在智能体i看来,智能体j的信息对于自己当前决策的重要性。α_{i,j} = softmax( (q_i · k_j) / sqrt(d_k) ) - 上下文向量聚合:智能体i将所有的值向量 v_j 用注意力权重 α_{i,j} 进行加权求和,得到一个聚合的上下文向量 c_i。
c_i = Σ_j (α_{i,j} * v_j)
这个上下文向量 c_i 捕获了团队中所有智能体信息的加权摘要,它隐含地编码了智能体之间的关系。如果两个智能体角色对称,那么它们相互关注的权重(α_{i,j} 和 α_{j,i})可能会很高,并且它们对于其他智能体的关注模式也会相似。
3.3 中心化评论家:全局视野与信用分配
在训练阶段,DelAC使用一个中心化的评论家网络(Critic)。这个评论家以全局状态 s(或所有智能体的观测拼接)以及所有智能体的联合动作 a 为输入,输出一个估计的团队状态-动作价值函数 Q_team(s, a)。
Q_team(s, a; φ)这里φ是评论家网络的参数。中心化评论家拥有全局信息,因此能够更准确地评估联合动作的长期价值。它的学习目标是最小化时序差分误差(TD-error):
L(φ) = E[(r_team + γ * Q_team(s', ā') - Q_team(s, a))^2]其中 ā' 是目标演员网络在下一状态s‘下采样的动作。
评论家如何与演员和注意力协同工作?
- 梯度传递:评论家计算出的Q值梯度,会通过反向传播传递到每个智能体的演员网络和注意力模块。
- 信用分配:由于Q值是针对联合动作的,梯度中包含了“哪个智能体的动作对团队价值贡献更大”的信息。注意力机制会学习调整权重,使得智能体更关注那些对团队价值贡献大的同伴的行为模式,从而间接实现了精细化的信用分配。
- 对称性涌现:在训练过程中,如果两个智能体角色对称,那么他们从相似的评论家梯度中学习,他们的注意力模块会学会关注相似的其他智能体集合,他们的演员网络也会在对称的观测下产生对称的动作分布。这种对称性不是预设的,而是从数据和团队目标中涌现出来的。
注意:DelAC的这种设计巧妙地平衡了“去中心化执行”的灵活性和“中心化训练”的稳定性。注意力机制充当了一个可学习的通信信道,让智能体在训练时能够进行隐式协调,而执行时又完全独立。
4. 实操实现:构建一个DelAC智能体团队
理论说得再多,不如动手实现一遍。这里我将以一个简化的团队协作环境(例如OpenAI的Multi-Agent Particle Environment中的Simple Spread场景)为例,勾勒出实现DelAC的关键步骤和代码框架。我们使用PyTorch作为深度学习框架。
4.1 环境与智能体定义
首先,我们需要一个环境,其中包含N个智能体,它们共享一个团队奖励(例如,所有智能体到达各自目标点的负距离之和加上避免碰撞的惩罚)。每个智能体获得局部观测,如自身位置、速度、目标点位置以及附近其他智能体和障碍物的相对位置。
我们定义智能体类DelACAgent:
import torch import torch.nn as nn import torch.nn.functional as F class AttentionLayer(nn.Module): """一个简单的多头注意力层""" def __init__(self, embed_dim, num_heads): super().__init__() self.multihead_attn = nn.MultiheadAttention(embed_dim, num_heads, batch_first=True) def forward(self, query, key, value): # query, key, value shape: (batch_size, num_agents, embed_dim) attn_output, attn_weights = self.multihead_attn(query, key, value) return attn_output, attn_weights # attn_weights用于可视化分析关系 class ActorNetwork(nn.Module): """去中心化演员网络,输入局部观测,输出动作分布""" def __init__(self, obs_dim, action_dim, hidden_dim=128): super().__init__() self.fc1 = nn.Linear(obs_dim, hidden_dim) self.fc2 = nn.Linear(hidden_dim, hidden_dim) # 输出动作概率分布(离散)或均值方差(连续) self.mean_head = nn.Linear(hidden_dim, action_dim) self.log_std_head = nn.Linear(hidden_dim, action_dim) # 连续动作 def forward(self, obs): x = F.relu(self.fc1(obs)) x = F.relu(self.fc2(x)) mean = self.mean_head(x) log_std = self.log_std_head(x) log_std = torch.clamp(log_std, min=-20, max=2) # 限制标准差范围 return mean, log_std class CentralizedCriticNetwork(nn.Module): """中心化评论家网络,输入全局状态和所有动作,输出团队Q值""" def __init__(self, global_state_dim, total_action_dim, hidden_dim=256): super().__init__() # 全局状态和联合动作通常先分别处理再合并 self.state_encoder = nn.Linear(global_state_dim, hidden_dim) self.action_encoder = nn.Linear(total_action_dim, hidden_dim) self.fc1 = nn.Linear(hidden_dim * 2, hidden_dim) self.fc2 = nn.Linear(hidden_dim, hidden_dim) self.q_head = nn.Linear(hidden_dim, 1) def forward(self, global_state, all_actions): state_feat = F.relu(self.state_encoder(global_state)) action_feat = F.relu(self.action_encoder(all_actions)) x = torch.cat([state_feat, action_feat], dim=-1) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) q_value = self.q_head(x) return q_value class DelACAgent: """DelAC智能体封装类""" def __init__(self, agent_id, obs_dim, action_dim, global_state_dim, num_agents): self.id = agent_id self.obs_dim = obs_dim self.action_dim = action_dim # 个体演员网络 self.actor = ActorNetwork(obs_dim, action_dim) # 注意力模块(所有智能体可共享,也可各有各的,论文中常共享) self.attention = AttentionLayer(embed_dim=128, num_heads=4) # 用于生成Q/K/V的编码器 self.obs_encoder = nn.Linear(obs_dim, 128) # 注意:评论家网络是全局的,不属于单个智能体,在训练循环中统一管理4.2 训练循环的核心步骤
训练在每一轮(episode)的每一步(step)中进行,核心步骤如下:
# 伪代码流程 for episode in range(total_episodes): state = env.reset() done = False while not done: all_actions = [] all_obs = [] all_encoded_obs = [] # 1. 收集观测并编码 for agent in agents: obs = agent.get_observation(state) # 从全局状态提取局部观测 encoded_obs = agent.obs_encoder(torch.FloatTensor(obs)) all_obs.append(obs) all_encoded_obs.append(encoded_obs) # 2. 应用注意力,获取上下文信息 encoded_obs_stack = torch.stack(all_encoded_obs, dim=0).unsqueeze(0) # (1, num_agents, feat_dim) context_vectors, attn_weights = attention_layer(encoded_obs_stack, encoded_obs_stack, encoded_obs_stack) # context_vectors shape: (1, num_agents, feat_dim),每个智能体对应一个上下文向量 # 3. 演员网络基于局部观测和上下文选择动作 for i, agent in enumerate(agents): obs_tensor = torch.FloatTensor(all_obs[i]) # 可以将上下文向量与编码后的观测拼接,作为演员的增强输入 context_for_i = context_vectors[0, i] actor_input = torch.cat([obs_tensor, context_for_i.detach()], dim=-1) # detach避免梯度流过注意力影响其他智能体策略 mean, log_std = agent.actor(actor_input) dist = torch.distributions.Normal(mean, torch.exp(log_std)) action = dist.sample() all_actions.append(action) # 4. 环境执行联合动作,得到下一状态和团队奖励 joint_action = torch.stack(all_actions).squeeze().numpy() next_state, team_reward, done, _ = env.step(joint_action) # 5. 将经验(s, a, r, s')存入回放缓冲区 replay_buffer.push(state, all_actions, team_reward, next_state, done) state = next_state # 6. 定期从缓冲区采样,更新网络 if len(replay_buffer) > batch_size: batch = replay_buffer.sample(batch_size) update_networks(batch, agents, centralized_critic, optimizer_actor, optimizer_critic)4.3 网络更新细节
update_networks函数是学习发生的核心:
def update_networks(batch, agents, critic, opt_actor, opt_critic): states, actions, rewards, next_states, dones = batch # 更新评论家 with torch.no_grad(): # 计算目标Q值:r + γ * Q'(s', π'(s')) next_actions = [] for i, agent in enumerate(agents): # 使用目标演员网络(延迟更新)计算下一动作 next_obs_i = ... # 从next_states提取 next_context_i = ... # 使用目标注意力网络计算 next_actor_input_i = torch.cat([next_obs_i, next_context_i], dim=-1) next_mean, next_log_std = agent.target_actor(next_actor_input_i) next_dist = torch.distributions.Normal(next_mean, torch.exp(next_log_std)) next_action_i = next_dist.sample() next_actions.append(next_action_i) next_joint_actions = torch.cat(next_actions, dim=-1) target_q = rewards + gamma * (1 - dones) * critic.target_network(next_states, next_joint_actions) current_q = critic.network(states, torch.cat(actions, dim=-1)) critic_loss = F.mse_loss(current_q, target_q) opt_critic.zero_grad() critic_loss.backward() opt_critic.step() # 更新演员(策略梯度) actor_losses = [] for i, agent in enumerate(agents): # 重新计算当前状态下的动作(为了获取梯度) obs_i = ... context_i = ... # 使用当前注意力网络计算 actor_input_i = torch.cat([obs_i, context_i], dim=-1) mean_i, log_std_i = agent.actor(actor_input_i) dist_i = torch.distributions.Normal(mean_i, torch.exp(log_std_i)) action_i = dist_i.rsample() # 使用重参数化技巧 # 为了计算联合动作的Q值,需要其他智能体的动作。这里使用回放缓冲区中存储的动作, # 但在计算梯度时只对agent i的动作求导。一种常见做法是使用当前策略重新采样其他智能体的动作(在计算图中)。 other_actions = [] for j in range(len(agents)): if j == i: other_actions.append(action_i) else: # 使用其他智能体当前的策略网络,但阻止梯度传播(detach) obs_j = ... context_j = ... actor_input_j = torch.cat([obs_j, context_j.detach()], dim=-1) mean_j, log_std_j = agents[j].actor(actor_input_j) dist_j = torch.distributions.Normal(mean_j, torch.exp(log_std_j)) other_actions.append(dist_j.rsample().detach()) # 其他动作不参与i的梯度计算 joint_actions = torch.cat(other_actions, dim=-1) q_value = critic.network(states, joint_actions) # 策略梯度目标:最大化Q值,同时加上熵正则项鼓励探索 log_prob_i = dist_i.log_prob(action_i).sum(dim=-1, keepdim=True) entropy_i = dist_i.entropy().sum(dim=-1, keepdim=True) actor_loss = -(q_value + entropy_beta * entropy_i).mean() actor_losses.append(actor_loss) opt_actor.zero_grad() total_actor_loss = torch.stack(actor_losses).sum() total_actor_loss.backward() opt_actor.step() # 软更新目标网络 soft_update(critic.network, critic.target_network, tau) for agent in agents: soft_update(agent.actor, agent.target_actor, tau)实操心得:在实现演员更新时,如何处理其他智能体的动作是一个关键细节。上述代码中,我们让智能体i的动作参与梯度计算,而其他智能体的动作则使用其当前策略采样并
detach()。这近似于一种“课程学习”,每个智能体在假设其他智能体策略固定的情况下优化自己,但通过中心化评论家Q(s, a)的梯度,所有智能体的策略实际上在协同进化。另一种更精确但复杂的方法是使用类似MADDPG的集中式策略梯度,需要存储所有智能体的策略网络。
5. 调参要点与常见问题排查
DelAC作为一个相对复杂的MARL算法,包含多个神经网络和超参数,调试起来需要耐心和技巧。以下是我在复现和实验过程中总结的一些关键点。
5.1 超参数敏感区
注意力相关参数:
- 嵌入维度(embed_dim)和头数(num_heads):这决定了注意力机制的表达能力。维度太小可能无法捕捉复杂关系,太大则容易过拟合并增加计算量。对于中小型团队(3-10个智能体),128维、4-8个头是一个不错的起点。
- 注意力层的输入:是使用原始观测,还是编码后的特征?通常先用一个全连接层对观测进行编码再输入注意力层,效果更好。
学习率与优化器:
- 评论家和演员通常需要不同的学习率。评论家负责拟合Q值,任务相对直接,学习率可以稍高(如1e-3)。演员负责策略优化,更加不稳定,学习率应更低(如5e-4或1e-4)。
- 使用Adam优化器通常比SGD更稳定。可以考虑为评论家和演员使用不同的优化器实例。
熵正则化系数(entropy_beta):
- 这个参数控制探索的强度。在训练初期,可以设置一个较大的值(如0.1)鼓励智能体广泛探索。随着训练进行,可以线性衰减到一个小值(如0.01),让策略逐渐收敛。
回放缓冲区与批次大小:
- MARL的非平稳性使得经验回放更加重要。缓冲区需要足够大(通常存储数十万到百万条经验)。
- 批次大小(batch_size)不宜过小,256或512是常见选择,以确保梯度估计的稳定性。
5.2 训练不稳定的典型症状与对策
| 症状 | 可能原因 | 排查与解决思路 |
|---|---|---|
| Q值爆炸或变成NaN | 学习率过高;评论家网络太深/太宽导致梯度爆炸;奖励未做适当缩放。 | 1. 大幅降低评论家学习率。 2. 为评论家网络添加梯度裁剪( torch.nn.utils.clip_grad_norm_)。3. 对团队奖励进行归一化,例如减去移动平均,除以标准差。 |
| 策略不收敛,智能体行为随机 | 熵系数过大;演员学习率过高;注意力机制未起作用,智能体未有效利用同伴信息。 | 1. 逐步减小熵系数beta。 2. 降低演员学习率。 3. 可视化注意力权重矩阵,检查智能体间是否有关注模式。如果权重均匀,可能是注意力模块学习失败,尝试简化网络或增加训练数据。 |
| 智能体学会“懒惰”策略 | 团队奖励设计有缺陷,存在局部最优或“搭便车”可能。例如,完成子任务有奖励,但智能体不协作也能获得少量奖励。 | 重新设计奖励函数,确保其可分解性和全局一致性。考虑加入基于进度的奖励,或者使用反事实基线等更高级的信用分配方法作为补充。 |
| 训练后期性能突然崩溃 | 过拟合;或者由于策略改进,经验分布发生剧烈变化,导致旧数据主导的回放缓冲区中的Q值估计不准。 | 1. 在演员和评论家网络中引入Dropout或L2正则化。 2. 使用优先级经验回放(PER),让算法更关注近期、TD误差大的经验。 3. 定期清空部分旧经验,或使用更大的缓冲区。 |
5.3 注意力权重的可视化与诊断
注意力机制是DelAC的灵魂,但其内部工作往往是黑盒。定期可视化注意力权重是强大的诊断工具。
# 在训练过程中,定期保存或打印注意力权重 # attn_weights 形状为 (batch_size, num_heads, num_agents, num_agents) # 取第一个样本,第一个注意力头,智能体0对所有智能体的注意力 weights_agent0 = attn_weights[0, 0, 0, :].detach().cpu().numpy() print(f"Agent 0 对各个智能体的注意力分布: {weights_agent0}") # 可以绘制热力图 import matplotlib.pyplot as plt import seaborn as sns plt.figure(figsize=(8,6)) sns.heatmap(attn_weights[0,0].cpu().numpy(), annot=True, cmap='YlOrRd', xticklabels=[f'A{i}' for i in range(num_agents)], yticklabels=[f'A{i}' for i in range(num_agents)]) plt.title('Attention Weights (Head 0)') plt.xlabel('Key (Other Agents)') plt.ylabel('Query (Current Agent)') plt.show()一个健康的注意力模式应该显示出一定的结构。例如,在对称角色中,智能体0和智能体1可能会相互高度关注,并且它们对智能体2(可能扮演不同角色)的关注度较低。如果热力图看起来几乎是均匀的或完全混乱的,说明注意力模块没有学到有意义的关系,需要检查网络结构或学习过程。
6. 超越基础:DelAC的进阶思考与扩展
实现一个能跑的DelAC只是第一步。要让它在实际复杂场景中发挥威力,还需要考虑以下几个进阶问题。
6.1 处理部分可观测与非对称性
标准的DelAC假设每个智能体都能获取所有其他智能体的信息来生成键值对(即使只是编码后的特征)。在完全去中心化且通信受限的场景下,这可能不现实。一种扩展是局部注意力,即每个智能体只能“看到”一定范围内的邻居智能体。这时,注意力计算只在邻居集合内进行,这更符合机器人或无线传感器网络的实际约束。
此外,团队中可能存在完全非对称的角色(如足球中的守门员和前锋)。DelAC框架本身并不排斥非对称性。注意力机制可以自动学习到不同角色之间的关注模式差异。例如,前锋可能更关注另一个前锋和传球路线上的中场,而守门员可能更关注对方前锋和己方后卫。我们可以通过为不同角色的智能体提供不同的观测编码器或甚至不同的注意力模块初始化来提供先验引导。
6.2 与现有MARL范式的结合
DelAC的思想可以与其他MARL技术结合:
- 与QMIX/VDN结合:DelAC的评论家输出的是团队Q值。我们可以将其替换为QMIX的混合网络,将团队Q值分解为个体Q值的非线性组合,可能能更好地处理某些信用分配问题。
- 与LSTM/POMDP结合:在部分可观测环境中,可以将智能体的观测历史通过LSTM编码后再输入注意力层和演员网络,使智能体具备记忆能力。
- 与课程学习/自博弈结合:对于竞争性或混合动机的环境,可以先用DelAC训练一个协作团队,然后将其作为对手进行自博弈,以训练更强大的策略。
6.3 对计算资源的考量
注意力机制的计算复杂度与智能体数量的平方成正比(O(N²))。对于大规模智能体系统(如百个以上),这将成为瓶颈。可以考虑以下优化:
- 使用稀疏注意力:只计算每个智能体与最近K个邻居的注意力。
- 分层注意力:先将智能体分组成簇,在簇内和簇间分别计算注意力。
- 线性注意力变体:研究如Linformer、Performer等线性复杂度的注意力近似方法。
在我自己的实验中发现,DelAC的核心优势在于其优雅地将对称性先验转化为一个可学习的注意力机制,从而在样本效率、策略泛化性和训练稳定性之间取得了良好的平衡。它不像硬参数共享那样死板,也不像完全独立学习那样低效。对于任何涉及具有内在协作结构和角色相似性的多智能体任务,DelAC都是一个非常值得尝试和深入挖掘的起点。