MAPPO动作类型改进(二)——MAPPO+连续环境
在上一篇博客中,作者给各位学者说明如何实现 基于最新版代码+离散环境,这篇文章帮大家实现 基于最新版代码+连续环境,示例环境仍然是用MPE类,
环境说明及地址: https://pettingzoo.farama.org/environments/mpe/simple_spread/
第一步:设置连续环境模式
由于最新版light_mappo的代码默认就是使用连续环境,因此确认下是使用ContinuousActionEnv就行,原始代码是这样的话就不用动。
def make_train_env(all_args):
def get_env_fn(rank):
def init_env():
# TODO 注意注意,这里选择连续还是离散可以选择注释上面两行,或者下面两行。
# TODO Important, here you can choose continuous or discrete action space by uncommenting the above two lines or the below two lines.
from envs.env_continuous import ContinuousActionEnv
env = ContinuousActionEnv()
# from envs.env_discrete import DiscreteActionEnv
# env = DiscreteActionEnv()
env.seed(all_args.seed + rank * 1000)
return env
return init_env
return DummyVecEnv([get_env_fn(i) for i in range(all_args.n_rollout_threads)])
第二步:接入连续环境
import numpy as np
from pettingzoo.mpe import simple_spread_v3
class EnvCore(object):
"""
# 环境中的智能体
"""
def __init__(self):
self.env = simple_spread_v3.parallel_env(render_mode="human", N=3, local_ratio=0.5, max_cycles=30,
continuous_actions=True)
#智能体个数N=3,
# local_ratio:适用于本地奖励和全球奖励的权重。全局奖励权重将始终为 1 - 本地奖励权重。
# max_cycles:游戏终止前的帧数(每个代理一个步骤)
# continuous_actions:代理操作空间是离散的(默认)还是连续的
self.agent_num = 3 #环境simple_spread_v3中Agents = 3 = N
self.obs_dim = 18 #环境simple_spread_v3中Observation Shape = 18
self.action_dim =5 #环境simple_spread_v3中Action Shape = 5
def reset(self):
"""
# 重置环境,simple_spread_v3环境自带了reset函数,可直接使用
"""
sub_agent_obs = []
observations, infos = self.env.reset()
for agent in self.env.agents:
sub_agent_obs.append(observations[agent])
return sub_agent_obs
def step(self, actions):
sub_agent_obs = []
sub_agent_reward = []
sub_agent_done = []
sub_agent_info = []
i = 0 # 初始化计数器
actions_step = {} # 创建一个空字典来存储动作
# 假设env.agents是一个包含所有智能体的列表
# 并且actions是一个包含所有动作的列表
for agent in self.env.agents:
if i < len(actions): # 确保不会超出actions列表的索引范围
actions_step[agent] = actions[i] # 将智能体映射到对应的动作
i += 1 # 递增计数器
observations, rewards, terminations, truncations, infos = self.env.step(actions_step)
for agent in self.env.agents:
# 添加观察值
sub_agent_obs.append(observations[agent])
# 添加奖励
sub_agent_reward.append([rewards[agent]]) # 注意:确保rewards[agent]是单个值或一维数组
# 添加终止标志
sub_agent_done.append(terminations[agent])
# 添加附加信息
sub_agent_info.append(infos[agent])
# return [observations, rewards, terminations, infos]
return [sub_agent_obs, sub_agent_reward, sub_agent_done, sub_agent_info]
第三步:改下config.py中episode_length
由于环境中max_cycles=30,因此必须满足episode_length<30才不会报错,如果设置为30,则会报错:ValueError: need at least one array to stack
parser.add_argument("--episode_length", type=int, default=25, help="Max length for any episode")
注意事项
self.warmup():
env_runner中的self.warmup()函数放在episode循环里面还是外面,这个自定吧 (由于这个环境运行了max_cycles后,不reset的话再传入动作会报错,所以这里要放到episode里面,接入自己环境时自定) 这里不放的话可能会报错:ValueError: need at least one array to stack
关于生成的动作越限的问题
:许多学者在env_continuous文件中定义了动作值的上下限,但生成的动作仍存在超过low和high的情况,这是由于网络输出并未基于环境的限制做缩放。
u_action_space = spaces.Box(
low=-np.inf,
high=+np.inf,
shape=(self.signal_action_dim,),
dtype=np.float32,
)
解决办法:
在act.py的初始化添加self.sigmoid = nn.Sigmoid()
注:环境的标准动作是在(0,1)之间,所以用的sigmoid,如果想要动作在(-1,1)之间,额可以用self.tanh = nn.Tanh()
def __init__(self, action_space, inputs_dim, use_orthogonal, gain):
super(ACTLayer, self).__init__()
self.mixed_action = False
self.multi_discrete = False
self.continuous_action = False
self.sigmoid = nn.Sigmoid()
elif self.continuous_action:
action_logit = self.action_out(x)
actions = action_logit.mode() if deterministic else action_logit.sample()
action_log_probs = action_logit.log_probs(actions)
actions = self.sigmoid(actions)
结语
以上改进都来自个人经验,正确性还有需要结合具体环境验证,如有错误,欢迎指正
同时大家有疑问可评论留言,如 想要已经改好的代码可联系本人(可提供指导),邮箱2360278536@qq.com
对MAPPO算法代码总体流程不太了解,可以参考多智能体强化学习MAPPO源代码解读
对MAPPO算法理论知识不太了解,可以参考多智能体强化学习之MAPPO理论解读和多智能体强化学习(二) MAPPO算法详解
MAPPO+离散环境讲解