編者按:近年來,雖然關于強化學習進展的新聞屢見報端,對強化學習感興趣的人也很多,但對普通學習者來說,真正做一個自己感興趣的強化學習項目還是太麻煩了。今天論智給大家推薦的是一名網友開源的Python庫,它提供了一個可以玩任何舊版街機游戲的API,操作方式非常親民。
這是一個允許你在幾乎任何街機游戲中訓練你的強化學習算法的Python庫,它目前在Linux系統上可用。通過這個工具包,你可以定制算法逐步完成游戲過程,同時接收每一幀的數據和內部存儲器地址值以跟蹤游戲狀態,以及發送與游戲交互的動作。
安裝
GitHub地址:github.com/M-J-Murray/MAMEToolkit/blob/master/README.md
你可以用pip安裝這個庫,只需運行以下命令:
pip install MAMEToolkit
演示示例:街霸
在街機愛好者心中,街霸是史上最經典的游戲之一。現在工具包內包含的街霸版本是街頭霸王3:三度沖擊(Japan 990608, NO CD),我們以此為例,用以下代碼寫一個隨機智能體:
import random
fromMAMEToolkit.sf_environment importEnvironment
roms_path = "roms/"
env = Environment("env1", roms_path)
env.start()
whileTrue:
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 上并行更新。處理器在無需對參數加鎖的情況下就可以訪問共享內存。但僅在輸入的是稀疏數據時才有效,因為每次更新僅修改所有參數的一小部分。他們展示了在這種情況下,更新策略幾乎可以達到一個最優的收斂率,因為處理器不太可能覆蓋掉有用的信息。
import random
fromMAMEToolkit.sf_environment importEnvironment
def run_env(env):
env.start()
whileTrue:
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:
fromMAMEToolkit.emulator importEmulator
emulator = Emulator("env1", "", "", memory_addresses)
這個命令會打開MAME仿真器。你可以搜索游戲列表以找到想要的游戲,游戲的ID位于游戲標題末尾的括號中。
內存地址
如果獲得了ID,也有了想要跟蹤的內存地址,你可以開始模擬:
fromMAMEToolkit.emulator importEmulator
fromMAMEToolkit.emulator importAddress
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矩陣返回,同時,它也會返回該時間步長的所有內存地址整數值。
如果要向仿真器輸入動作,你還需要確定游戲支持的輸入端口和字段。比如玩街霸需要先投幣,這個代碼是:
fromMAMEToolkit.emulator importAction
insert_coin = Action(':INPUTS', 'Coin 1')
data = emulator.step([insert_coin])
要確定哪些端口可用,請使用list actions命令:
fromMAMEToolkit.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幀,可以輸入以下代碼:
fromMAMEToolkit.emulator importEmulator
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關。
至于智能體的學習率,它是用每一局智能體所造成的凈傷害和所承受的傷害來計算的。
-
存儲器
+關注
關注
38文章
7632瀏覽量
166370 -
python
+關注
關注
56文章
4823瀏覽量
86153 -
強化學習
+關注
關注
4文章
269瀏覽量
11514
原文標題:MAME:在這里,你可以用Python玩任何街機游戲
文章出處:【微信號:jqr_AI,微信公眾號:論智】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
評論