这是一个容许你在几乎任何街机游戏中训练你的强化学习算法的Python库,它目前在Linux系统上可用。经过这个工具包,你能够定制算法逐步完成游戏过程,同时接收每一帧的数据和内部存储器地址值以跟踪游戏状态,以及发送与游戏交互的动做。python
安装git
GitHub地址:github.com/M-J-Murray/MAMEToolkit/blob/master/README.mdgithub
你能够用pip安装这个库,只需运行如下命令:算法
pip install MAMEToolkitdom
演示:街霸ide
街霸是史上最经典的游戏之一。如今工具包内包含的街霸版本是街头霸王3:三度冲击(Japan 990608, NO CD),咱们以此为例,用如下代码写一个随机智能体:函数
import random from MAMEToolkit.sf_environment import Environment roms_path = "roms/" env = Environment("env1", roms_path) env.start() while True: move_action = random.randint(0, 8) attack_action = random.randint(0, 9) frames, reward, round_done, stage_done, game_done = env.step(move_action, attack_action) if game_done: env.new_game() elif stage_done: env.next_stage() elif round_done: env.next_round()
支持hogwild!工具
hogwild!? Niu等人引入了一个叫作 Hogwild! 的更新策略,可使 SGD 能够在多 CPU 上并行更新。处理器在无需对参数加锁的状况下就能够访问共享内存。但仅在输入的是稀疏数据时才有效,由于每次更新仅修改全部参数的一小部分。他们展现了在这种状况下,更新策略几乎能够达到一个最优的收敛率,由于处理器不太可能覆盖掉有用的信息。
from threading import Thread import random from MAMEToolkit.sf_environment import Environment def run_env(env): env.start() while True: move_action = random.randint(0, 8) attack_action = random.randint(0, 9) frames, reward, round_done, stage_done, game_done = env.step(move_action, attack_action) if game_done: env.new_game() elif stage_done: env.next_stage() elif round_done: env.next_round() def main(): workers = 8 # Environments must be created outside of the threads roms_path = "roms/" envs = [Environment(f"env{i}", roms_path) for i in range(workers)] threads = [Thread(target=run_env, args=(envs[i], )) for i in range(workers)] [thread.start() for thread in threads]
创建本身的游戏环境性能
这个工具包之因此易于上手,是由于它和模拟器自己不须要太多交互,只需注意两点——一是查找你关注的内部状态相关联的内存地址值,二是用选取的环境跟踪状态。你能够用MAME Cheat Debugger,它会反馈游戏的内存地址值如何随时间变化。若是要建立游戏模拟,你得先得到正在模拟的游戏的ROM,并知道MAME使用的游戏ID,好比街霸的ID是'sfiii3n'。学习
游戏ID
你能够经过运行如下代码找到游戏的ID
from MAMEToolkit.emulator import Emulator emulator = Emulator("env1", "", "", memory_addresses)
这个命令会打开MAME仿真器。你能够搜索游戏列表以找到想要的游戏,游戏的ID位于游戏标题末尾的括号中。
内存地址
若是得到了ID,也有了想要跟踪的内存地址,你能够开始模拟:
from MAMEToolkit.emulator import Emulator from MAMEToolkit.emulator import Address roms_path = "roms/" game_id = "sfiii3n" memory_addresses = { "fighting": Address('0x0200EE44', 'u8'), "winsP1": Address('0x02011383', 'u8'), "winsP2": Address('0x02011385', 'u8'), "healthP1": Address('0x02068D0B', 's8'), "healthP2": Address('0x020691A3', 's8') } emulator = Emulator("env1", roms_path, "sfiii3n", memory_addresses)
这会启动仿真器,并在工具包链接到模拟器进程时暂停。
分步运行仿真器
链接工具箱后,你能够分步运行仿真器:
data = emulator.step([]) frame = data["frame"] is_fighting = data["fighting"] player1_wins = data["winsP1"] player2_wins = data["winsP2"] player1_health = data["healthP1"] player2_health = data["healthP2"]
step函数会把帧数据做为NumPy矩阵返回,同时,它也会返回该时间步长的全部内存地址整数值。
若是要向仿真器输入动做,你还须要肯定游戏支持的输入端口和字段。好比玩街霸须要先投币,这个代码是:
from MAMEToolkit.emulator import Action insert_coin = Action(':INPUTS', 'Coin 1') data = emulator.step([insert_coin])
要肯定哪些端口可用,请使用list actions命令:
from MAMEToolkit.emulator import list_actions roms_path = "roms/" game_id = "sfiii3n" print(list_actions(roms_path, game_id))
下面这个返回的列表就包含街霸环境中可用于向步骤函数发送动做的全部端口和字段:
[ {'port': ':scsi:1:cdrom:SCSI_ID', 'field': 'SCSI ID'}, {'port': ':INPUTS', 'field': 'P2 Jab Punch'}, {'port': ':INPUTS', 'field': 'P1 Left'}, {'port': ':INPUTS', 'field': 'P2 Fierce Punch'}, {'port': ':INPUTS', 'field': 'P1 Down'}, {'port': ':INPUTS', 'field': 'P2 Down'}, {'port': ':INPUTS', 'field': 'P2 Roundhouse Kick'}, {'port': ':INPUTS', 'field': 'P2 Strong Punch'}, {'port': ':INPUTS', 'field': 'P1 Strong Punch'}, {'port': ':INPUTS', 'field': '2 Players Start'}, {'port': ':INPUTS', 'field': 'Coin 1'}, {'port': ':INPUTS', 'field': '1 Player Start'}, {'port': ':INPUTS', 'field': 'P2 Right'}, {'port': ':INPUTS', 'field': 'Service 1'}, {'port': ':INPUTS', 'field': 'Coin 2'}, {'port': ':INPUTS', 'field': 'P1 Jab Punch'}, {'port': ':INPUTS', 'field': 'P2 Up'}, {'port': ':INPUTS', 'field': 'P1 Up'}, {'port': ':INPUTS', 'field': 'P1 Right'}, {'port': ':INPUTS', 'field': 'Service Mode'}, {'port': ':INPUTS', 'field': 'P1 Fierce Punch'}, {'port': ':INPUTS', 'field': 'P2 Left'}, {'port': ':EXTRA', 'field': 'P2 Short Kick'}, {'port': ':EXTRA', 'field': 'P2 Forward Kick'}, {'port': ':EXTRA', 'field': 'P1 Forward Kick'}, {'port': ':EXTRA', 'field': 'P1 Roundhouse Kick'}, {'port': ':EXTRA', 'field': 'P1 Short Kick'} ]
仿真器类还有一个frame_ratio参数,可用于调整算法所见的帧速率。默认状况下,MAME以每秒60帧的速度生成帧,若是你以为这太多了,想把它改为每秒20帧,能够输入如下代码:
from MAMEToolkit.emulator import Emulator emulator = Emulator(roms_path, game_id, memory_addresses, frame_ratio=3)
MAME性能基准测试
目前这个工具包的开发和测试已在8核AMD FX-8300 3.3GHz CPU以及3GB GeForce GTX 1060 GPU上完成。在使用单个随机智能体的状况下,街头霸王环境能够以正常游戏速度的600%+运行。而若是是用8个随机智能体进行hogwild!训练,环境能够以正常游戏速度的300%+运行。
ConvNet智能体
为了确保工具包可以训练算法,做者还设置了一个简单的5层ConvNet,只需少许调整,你就能够用它进行测试。在街霸实验中,这个算法可以成功学习到游戏的一些简单技巧,好比连击(combo)和格挡(blocking)。街霸自己的游戏机制是分红10个关卡(难度递增),玩家在每一个关卡都要迎战不一样的对手。刚开始的时候,这个智能体平均只能打到第2关。但在通过2200次训练后,它平均能打到第5关。
至于智能体的学习率,它是用每一局智能体所形成的净伤害和所承受的伤害来计算的。
Python学习交流q-u-n-【 784758214 】内有安装包和学习视频资料,零基础,进阶,,大牛在线解答疑问。但愿能够帮助你快速了解Python、学习python
python开发者的集中营:加入