文章目录
一、待解决问题
1.1 问题描述
由于有自建环境的需求,但想使用MAPPO的算法,但MAPPO benchmark没有可以直接应用的框架,因此在网上参考学习。
1.2 解决方法
(1)下载light_mappo 源码
(2)light_mappo 框架实际应用
(3)light_mappo 代码解析
二、方法详述
2.1 必要说明
MAPPO 框架讲解参考链接:多智能体强化学习(二) MAPPO算法详解
MAPPO 框架讲解(视频)参考链接:MAPPO的代码框架解析
light_mappo 源码链接: github/ tinyzqh /light_mappo
✅非常感谢大佬的分享!!!
2.2 应用步骤
2.2.1 下载light_mappo 源码
根据源码链接下载对应源码,得到目录如下:
首先查看对应
README_CN.md
说明
## 背景
MAPPO原版代码对于环境的封装过于复杂,本项目直接将环境封装抽取出来。更加方便将MAPPO代码移植到自己的项目上。
## 安装
直接将代码下载下来,创建一个Conda环境,然后运行代码,缺啥补啥包。具体什么包以后再添加。
## 用法
- 环境部分是一个空的的实现,文件`light_mappo/envs/env_core.py`里面环境部分的实现:[Code](https://github.com/tinyzqh/light_mappo/blob/main/envs/env_core.py)
import numpy as np
class EnvCore(object):
"""
# 环境中的智能体
"""
def __init__(self):
self.agent_num = 2 # 设置智能体(小飞机)的个数,这里设置为两个
self.obs_dim = 14 # 设置智能体的观测维度
self.action_dim = 5 # 设置智能体的动作维度,这里假定为一个五个维度的
def reset(self):
"""
# self.agent_num设定为2个智能体时,返回值为一个list,每个list里面为一个shape = (self.obs_dim, )的观测数据
"""
sub_agent_obs = []
for i in range(self.agent_num):
sub_obs = np.random.random(size=(14, ))
sub_agent_obs.append(sub_obs)
return sub_agent_obs
def step(self, actions):
"""
# self.agent_num设定为2个智能体时,actions的输入为一个2纬的list,每个list里面为一个shape = (self.action_dim, )的动作数据
# 默认参数情况下,输入为一个list,里面含有两个元素,因为动作维度为5,所里每个元素shape = (5, )
"""
sub_agent_obs = []
sub_agent_reward = []
sub_agent_done = []
sub_agent_info = []
for i in range(self.agent_num):
sub_agent_obs.append(np.random.random(size=(14,)))
sub_agent_reward.append([np.random.rand()])
sub_agent_done.append(False)
sub_agent_info.append({})
return [sub_agent_obs, sub_agent_reward, sub_agent_done, sub_agent_info]
只需要编写这一部分的代码,就可以无缝衔接MAPPO。在env_core.py之后,单独提出来了两个文件env_discrete.py和env_continuous.py这两个文件用于封装处理动作空间和离散动作空间。在algorithms/utils/act.py中elif self.continuous_action:这个判断逻辑也是用来处理连续动作空间的。和runner/shared/env_runner.py部分的# TODO 这里改造成自己环境需要的形式即可都是用来处理连续动作空间的。
在train.py文件里面,选择注释连续环境,或者离散环境进行demo环境的切换。
核心点总结:
(1)直接下载源码后,创建conda虚拟环境,并运行
light_mappo-main/train/train.py
可直接调用mappo算法,缺少什么包安装什么依赖;
(2)该框架已经把mappo benchmark中的env环境
的代码抽离了出来,可以在light_mappo/envs/env_core.py
源码上修改为自己的env环境
。
2.2.3 light_mappo 框架实际应用
主要参考:强化学习-MAPPO算法解析与实践-Multi Agent Proximal Policy Optimization
✅非常感谢大佬的分享!!!
(1)安装ma-gym环境
该实例直接应用了ma_gym
当中的Combat
环境,因此首先安装ma-gym
多智能体环境,具体安装步骤及Combat
可参考:
【动手学强化学习】番外7-MAPPO应用框架2学习与复现
(2)更改环境代码
将light_mappo
中env_core.py
的环境代码修改为如下:
import time
import numpy as np
from ma_gym.envs.combat.combat import Combat
class EnvCore(object):
"""
# 环境中的智能体
"""
def __init__(self):
self.agent_num = 2
team_size = self.agent_num
grid_size = (15, 15)
self.env = Combat(grid_shape=grid_size, n_agents=team_size, n_opponents=team_size)
self.obs_dim = 150 # 设置智能体的观测维度 # set the observation dimension of agents
self.action_dim = self.env.action_space[0].n # 设置智能体的动作维度,这里假定为一个五个维度的 # set the action dimension of agents, here set to a five-dimensional
def reset(self):
s = self.env.reset()
sub_agent_obs = []
for i in range(self.agent_num):
sub_obs = np.array(s[i])#np.random.random(size=(14,))
sub_agent_obs.append(sub_obs)
return sub_agent_obs
def step(self, actions):
self.env.render("human")
time.sleep(0.4)
sub_agent_obs = []
sub_agent_reward = []
sub_agent_done = []
sub_agent_info = []
action_index = [int(np.where(act==1)[0][0]) for act in actions]
next_s, r, done, info = self.env.step(action_index)
for i in range(self.agent_num):
# r[agent_i] + 100 if info['win'] else r[agent_i] - 0.1
sub_agent_obs.append(np.array(next_s[i]))
# sub_agent_reward.append([r[i] + 100 if info['winners'] else r[i] - 0.1])
sub_agent_reward.append(r[i])
sub_agent_done.append(done[i])
sub_agent_info.append(info)
return [sub_agent_obs, sub_agent_reward, sub_agent_done, sub_agent_info]
(3)解决报错
首次运行,关键报错如下:
libGL error: MESA-LOADER: failed to open iris:
libGL error: MESA-LOADER: failed to open swrast
version `GLIBCXX_3.4.30’ not found
ContextException: Could not create GL context
从报错信息来看,询问大模型,大概率是加载 OpenGL 驱动时遇到了问题,特别是 iris 和 swrast 驱动。
并且发现缺少 GLIBCXX_3.4.30,可以尝试升级 libstdc++ 库,这一步骤可参考:
【动手学强化学习】番外5-MPE(Multi-agent Particle-World Environment)多智能体仿真环境介绍
大致过程总结如下:
#安装或更新 MESA 驱动
sudo apt-get install mesa-utils
sudo apt-get install mesa-opencl-icd
#排查当前conda环境是否缺失GLIBCXX_3.4.30,XXXX改为自己的用户名
strings /home/XXXX/anaconda3/envs/simple_mappo/lib/libstdc++.so.6 | grep GLIBCXX
#若缺失GLIBCXX_3.4.30的话,更新libstdcxx-ng版本,,无缺失即可省略
#查询当前libstdcxx-ng版本
conda list | grep libstdcxx-ng
#直接通过默认源是无法升级安装libstdcxx-ng的,需要先添加conda-forge源
conda config --add channels conda-forge
#可以执行以下命令来查看下载源
conda config --show channels
conda install libstdcxx-ng=12.1.0
conda list | grep libstdcxx-ng
#升级完成之后再查询 GLIBCXX 版本
strings /home/XXXX/anaconda3/envs/simple_mappo/lib/libstdc++.so.6 | grep GLIBCXX
#如果 iris_dri.so 和 swrast_dri.so 文件存在于 /usr/lib/x86_64-linux-gnu/dri 目录下,但系统无法找到它们,可以尝试创建软链接
cd /usr/lib
#创建文件夹
sudo mkdir ./dri
#创建iris_dri.so文件软链接
sudo ln -s /usr/lib/x86_64-linux-gnu/dri/iris_dri.so /usr/lib/dri/
#创建swrast_dri.so文件软链接
sudo ln -s /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so /usr/lib/dri/
cd dri
ls
#记得删除conda-forge镜像源
conda config --remove channels conda-forge
rm ~/.condarc
conda config --add channels defaults
conda config --set show_channel_urls yes
#测试源是否删除(安装一个仅有conda-forge有的包)
conda install libstdcxx-ng=12.2.0
能够成功运行,但是到第5步依然会报错:
File ~/code/light_mappo-main/utils/separated_buffer.py:70, in SeparatedReplayBuffer.insert(self, share_obs, obs, rnn_states, rnn_states_critic, actions, action_log_probs, value_preds, rewards, masks, bad_masks, active_masks, available_actions)
68 self.action_log_probs[self.step] = action_log_probs.copy()
69 self.value_preds[self.step] = value_preds.copy()
—> 70 self.rewards[self.step] = rewards.copy()
71 self.masks[self.step + 1] = masks.copy()
72 if bad_masks is not None:
ValueError: could not broadcast input array from shape (5,) into shape (5,1)
总体感觉,方法之间封装太多层了,不好调试。
2.2.2 light_mappo 代码解析
(后续补充)
三、疑问
暂无。
四、总结
- light_mappo 框架直接基于原文献MAPPO的框架上将
环境
独立了出来,但是原框架内容还是比较繁琐,封装了很多层,不如人直接理解PPO原理,然后直接在PPO算法的框架下,设计centralized_V
,即全局中心化critic网络
,直接就应用为MAPPO算法;若每个agent采用自身的critic网络
,即为IPPO算法。 - 在agent类型上,可考虑
shared policy
或separated policy
以确定同质
或异质
智能体,其本质上就是多agent使用一个policy网络和还是分别是用各自的policy网络。