相比于传统的RL,MARL的几个挑战:
-
环境非静态性:其他智能体的行为变化导致环境对于任一智能体来说都是非静态的,即环境的动态性不仅来自环境本身的变化,还来自其他智能体策略的变化。
-
部分可观察性:在多智能体环境中,一个智能体可能无法完全观察到环境的全部状态,包括其他智能体的私有信息和意图。这导致学习过程中存在不确定性,增加了决策的复杂度。
-
信用分配问题:当多个智能体共同作用于环境并共享奖励时,确定每个智能体对共同结果贡献的程度(即信用分配)变得挑战,特别是在合作任务中。这个也会造成虚假奖励:对其中一个智能体来说,其获得的团队奖励很有可能是其队友的行为导致的。
论文链接:https://arxiv.org/abs/1706.02275
代码参考:xuance/examples/maddpg/maddpg_simple_spread.py at master · agi-brain/xuance · GitHub
动机:
主要是以上MARL挑战中的第一点 ,环境的非静态性。
传统方法用于MARL的挑战:
- Q-Learning:非静态性:随着其他个体更新策略,环境以一种不仅仅由学习者的行为所能解释的方式动态变化,单纯Q值的估计变得困难。
- 策略梯度方法:随着智能体数量的增加,梯度估计的方差增加,使得多智能体的协调变得更加困难。
模型框架:
这篇文章就是采用了集中训练与分散执行的框架,是对经典的演员-评论家方法的改进,解决了以上问题。以下是算法的框架,可以看到每个智能体的训练都与其他智能体采取的动作以及当前的Q值有关。
模型训练:
MADDPG的主要思想是,在多智能体环境中,即便个体智能体的策略在持续变化,如果我们能够知道所有智能体的行动选择,环境对于学习系统来说可以被认为是静态的。这意味着环境的变化完全可以通过智能体的行动来预测,而不是不可预知的外部变化。
因此在以下的训练过程中,Q网络的输入都加了所有智能体的行动选择ai。
Actor训练:
这是传统的策略梯度(DDPG):
这是本文的:
基本是一样的,都是采用的链式法则,区别是Q值的定义。Q的输入也不是简单的(s,a),而是(x,a1....aN),x是全局状态,ai的输入能考虑到其他个体策略对环境带来的影响。此外缓冲池的实现:多智能体的缓冲池存入的是(x,a,r,x‘)。x代表全局状态,a是(a1...aN)。r是(r1....rN)。
# train actor
_, actions_eval = self.policy(obs, IDs)
loss_a = -(self.policy.critic(obs, actions_eval, IDs) * agent_mask).sum() / agent_mask.sum()#IDs是智能体的标识符,用于policy.critic来识别当前智能体是团队的第几个,agent_mask是智能体掩码,由环境给出,用于识别当前在环境仍然活跃的智能体,为1代表活跃,才会把loss考虑
self.optimizer['actor'].zero_grad()
loss_a.backward()
if self.args.use_grad_clip:
torch.nn.utils.clip_grad_norm_(self.policy.parameters_actor, self.args.grad_clip_norm)#梯度裁剪,防梯度爆炸
self.optimizer['actor'].step()
if self.scheduler['actor'] is not None:
self.scheduler['actor'].step()
Critic训练:
和DDPG大同小异,区别仅仅是Q网络的输入加了所有智能体的行动。
# train critic
actions_next = self.policy.target_actor(obs_next, IDs)
q_eval = self.policy.critic(obs, actions, IDs)
q_next = self.policy.target_critic(obs_next, actions_next, IDs)
q_target = rewards + (1 - terminals) * self.args.gamma * q_next
td_error = (q_eval - q_target.detach()) * agent_mask
loss_c = (td_error ** 2).sum() / agent_mask.sum()
self.optimizer['critic'].zero_grad()
loss_c.backward()
if self.args.use_grad_clip:
torch.nn.utils.clip_grad_norm_(self.policy.parameters_critic, self.args.grad_clip_norm)
self.optimizer['critic'].step()
if self.scheduler['critic'] is not None:
self.scheduler['critic'].step()
self.policy.soft_update(self.tau)
技巧:
推断其他代理的策略:
文中提到了:“为了消除知道其他智能体策略的假设”,怎么理解呢,因为缓冲池中取出的a1...aN代表过去的所有智能体策略会执行的动作,这不能代表他们现在的行动选择。
为了能构造出更贴切的策略模拟,对每个智能体构造了一个网络,网络的训练:损失L从经验回放中其他策略在某个状态做出的动作学习,知道其他策略大概会怎么做:
,H是熵。
最后目标Q值的输入可以用拟合的策略去估计:
策略集合优化:
通过为每个代理训练一组策略集合(即策略集合),来提高多智能体策略的稳定性和鲁棒性。每个代理不是只学习一个策略,而是学习多个子策略,并在每次执行时随机选择一个子策略来执行。这种方法的目标是使得学习到的策略对于其他代理策略的变化更加鲁棒,主要体现在:
1.在每个回合开始时,智能体随机选择一个子策略来执行整个回合的动作。
2.在训练过程中,通过下式来训练:
具体来说,每个策略从自己独有的缓冲区中Di中取出样本来算得loss,最后对K个子策略进行一个平均,平均的方法能降低他们的方差减少不稳定性。
这种策略选择方法促使每个代理需要与多样化的策略互动,进而增强了与不同对手或合作者互动时的稳定性和效果。
实验环境:https://github.com/openai/multiagent-particle-envs
文中的几种实验环境,这些环境在后面应该用的不多了。
在上图从左至右:
1.合作通信:需要两个智能体(一个发言者和一个听者)通过合作完成任务,发言者向听者传达目标地标的颜色,听者根据发言者的指示找到正确的地标。
2.捕食者与猎物:慢速的合作智能体需要追捕更快的猎物智能体,通过物理障碍物进行辅助。
3.合作导航:多个智能体需要通过物理行动合作覆盖所有地标,同时避免相互碰撞。
4.物理欺骗:合作智能体需要到达某个目标地标,但存在一个对立智能体也想到达目标地标,且不知道正确的地标是哪一个,因此合作智能体需要通过分散来欺骗对立方。
最后与早期的DDPG,reinforce,DQN等算法进行比较,效果更好。
自己跑了一个mpe中的simple_spread_v3的环境: