7
6

More than 1 year has passed since last update.

OpenSpielで始める強化学習その① ~OpenAI Gymとの比較~

Last updated at Posted at 2021-08-14

初めに

OpenSpielとは

DEEPMINDが作成した研究者向けの強化学習フレームワークのOSSです。マルチエージェントRLの研究の促進や研究の再現性の向上を目的としています。
主にPythonとC++で書かれていますが、GoやSwift、Juliaもサポートされています。
深層強化学習はTensorFlow1、2、JAXとPytorchに対応しています。

想定される読者

自分のように研究者ではないが強化学習について勉強してみたいけど何使えばいいんだっけという人向けに書いています。

環境

$ sw_vers
ProductName:    macOS
ProductVersion: 11.4
BuildVersion:   20F71

$ python3 -V
Python 3.9.5

インストール方法

pip install open_spiel

でインストールされます。ビルドするため8分程度かかるかと思います。
環境によっては、うまくいかないかもしれないので公式ドキュメントを参考にしてください。

8月中旬に1.0.0へのMajor updateが予定されていて、それ以降はでものの数秒でインストールされるようになるはずです。

基本的な使い方

主に二つあるのでそれぞれ紹介します。

①OpenAI Gymに近い使い方

import pyspiel
from open_spiel.python import rl_environment
from open_spiel.python.algorithms import random_agent
# 登録されているゲームを読み込みます
env = rl_environment.Environment('go(komi=0.0,board_size=5)')
# 環境を初期化します
time_step = env.reset()
agents = [random_agent.RandomAgent(player_id, env.action_spec()['num_actions']) for player_id in range(2)]
# ゲームが終了するまで動かします
while not time_step.last():
    current_player = time_step.observations["current_player"]
    # エージェントのstepでactionを決定
    agent_output = agents[current_player].step(time_step)
    # 環境を進めます
    time_step = env.step([agent_output.action])

②公式で紹介されている方法

import random

import pyspiel
import numpy as np

# 登録されているゲームを読み込みます
game = pyspiel.load_game('go(komi=0.0,board_size=5)')
# 新しいゲームを始めます
state = game.new_initial_state()
# ゲームが終わるまで動かします
while not state.is_terminal():
    legal_actions = state.legal_actions()
    # チャンスノード
    if state.is_chance_node():
        outcomes_with_probs = state.chance_outcomes()
        action_list, prob_list = zip(*outcomes_with_probs)
        action = np.random.choice(action_list, p=prob_list)
        # 環境を進めます
        state.apply_action(action)
    else:
        # 各プレイヤーの行動
        legal_actions_mask = state.legal_actions_mask()
        prob_list = [legal_actions_mask[action] / sum(legal_actions_mask) for action in legal_actions]
        action = np.random.choice(legal_actions, p=prob_list)
        # 環境を進めます
        state.apply_action(action)

今回はGymとの比較のため前者の方法で記載していきたいと思います。

OpenAI Gymとの違い

まず「強化学習をpythonで」と聞くと真っ先に思いつくのがOpenAI Gymだと思います。
ここでは違いを簡単に比較していきたいと思います。

提供されているゲーム

>>> import gym
>>> len(gym.envs.registry.all())
859
>>> import pyspiel
>>> len(pyspiel.registered_games())
78

Gymは強化学習のシミュレーション用プラットフォームだけあって提供されているゲームがそれこそ桁違いにあります。公式リンクはこちら
OpenSpielの一覧はこちらです。
GymはAtariを代表とした主に一人用のゲーム、OpenSpielは主に複数人用のゲームを提供しているためかゲームは全く被っていません。

ゲームの実行速度

被っているものがなかったのでGym公式が記載していた外部パッケージを使用して比較します。

import gym
go_env = gym.make('gym_go:go-v0', size=5, komi=0)
for _ in range(100):
    go_env.reset()
    done = False
    while not done:
        action = go_env.uniform_random_action()
        state, reward, done, info = go_env.step(action)

2.07 s ± 102 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

import pyspiel
from open_spiel.python import rl_environment
from open_spiel.python.algorithms import random_agent
env = rl_environment.Environment('go(komi=0.0,board_size=5)')
for _ in range(100):
    time_step = env.reset()
    agents = [random_agent.RandomAgent(player_id, env.action_spec()['num_actions']) for player_id in range(2)]
    while not time_step.last():
        current_player = time_step.observations["current_player"]
        agent_output = agents[current_player].step(time_step)
        time_step = env.step([agent_output.action])

164 ms ± 1.89 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

OpenSpielではゲームはC++で書かれたものをPythonバインディングしているので、Gymと比較して10倍程度早いという結果になりました。

実装されている手法

Gymはシミュレーションプラットフォームのため、手法の提供しておらず、外部パッケージを用いる必要があります。
例えばDQNを使用したい場合、公式のリンクからパッケージをインストールするか、
keras-rlを用いて自分でネットワークを書かないといけません。

OpenSpielでは、多くの手法が提供されており、例えばAlpha Zeroも何も考えずに使えるようになっています。
比較のためDQNを使用する場合を記載すると

import pyspiel
from open_spiel.python import rl_environment
from open_spiel.python.algorithms import random_agent
from open_spiel.python.pytorch import dqn
env = rl_environment.Environment('go(komi=0.0,board_size=5)')
time_step = env.reset()
agents = [dqn.DQN(player_id,
                  env.observation_spec()['info_state'][0],
                  env.action_spec()['num_actions']) for player_id in range(2)]
while not time_step.last():
    current_player = time_step.observations["current_player"]
    agent_output = agents[current_player].step(time_step)
    time_step = env.step([agent_output.action])

もちろんDQNの引数でNNの定義を変更することも可能です。
その他すぐに使える手法としては公式で一覧があります。

まとめ

  1. 自分が強化学習したいゲームを提供している環境がある方を使うのが良さそう
  2. Gymの外部パッケージのゲームとOpenSpielのゲームだったらOpenSpielの方が高速なのでOpenSpielの方が良さそう
  3. いろいろな手法を比較したい場合OpenSpielの方が良さそう

最後に

目隠しチェスでのDEEPMIND主催のコンペも開催されているみたいです。

次回はばかなおうじさんの記事を元にしてOpenSpielを使用したCFRの実装を深ぼるところを記事にしたいと思います。
(追記)②も書いたのでぜひ読んでください!

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6