使用pysc2的環(huán)境并與其進(jìn)行交互
關(guān)于pysc2使用的全部?jī)?nèi)容請(qǐng)參考:【文集:pysc2的簡(jiǎn)單教程】
作為應(yīng)用于強(qiáng)化學(xué)習(xí)的SCII環(huán)境是被定義在 pysc2.env.sc2_env
中的糙箍,(action 和 observation 空間是定義在 pysc2.lib.features
中的),環(huán)境的類(lèi)即 SC2Env
牵祟,繼承自 pysc2.env.environment.Base
類(lèi)深夯。可以作為使用一般的gym庫(kù)的強(qiáng)化學(xué)習(xí)的環(huán)境一樣使用它。
要實(shí)例化并使用一個(gè) SC2Env
诺苹,需要傳入幾個(gè)重要的參數(shù)咕晋,完整的參數(shù)列表如下:
_only_use_kwargs=None,
map_name=None,
battle_net_map=False,
players=None,
agent_interface_format=None,
discount=1.,
discount_zero_after_timeout=False,
visualize=False,
step_mul=None,
realtime=False,
save_replay_episodes=0,
replay_dir=None,
replay_prefix=None,
game_steps_per_episode=None,
score_index=None,
score_multiplier=None,
random_seed=None,
disable_fog=False,
ensure_available_actions=True,
version=None
重要的參數(shù)說(shuō)明
一些重要的參數(shù)說(shuō)明如下:
-
map_name
:地圖的名稱,一個(gè)字符串- 地圖名均列在了
pysc2.bin.map_list
中收奔,可以使用如下的命令來(lái)列出所有的地圖名稱:python -m pysc2.bin.map_list
- 或者可以在 pysc2/maps/ 下的文件夾中查找掌呜,比如 pysc2/maps/melee.py 中定義了所有 Melee 的地圖名稱:
melee_maps = ["Flat32", "Flat48", "Flat64", "Flat96", "Flat128", "Simple64", "Simple96", "Simple128",]
- 地圖名均列在了
-
players
:傳入一個(gè)list,list中是一個(gè)或兩個(gè)pysc2.env.sc2_env.Agent
或pysc2.env.sc2_env.Bot
的實(shí)例坪哄,目前只支持一個(gè)或者兩個(gè)站辉,一個(gè)就是單 Agent 與環(huán)境交互呢撞,兩個(gè)就是互相對(duì)戰(zhàn),有些地圖只能傳入一個(gè)饰剥。注意,就是使用一個(gè)Agent
或Bot
的實(shí)例時(shí)摧阅,也要使用 list 包裹汰蓉。- 注意,此處的
pysc2.env.sc2_env.Agent
和pysc2.env.sc2_env.Bot
是不同于我們前文中所提到的自定義的繼承自pysc2.agetns.base_agent
的棒卷,這是兩個(gè)不同的類(lèi)顾孽,這里使用的 Agent 和 Bot 用于定義與環(huán)境交互的player的類(lèi)型、名稱比规、種族若厚、困難度等信息,這兩個(gè)類(lèi)的定義很簡(jiǎn)單:class Agent(collections.namedtuple("Agent", ["race", "name"])): """Define an Agent. It can have a single race or a list of races.""" def __new__(cls, race, name=None): return super(Agent, cls).__new__(cls, to_list(race), name or "<unknown>") class Bot(collections.namedtuple("Bot", ["race", "difficulty", "build"])): """Define a Bot. It can have a single or list of races or builds.""" def __new__(cls, race, difficulty, build=None): return super(Bot, cls).__new__(cls, to_list(race), difficulty, to_list(build or BotBuild.random))
- 注意,此處的
-
agent_interface_format
:用于規(guī)定 observation 和 action 的形式蜒什,比如地圖或者feature layers的分辨率等测秸,接受pysc2.lib.features.AgentInterfaceFormat
實(shí)例,或者pysc2.env.sc2_env.AgentInterfaceFormat
實(shí)例灾常。(實(shí)際上兩者相同霎冯,sc2_env.py
中使用了 = 將其兩者賦值)- 如果你在players參數(shù)中傳入了兩個(gè)對(duì)象,那么可以傳入一個(gè)
AgentInterfaceFormat
的實(shí)例同時(shí)應(yīng)用于兩個(gè)player钞瀑,或者傳入一個(gè)包含兩個(gè)AgentInterfaceFormat
的list沈撞,和players的順序一致地分別應(yīng)用于兩個(gè)player - AgentInterfaceFormat 的參數(shù)等設(shè)置方法直接參考其定義
- 如果你在players參數(shù)中傳入了兩個(gè)對(duì)象,那么可以傳入一個(gè)
-
step_mul
參數(shù)接收一個(gè)整數(shù),可以理解為:每次采集observation和應(yīng)用action之間跳過(guò)多少個(gè)幀(但是不是實(shí)際上的幀數(shù))雕什。1 秒相當(dāng)于 16 steps缠俺,如果這里設(shè)置為16
,就代表每秒采集一次贷岸。 -
game_steps_per_episode
:一代多少個(gè) steps壹士,比如這里設(shè)置為200*16
,就表示一代經(jīng)歷 200 秒結(jié)束 -
save_replay_episodes
:多少代保存一次replay -
replay_dir
:replay保存在哪個(gè)位置
使用自己實(shí)例化的環(huán)境
定義了自己的env以及agent凰盔,就可以像使用其他gym環(huán)境一樣進(jìn)行交互了墓卦,一個(gè)很好的官方提供的例子就是這個(gè) pysc2/env/run_loop.py 文件下的 run_loop
函數(shù),它接收一個(gè)/兩個(gè) agent(s) 實(shí)例和一個(gè) env 實(shí)例户敬,運(yùn)行若干幀/代:
def run_loop(agents, env, max_frames=0, max_episodes=0):
"""A run loop to have agents and an environment interact."""
total_frames = 0
total_episodes = 0
start_time = time.time()
observation_spec = env.observation_spec()
action_spec = env.action_spec()
for agent, obs_spec, act_spec in zip(agents, observation_spec, action_spec):
agent.setup(obs_spec, act_spec)
try:
while not max_episodes or total_episodes < max_episodes:
total_episodes += 1
timesteps = env.reset()
for a in agents:
a.reset()
while True:
total_frames += 1
actions = [agent.step(timestep) for agent, timestep in zip(agents, timesteps)]
if max_frames and total_frames >= max_frames:
return
if timesteps[0].last():
break
timesteps = env.step(actions)
except KeyboardInterrupt:
pass
finally:
elapsed_time = time.time() - start_time
print("Took %.3f seconds for %s steps: %.3f fps" % (elapsed_time, total_frames, total_frames / elapsed_time))
最后再來(lái)看一下官方提供的落剪,實(shí)例化一個(gè) SC2Env
實(shí)例,一個(gè) Agent
實(shí)例尿庐,然后使用上述的 run_loop
函數(shù)進(jìn)行測(cè)試的例子忠怖,若干個(gè)例子可以在 pysc2/tests/easy_scripted_test.py 中找到:
def test_move_to_beacon(self):
with sc2_env.SC2Env(
map_name="MoveToBeacon",
players=[sc2_env.Agent(sc2_env.Race.terran)],
agent_interface_format=sc2_env.AgentInterfaceFormat(
feature_dimensions=sc2_env.Dimensions(
screen=84,
minimap=64)),
step_mul=self.step_mul,
game_steps_per_episode=self.steps * self.step_mul) as env:
agent = scripted_agent.MoveToBeacon()
run_loop.run_loop([agent], env, self.steps)
這里使用了 with as
的形式,我們需要?jiǎng)?chuàng)建長(zhǎng)久的交互式直接使用 evn = SC2Env(…)
即可抄瑟。
啟動(dòng)SCII程序
啟動(dòng)真正的SCII程序需要使用 absl.app
下的 run
函數(shù)凡泣,然后傳入一個(gè)運(yùn)行我們上述代碼的主要函數(shù)作為參數(shù),比如我們?cè)O(shè)置了一個(gè)主函數(shù)來(lái)設(shè)置env、agent等鞋拟,以及完成了基本的循環(huán)條件骂维,把這些都封裝在了一個(gè)名為 main
的函數(shù)中,最后贺纲,需要使用 absl.app.run(main)
來(lái)啟動(dòng)真正的 SCII 程序航闺。一個(gè)完整的例子如下:
from pysc2.env import run_loop, sc2_env
from pysc2.agents import random_agent
from absl import app
def main(args):
agent = random_agent.RandomAgent()
with sc2_env.SC2Env(map_name="MoveToBeacon", players=[sc2_env.Agent(sc2_env.Race.terran)],
agent_interface_format=sc2_env.AgentInterfaceFormat(
feature_dimensions=sc2_env.Dimensions(screen=84, minimap=64)), step_mul=16,
game_steps_per_episode=200 * 16, visualize=True) as env:
run_loop.run_loop([agent], env, 200)
if __name__ == "__main__":
app.run(main)
幾個(gè)非常需要注意的點(diǎn):
-
app.run
內(nèi)傳入的參數(shù),第一個(gè)參數(shù)是必須傳入的猴誊,是主函數(shù)的名字潦刃,不帶括號(hào)和參數(shù),第二個(gè)參數(shù)可選懈叹,當(dāng)主函數(shù)需要參數(shù)的時(shí)候乖杠,在第二個(gè)參數(shù)這里提供,需要將所用到的參數(shù)打包成list作為參數(shù)傳入 - 定義
main
函數(shù)時(shí)澄成,必須為其設(shè)置至少一個(gè)參數(shù)胧洒,比如這里的args
,這個(gè)參數(shù)可以不在函數(shù)中使用环揽,但是如果只定義def main()
就會(huì)報(bào)錯(cuò) - 這里我們使用了官方提供的
run_loop
函數(shù)略荡,傳入時(shí),第一個(gè)參數(shù)為我們的 agent 們歉胶,即使只有一個(gè)汛兜,也要打包成list傳入
重要參考官方文檔:https://github.com/deepmind/pysc2/blob/master/docs/environment.md#rl-environment
參考一篇blog:https://itnext.io/build-a-zerg-bot-with-pysc2-2-0-295375d2f58e