如何使用Unity创建场景并转为gym环境,外接自定义强化学习算法

       首先声明这种方式的最大问题:
       1、如果你的强化学习环境既包含连续动作,也包含离散动作,本文不敢确保是否可以正常使用,遇到过报错情况,目前我用的全部是连续,如果有人用了功能正常,欢迎评论区告知;
       2、如果你的强化学习问题是多智能体方向的研究,放弃本文,gym_unity暂不支持多智能体训练,要么找办法实现mlagents外接算法(目前没找到能用的办法),要么用unity的mlagents自带PPO、SAC等。
       开始这种方式之前,请先确认你已安装gym_unity:

pip3 install gym_unity

       或者进入到ml-agents本地文件夹,进入gym_unity文件夹下,执行本地安装:

pip3 install -e .

一、创建场景

       既然都已经搜索这个问题了,那就是对强化学习的基本概念、gym库以及unity提供的强化学习工具MLAgents有了一定的了解,并且是已经去过github上的mlagents官方了,在那里可以看到大量官方说明文档,关于如何在unity开启一个训练场景,可以查看官方链接,官方说的很清楚(github上不去的可能要科学上网)
       或者参照B站up主三次元魔法师的视频教程(在此感谢up,我的场景制作就是照着这个视频来的,也是因为看到有人用unity的mlagents还做视频,才继续用它来做强化学习的环境仿真)
       创建好之后的小球追立方体场景如下图:
Demo场景

二、使用Python与Unity Editor交互训练

       下面开始讲解Python代码如何使用这个建立好的场景,直接贴代码吧

from gym_unity.envs import UnityToGymWrapper
from mlagents_envs.environment import UnityEnvironment
max_step = 1000                 # 整个训练的最大总步数
max_step_per_episode = 200      # 每个episode最大探索步数


if __name__ == '__main__':
    total_step = 0
    env_path = None
    # env_path = "你的unity场景编译后的exe文件路径"
	unity_env = UnityEnvironment(env_path)
	
    """
    参数allow_multiple_obs=False代表不启用多种类型的观察值,因为我的状态空间没有包括视觉,
    所以设为False,如果你的用到了视觉,根据官方文档,必须设为True才可正常接收到unity的视觉
    状态信息
    """
    env = UnityToGymWrapper(unity_env, allow_multiple_obs=False)		

    state_dim = env.observation_space.shape[0]  # 获取状态空间的维度
    action_dim = env.action_space.shape[0]      # 获取动作空间的维度

    while total_step < max_step:        # 这里是按照最大总步数结束训练的,当然你也可以改成指定最大episode次数
        state = env.reset()
        current_ep_reward = 0

        for t in range(1, max_step_per_episode + 1):
            # action = agent.get_action(state)      # 对于外接算法,这里的action应该是你的强化学习算法给出
            action = [0.1, 0.05]        # 时间原因,只测试Python与unity Editor对接功能,这里就固定了action
            state_, reward, done, _ = env.step(action)
            if done:
                break

       这里面有个env_path的定义,如果为None(与直接执行方法unity_env = UnityEnvironment()没有区别),这时候代码执行后,在终端可以看到以下信息,代表此时程序开始监听unity端口(了解通信的可能就猜到了,端口被占用了,就不可能启动第二个,所以训练就只能开一个)
开始监听unity端口
       这个时候去Unity Editor,回到前文中建立好的小球追立方体场景,首先在开始之前一定要确认下面几个关键点,否则可能导致Unity报错或者警告信息,甚至无法正常启动小球:
       1.直接点击播放按钮,测试小球是否可以手动控制移动;
       2.查看Unity Editor的Inspector面板,检查其中Behavior Parameters的动作空间、观察空间是否与你智能体挂载的C#脚本定义一致;
       (Space Size 表示观察空间维度,下面的Continuous Action代表连续型动作维度,Discrete Branch表示离散动作维度。注意:如果连续动作和离散动作同时存在,我在执行后面Python程序时报错)
       附:C#脚本中如何查看状态空间和动作空间维度:
              1)去CollectObservations查看状态空间维度,因此这个小球的观察空间定义为8维
在这里插入图片描述
              2)去Heuristic查看动作空间维度,因此这里定义的是2维。
在这里插入图片描述

       3.Max Step确认一下,别写成0,否则会导致无法移动。

在这里插入图片描述

       检查过后,点击Unity Editor上面的播放按钮即可看到Python代码控制了小球的运动(没法上传录制的视频,到这应该能看到小球运动了),因为我们在Python代码中的action只是为了测试而设置定值,可以看到小球朝着固定方向移动,到这里说明你已经成功了,只不过这时候的Python代码必须与Unity Editor同时开启运行,显然Editor的动画演示效果占用了大量内存、CPU和GPU性能,所以Unity还提供了无可视化界面的Python-Unity交互训练方式,见下文。

三、Windows下编译场景为exe文件,用Python交互训练

       这里还是想再次强调一遍,将自定义的强化学习场景编译为exe文件之前,首先确认一下上面的Inspector面板参数,状态空间、动作空间维度是否与场景中智能体挂载的C#脚本定义一致。
       确认无误后,开始编译exe过程:
       1.在Unity Editor,点击File->Build Settings…,选中要编译的场景,勾选Server Build,然后点开左下角的Player Settings…
在这里插入图片描述
       2.在打开的Player Settings…窗口内,一定要选中Run In BackGround* !!!
在这里插入图片描述
       3.修改和确认以上设置之后,点击Build开始编译,此时弹出选择文件夹,这里新建了Demo文件夹
在这里插入图片描述
       4.选择,然后开始编译,慢慢等,根据电脑配置和你的场景大小复杂程度,等待时间会不同:
在这里插入图片描述
       5.编译完成,自动打开所在路径,也就是刚刚选择的Demo文件夹所在位置:
在这里插入图片描述
       这里带有Unity图标的exe文件,就是我们的场景对应的exe了,但是当你双击运行的时候,会发现只是个命令行,没有显示你的场景画面,这就对了,因为编译之前设置的那一通,是让他以server方式后台运行,无可视化界面(走这一步不就是为了不要可视化节省电脑资源嘛),然后复制这个exe文件的路径,比如这里是F:\Projects\UnityProjects\ExecutableExamples\Demo\Off-Road.exe,提醒一下不要看到是exe就复制,我就搞错了一次,复制成了下面那个UnityCrashHandler64.exe,半天愣是没跑起来,还不知道哪的错=.=|||
然后把这个路径粘贴进Python代码,也就是之前的env_path路径:

env_path = None

       现在变成了(注意这里的路径换成了双斜线):

env_path = "F:\\Projects\\UnityProjects\\ExecutableExamples\\Demo\\Off-Road.exe"

       如果没有可视化界面,我们不知道智能体(小球)是否正常工作,所以在原来的Python代码里面加个观察空间(observation)的输出,同时也是为了检查环境返回的观察信息是否符合期望,新的完整代码就成了:

from gym_unity.envs import UnityToGymWrapper
from mlagents_envs.environment import UnityEnvironment
max_step = 1000                 # 整个训练的最大总步数
max_step_per_episode = 200      # 每个episode最大探索步数


if __name__ == '__main__':
    total_step = 0
    env_path = "F:\\Projects\\UnityProjects\\ExecutableExamples\\Demo\\Off-Road.exe"		# 改成你自己的exe文件路径

	"""
	勾选Run In Background*的exe无法显示图形界面
	不勾选Run In Background*的exe可以用no_graphics参数决定是否显示
	"""
    unity_env = UnityEnvironment(env_path,
					    		base_port=5000,	# 端口自定义
					            seed=0,			# 随机种子
					            no_graphics=True,	# 显示图形界面,True不显示,False显示
					            timeout_wait=60,)	# 超时时间设置
    env = UnityToGymWrapper(unity_env, allow_multiple_obs=False)

    state_dim = env.observation_space.shape[0]  # 获取状态空间的维度
    action_dim = env.action_space.shape[0]      # 获取动作空间的维度

    while total_step < max_step:        # 这里是按照最大总步数结束训练的,当然你也可以改成指定最大episode次数
        state = env.reset()
        current_ep_reward = 0

        for t in range(1, max_step_per_episode + 1):
            # action = agent.get_action(state)      # 对于外接算法,这里的action应该是你的强化学习算法给出
            action = [0.1, 0.05]        # 时间原因,只测试Python与unity Editor对接功能,这里就固定了action
            state_, reward, done, _ = env.step(action)
            print(state_)
            if done:
                break

       然后运行程序,可以看到随着执行,不断输出小球每一次执行action之后获取的观察值信息(按照定义的收到的就是8维),同时你还可以看到一行WARNING信息,他告诉了你那个allow_multiple_obs参数的作用:
在这里插入图片描述
       到这里说明你的exe正常,Python可以使用该环境的exe文件训练了,因为转成了gym的形式,所以只要你会用gym写自己的算法,无论是PPO、DDPG、SAC等等,理论上来说都不是问题了。但实际上,gym_unity目前还不完善,有一些限制(已知的明确的一点就是,这种方式下,unity编写的环境无法支持多智能体,无论是单一场景包含多人对抗的,还是你在Unity Editor复制了多个场景想用来加速训练,都不行了),但是相信这个AI盛行的时代,Unity也懂得顺应潮流,也许不久的将来也会提供更全面的gym环境支持。
 
 
 
       PS:其实github上MLAgents官方都有,可我自己现在回去找都没找到原文,,他文档实在是太多了啊我的天,写的仓促,有错请指正。

  • 16
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值