在浪潮AiStation上部署RoboCup3D深度强化学习环境
简介
浪潮AiStation上的开发环境和训练任务都是基于镜像创建容器来运行的,所以需要先配置一个可用于RoboCup3D优化的环境,但是集群只能内网访问,无法访问公网资源,显然环境配置无法直接在集群上进行。
制作包含RoboCup3D深度强化学习环境的容器镜像
通过阅读AiStation技术文档我们发现可以自己现在本地docker容器中配置好环境然后导出为tar,再导入集群使用。
创建Ubuntu的docker容器
-
之前在实验室一台物理机上装了个飞牛系统,于是此处直接使用飞牛自带的docker管理功能,直接在docker中搜索Ubuntu,然后点击右边的下载按钮,选择标签22.04然后确定就开始下载了,可以在本地镜像中看到下载进度,这里我已经下载好了
-
点击上图中右边的三角形可以直接创建容器,然后点击下一步,在高级设置界面创建两个端口转发,容器内22端口映射到10086,用于SSH,4200端口映射到10087,用于观察FCP底层强化学习训练是否可以正常进行
- 然后直接一路确定即可创建容器,创建好的容器在容器里可以看见
配置容器内环境
- 先按照AiStation官方教程来操作,对openssh进行安装和设置
apt-get update
# 安装openssh提供远程登录支持
apt-get install openssh-client
apt-get install openssh-server
# 配置openssh
/usr/bin/ssh-keygen -A
cat /etc/ssh/ssh_config | grep -v StrictHostKeyChecking > /etc/ssh/ssh_config.new
echo " StrictHostKeyChecking no" >> /etc/ssh/ssh_config.new
cat /etc/ssh/sshd_config | grep -v PermitRootLogin > /etc/ssh/sshd_config.new
echo "PermitRootLogin yes" >> /etc/ssh/sshd_config.new
mv -f /etc/ssh/ssh_config.new /etc/ssh/ssh_config
mv -f /etc/ssh/sshd_config.new /etc/ssh/sshd_config > /dev/null 2>&1
# 启动openssh
mkdir -p /run/sshd
chmod 0755 /run/sshd
/usr/sbin/sshd
到这一步完成了基础环境的配置,此时的容器导出后已经具备在集群中使用的能力
- 配置RoboCup3D环境 安装sudo
apt install sudo
安装依赖
sudo apt-get install g++ git make cmake libfreetype6-dev libode-dev libsdl2-dev ruby ruby-dev libdevil-dev libboost-dev libboost-thread-dev libboost-regex-dev libboost-system-dev qtbase5-dev qtchooser qt5-qmake libqt5opengl5-dev gpg curl
添加源
echo 'deb http://download.opensuse.org/repositories/science:/SimSpark/xUbuntu_20.04/ /' | sudo tee /etc/apt/sources.list.d/science:SimSpark.list
添加GPG秘钥到信任密钥库
curl -fsSL https://download.opensuse.org/repositories/science:SimSpark/xUbuntu_20.04/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/science_SimSpark.gpg > /dev/null
更新包列表
sudo apt-get update
安装rcssserver3d
sudo apt-get install rcssserver3d
- 安装FCP底层代码的深度强化学习优化环境
sudo apt install libgsl-dev python3-pip
# 安装FCP底层基础依赖库
pip3 install numpy pybind11 psutil
# 切换科大镜像源
pip config set global.index-url https://mirrors.ustc.edu.cn/pypi/simple
# 安装FCP底层强化学习依赖库
pip3 install stable-baselines3 gym shimmy
- 拉取FCPCodebase进行本地测试
git clone https://github.com/m-abr/FCPCodebase
cd FCPCodebase
python3 Run_Utils.py
# 等待程序自动编译C++库
选择序号0然后在下图界面中选择项一个一个修改将server配置设置为如下图状态(0不用管,修改了其他的项,0-Official Config
自然会变成off
)
然后按
ctrl+C
退回上一级,然后再按ctrl+C
退出脚本
再次执行python3 Run_Utils.py
,选择15-Basic_Run
,选择0-Train
,然后在RoboViz连接到飞牛nas的ip,端口就是刚才映射到4200的10087端口,等待一会,如果球场正常跑起来了,球员也出现了,说明环境配置成功
导出容器为tar
此处我用finalshell连接飞牛nas,如果你连不上就去飞牛设置看一下是不是ssh功能没开,ssh登录账户密码就是飞牛系统初始化时设置的超级管理员账号密码
然后sudo su
切换到root下操作
1. 先docker ps -a
查看刚才的容器id
2. 将当前的容器保存为一个镜像
此处ss3d_fcp_env是自己取的名字,后续保持相同即可随意取名(但也别太随意)
docker commit <刚才查看到的容器的id> ss3d_fcp_env:latest
- 将保存的镜像导出为tar
此处
ss3d_fcp_env.tar
是导出文件名称,ss3d_fcp_env:latest
是刚才保存为镜像的名称
# 先导出
docker save -o ss3d_fcp_env.tar ss3d_fcp_env:latest
# 修改权限确保finalshell可下载
chmod 777 ss3d_fcp_env.tar
点一下finalshell的刷新按钮,导出的tar文件出现在文件列表,右键下载即可将这个文件下载到桌面上的fsdownload文件夹中
tar文件导入AiStation集群使用
-
访问AiStation网页,点击左侧数据管理——文件管理,然后选择用户目录
-
点击上传——上传文件,选择桌面上fsdownload文件夹中刚才导出的
ss3d_fcp_env.tar
进行上传,可能需要很久 -
访问AiStation网页,点击左侧镜像管理,然后在页面右侧点击导入,选择内部导入,选择镜像文件就是刚才导入到用户目录的那个
ss3d_fcp_env.tar
,其他项按如下填写即可,然后点击确定,镜像会开始导入,可能需要很长时间 - 导入成功后会如下图所示
在开发环境中测试镜像是否正常工作
- 在业务管理——开发环境——创建中填写相关信息,点击确定即可创建开发环境
- 在开发环境列表中往右拖可以看到SSH连接信息,可以使用vscode远程连接开发,不过因为集群不能联网下载vscode服务端,可能第一次连接会耗时很久
- 使用vscode远程连接后打开FCPCodebase目录,此时可以测试是否可以正常进行训练
编写脚本实现全自动开始训练
- FCPCodebase默认的深度强化学习脚本需要人工操作好几步才能进行训练,我们在集群上训练任务需要使用命令去开始优化而不能手动启动,于是基于Run_Utils.py脚本修改了一下做了个自动开始训练的脚本(
train.py
),如果要使用需要修改其中的部分代码以适应自己的训练任务cls_name
的值应该与你放在scripts/gyms
下的优化类的文件名相同mod
导入的类注意与cls_name
的关联 如果idx
设为0,表示从头开始训练,不需要关心model_info
的内容,如果是1或者2,则需要配置model_info
def main():
from scripts.commons.Script import Script
script = Script() #Initialize: load config file, parse arguments, build cpp modules (warns the user about inconsistencies before choosing a test script)
# Allows using local version of StableBaselines3 (e.g. https://github.com/m-abr/Adaptive-Symmetry-Learning)
# place the 'stable-baselines3' folder in the parent directory of this project
import sys
from os.path import dirname, abspath, join
sys.path.insert( 0, join( dirname(dirname( abspath(__file__) )), "stable-baselines3") )
from scripts.commons.UI import UI
from os.path import isfile, join, realpath, dirname
from os import listdir, getcwd
from importlib import import_module
_cwd = realpath( join(getcwd(), dirname(__file__)))
gyms_path = _cwd + "/scripts/gyms/"
utils_path = _cwd + "/scripts/utils/"
exclusions = ["__init__.py"]
utils = sorted([f[:-3] for f in listdir(utils_path) if isfile(join(utils_path, f)) and f.endswith(".py") and f not in exclusions], key=lambda x: (x != "Server", x))
gyms = sorted([f[:-3] for f in listdir(gyms_path ) if isfile(join(gyms_path , f)) and f.endswith(".py") and f not in exclusions])
while True:
is_gym = True
cls_name = "Big_Kick"
mod = import_module("scripts.gyms.Big_Kick")
idx=2 #0-train 1-test 2-retrain
model_info={
'folder_dir': './scripts/gyms/logs/Big_Kick',
'folder_name': 'Big_Kick',
'model_file': './scripts/gyms/logs/Big_Kick/BIG_R1_16.08M.zip'
}
if not is_gym:
from world.commons.Draw import Draw
from agent.Base_Agent import Base_Agent
obj = getattr(mod,cls_name)(script)
try:
obj.execute() # Util may return normally or through KeyboardInterrupt
except KeyboardInterrupt:
print("\nctrl+c pressed, returning...\n")
Draw.clear_all() # clear all drawings
Base_Agent.terminate_all() # close all server sockets + monitor socket
script.players = [] # clear list of players created through batch commands
del obj
else:
from scripts.commons.Train_Base import Train_Base
print("\nBefore using GYMS, make sure all server parameters are set correctly")
print("(sync mode should be 'On', real time should be 'Off', cheats should be 'On', ...)")
print("To change these parameters go to the previous menu, and select Server\n")
print("Also, GYMS start their own servers, so don't run any server manually")
while True:
if idx == 0:
mod.Train(script).train(dict())
else:
if model_info is not None and idx == 1:
mod.Train(script).test(model_info)
elif model_info is not None:
mod.Train(script).train(model_info)
# allow child processes to bypass this file
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\nctrl+c pressed, exiting...")
exit()
- 将整个优化项目上传到用户目录,我是吧FCPCodebase项目文件夹整个上传到用户目录的
SS3D
目录下并把项目文件夹重命名为FCP_TRAIN
,所以我的train.py
的路径为/用户名/SS3D/FCP_TRAIN/train.py
- 光有一个py脚本肯定是不够的,因为在优化前需要做一些设置,于是编写了如下的shell脚本(train.sh),注意这个脚本的存放位置为
/用户名/SS3D/FCP_TRAIN/train.sh
,可通过网页上传到用户目录的该位置下
#!/bin/bash
export OMP_NUM_THREADS=1
cd /用户名/SS3D/FCP_TRAIN/ # 注意,这一步切换的目录跟你的账户用户名有关
python3 train.py
- 通过vscode或其他ssh工具远程登录刚才的开发环境,一般情况下网页端显示的那个用户目录是会自动挂在到开发环境中的,我这里直接是根目录下的以用户名命名的一个文件夹,cd进去ls一下看看文件列表是不是和网页端一样,如果一样的话执行
chmod -R 777 SS3D
赋予权限,否则训练任务会执行失败
提交训练任务
- 在AiStation网页的业务管理——任务管理页面右侧点击创建
- 按下图配置,选择我们导入的镜像,运行里面点击右侧文件选择按钮从用户目录中选择刚才创建的那个
train.sh
,CPU核心可以按需多选一点,这里因为我已经有一个任务再跑了只剩12核心可用,正在跑的优化使用了48核心,端口填写4200,其他不用管,点击确定提交任务。 - 在任务列表点击任务编号(蓝色的一串数字可以进入详情查看终端输出),容器实例选项卡页面可以看到4200端口被映射到了哪里,使用RoboViz进行连接查看即可。