ML-Agents与python的Low Level API通信
本文基于我前面的文章Unity强化学习之ML-Agents的使用
参考Github链接:https://github.com/Unity-Technologies/ml-agents
参考文档:https://unity-technologies.github.io/ml-agents/
在之前利用Unity3D中的ML-Agents插件训练出来的游戏AI中,我们只需要自己创建对应的环境,设定深度强化学习所必要的几个因素:
- 神经网络所接收的状态state
- 神经网络输出的动作action
- action控制智能体的运动
- 回合结束条件与重置后的状态
- 每一个step在不同条件下智能体得到的奖励reward
- 训练算法及其参数(设定对应的yaml文件)
设定好后,在控制台输入对应的命令就能够用官方对应的算法训练自己的智能体。
这种算法本质上也是调用了Unity官方编写的python代码,采用官方的PPO或者SAC算法来训练自己单智能体,采用MA-POCA算法来训练自己的多智能体,对于不懂强化学习算法来说十分友好,无需关注算法本身,只需要关注如何搭建环境即可,配置对应的算法参数即可训练出不错的游戏AI。
然而,这种良好的封装带来的问题就是,我们如果想要对算法进行微调就变得有些困难了,封装得越完美,就越难以从底层入手进行改进,如果要进行强化学习的科研,我们的代码越轻量化,自己能掌握的部分越多,越利于我们进行改进,因此有必要搭建自己的python框架对Unity的环境进行训练。
python与Unity通信方法
这里采用的是ML-Agents官方的Low Level API进行通信,Unity 和 Python 之间的通信是通过open socket进行的,无需身份验证。因此,请确保进行训练的网络是安全的。
对于强化学习训练来说,与环境的通信我们至少需要知道几点:
- 如何创建一个环境
- 如何实时获取环境中每个智能体实时的状态,这一个step是否结束episode
- 如何给智能体输入动作action使其推进一个step
- 推进step后,如何获取状态以及对应的奖励reward
对环境数据的获取可以参考OpenAI的Gym环境,Gym在对环境进行Reset之后就可以返回智能体的state,对环境step函数输入action就能返回下一个step的状态state,奖励reward以及否结束episode,因此对于Unity也需要获取这些环境信息。
方便的一点是,在我们编写的Unity环境中,我们已经设定好了环境reset的条件,所以我们不用在python端给它reset。
创建一个环境
首先建议最好能把环境打包成可执行文件,把python代码和可执行文件放到同一个目录下。
我们可以用以下代码来运行一个Unity环境:
channel = EngineConfigurationChannel()
env = UnityEnvironment(file_name="UnityEnvironment", seed=1, side_channels=[channel])
channel.set_configuration_parameters(time_scale = 3.0)
其中file_name参数就是可执行文件的文件名,如果设为None,则直接在Unity编辑器中训练,time_scale可以控制环境运行的速度。
查看环境基本数据
下面的代码可以查看环境智能体的behavior_name,对应的队伍,状态空间和动作空间
behavior_names = list(env.behavior_specs.keys())
behavior_value = list(env.behavior_specs.values())
for i in range(len(behavior_names)):print(behavior_names[i])print("obs:",behavior_value[i].observation_specs, " act:", behavior_value[0].action_spec)
查看智能体数据
对于只有一个behavior_name的环境来说,我们可以通过这样的代码获取同一个behavior_name下的智能体状态,奖励等信息。
DecisionSteps, TerminalSteps = env.get_steps(behavior_names[0])
agentsNum = len(DecisionSteps.agent_id)
print("exist:",DecisionSteps.agent_id," Dead:",TerminalSteps.agent_id)
print("reward:",DecisionSteps.reward,"reward_dead:",TerminalSteps.reward)
print("obs:",DecisionSteps.obs,"DeadObs:",TerminalSteps.obs)
print("interrupted:", TerminalSteps.interrupted)
这是一个重要的部分,get_steps函数贯穿了整个强化学习的始终,它返回了两个值,第一个值DecisionSteps里面包含了正在执行动作的智能体信息,TerminalSteps包含的是正处于回合结束的智能体信息,很多时候,DecisionSteps或TerminalSteps里面不一定有值,在DecisionSteps有值的智能体,我们才需要对其执行动作
执行动作
用以下代码即可操作智能体
continuous_actions = (np.random.rand(agentsNum, 2) - 0.5) * 2
discrete_actions = None
actions = ActionTuple(continuous_actions, discrete_actions)
env.set_actions(behavior_names[0],actions)
对于智能体的操作可以分为离散动作和连续动作,我们需要分布对其进行赋值,对于DecisionSteps没有数据的智能体,我们不需要对其进行赋值。
完整示例代码
该代码基于ML-Agents官方环境3DBall,将3DBall打包之后,将该python代码放在同一个目录下,启动对应的ml-agents python环境,运行该代码,即可看到一个运行随机动作的环境
from mlagents_envs.environment import UnityEnvironment
import numpy as np
from mlagents_envs.environment import ActionTuple
import time
from mlagents_envs.side_channel.engine_configuration_channel import EngineConfigurationChannel# if file_name=None , use editor to train
channel = EngineConfigurationChannel()
env = UnityEnvironment(file_name="UnityEnvironment", seed=1, side_channels=[channel])
# 环境运行速度调整为3倍
channel.set_configuration_parameters(time_scale = 3.0)env.reset()
behavior_names = list(env.behavior_specs.keys())
behavior_value = list(env.behavior_specs.values())
# 这里可以得到observation和action的shape
for i in range(len(behavior_names)):print(behavior_names[i])print("obs:",behavior_value[i].observation_specs, " act:", behavior_value[0].action_spec)
# 这里可以得到智能体组的数据,包括状态,奖励,ID等,DecisionSteps包含回合未结束的智能体信息
# TerminalSteps包含回合已结束的智能体信息,包括结束原因等
# 智能体回合结束后进入TerminalSteps,并且下一回合进行重置并进入DecisionSteps,也有可能此回合同时进入DecisionSteps
DecisionSteps, TerminalSteps = env.get_steps(behavior_names[0])
print("agentIds:",DecisionSteps.agent_id)
print("rewards:",DecisionSteps.reward)
print("obs:",DecisionSteps.obs)
values = list(DecisionSteps.values())
for i in range(len(values)):print(values[i])
print("ter_reward:",TerminalSteps.reward)
print("interrupted:", TerminalSteps.interrupted) # 是否由于步数到了而停止
# 重置环境的条件以及外部奖励函数都在环境中的C#脚本中编写,这里只负责收集数据进行训练,实现训练和数据收集的分离处理
discrete_actions = None
this_time = time.time()
for i in range(1000000):print("step:",i," last_step_cost:",time.time() - this_time)this_time = time.time()DecisionSteps, TerminalSteps = env.get_steps(behavior_names[0])agentsNum = len(DecisionSteps.agent_id)print("exist:",DecisionSteps.agent_id," Dead:",TerminalSteps.agent_id)#print("reward:",DecisionSteps.reward,"reward_dead:",TerminalSteps.reward)#print("obs:",DecisionSteps.obs,"DeadObs:",TerminalSteps.obs)continuous_actions = (np.random.rand(agentsNum, 2) - 0.5) * 2actions = ActionTuple(continuous_actions, discrete_actions)#print("actions:", actions.continuous)env.set_actions(behavior_names[0],actions)env.step()env.close()
展望
后面在此基础之上将强化学习算法PPO对现有环境进行训练,敬请期待!
ML-Agents与python的Low Level API通信相关推荐
- Kafka High Level API vs. Low Level API
目录: 1.ConsumerApi 2.High Level Consumer (屏蔽细节管理) 3.Low Level API (细节需要自己处理) 1.Kafka提供了两种Consumer API ...
- 如何使用 Elastic Search Low Level API 构造请求进行搜索
场景: 需要在客户端构造请求调解, 调用 Elastic Search 的 API 取到结果,并且能够使用 ES 的授权机制. 方案: 一.在客户端构造 Low Level API . 二.Low L ...
- PostgreSQL备份之手工备份(Low Level API)
为什么80%的码农都做不了架构师?>>> 一.备份 1. 需要保证archive_mode = on 和 archive_command是有效的 2. 在master节点上连接 ...
- Elasticsearch java api操作(一)(Java Low Level Rest Client)
一.说明: 一.Elasticsearch提供了两个JAVA REST Client版本: 1.java low level rest client: 低级别的rest客户端,通过http与集群交互, ...
- Consumer设计-high/low Level Consumer
1 Producer和Consumer的数据推送拉取方式 Producer Producer通过主动Push的方式将消息发布到Broker n Consumer Consumer通过Pull从Br ...
- Kafka:High level consumer vs. Low level consumer
Kafka中的消费者有两套API,分别是high level的和low level的.两种消费方式在构造和实现上都是不同的,在此记录一下: 一.High level consumer API High ...
- [Python]调用百度地图API对地点进行搜索,利用 JSON 返回纬度/行政区域编号
1.创建百度API应用 类似爬虫程序,在百度地图API进行注册 在此处点击控制台,在应用管理------我的应用处 创建自己的应用. 创建应用如图所示,在请求校验方式处选择sn校验方式 记住自己的AK ...
- python实现简单的api接口-对Python实现简单的API接口实例讲解
get方法 代码实现 # coding:utf-8 import json from urlparse import parse_qs from wsgiref.simple_server impor ...
- python实现简单的api接口-简单实现Python调用有道API接口(最新的)
# ''' # Created on 2018-5-26 # # @author: yaoshuangqi # ''' import urllib.request import urllib.pars ...
最新文章
- 成功解决ValueError: `bins` must be positive, when an integer
- BUUCTF-Reverse:SimpleRev(算法分析题)
- ThreadLocal 详解
- MYSQL Incorrect string value: '\xE5\x8C\x97\xE4\xBA\xAC' for column
- C++中什么时候用new[]申请,可以用delete释放
- 一致性协议raft详解(三):raft中的消息类型
- met40如何升级成鸿蒙系统,再见了,EMUI11!你好,华为鸿蒙!
- 工作175:数据在表格横坐标动态显示
- c语言error和,C语言ERROR精选.doc
- 2015新东方计算机,2015年同等学力计算机综合模拟(2)
- BlockChain: 区块链入门课程 -- 区块链适用于移动性 分享和收费案例
- laravel5.4 刷新过快,出现The only supported ciphers are AES-128-CBC and AES-256-CBC
- 菜鸟学SQLServer--恢复模式
- Python学习教程(Python学习路线):Python3你还未get到的隐藏技能
- 如何进行在线Post接口测试?
- 电脑桌面计算机英语,IT计算机英语词汇
- wps怎么删除空白页?你学会了吗?
- 建立量化交易趋势跟踪策略的五个指标
- rhel6.5 oracle12c,中标麒麟Linux6.5安装Oracle12C配置过程
- NameSilo使用API进行动态域名解析DDNS