這是一個容許你在幾乎任何街機遊戲中訓練你的強化學習算法的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開發者的集中營:加入