初めに
- この記事は 2018/06/30 に開催の「機械学習 名古屋 第14回勉強会【ゲームの強化学習ハンズオン OpenAI Gym パート2】」のための解説ページです。
おさらい:強化学習とは
強化学習とは
- 変化する 環境 下で判断・ 行動 し課題を解決する問題を扱う
- (一連の)行動に対して得られる 報酬 を元に、ある 状態 における 次の行動 を 学習 して獲得していく
事例:自動運転
- Building a Simple Self-Driving Car Simulator | Pointers Gone Wild(ブログ記事)
- Lane-following neural network in a simulation - YouTube(デモ動画)
事例:ゲーム
基礎概念
- 状態:
S
(Observation の略でobs
とすることも) - モデル:
T
(T(s,a,s')
) - 行動:
A
(A(s)
) - 報酬:
R
(R(s)
/R(s,a)
/R(s,a,s')
)
おさらい:OpenAI Gym
OpenAI Gym
- OpenAI Gym
- 強化学習用ツールキット。統一インターフェースを提供
- いくつかのシミュレーション環境(ゲーム等)を用意
OpenAI Gym の 環境 (Env)
env = gym.make(env_name) # 環境構築(読込)
env.reset() # 初期化 状態を取得
env.render() # 可視化
env.step(action) # 行動を行う 状態・報酬などを取得
env.close() # 終了
大事なのは↓の2つ
- 環境から状態(
S
=obs
)を取得 - 環境に対して行動(
step
) → 結果の状態(obs
)と報酬(R
)を返す
OpenAI Gym で強化学習
- モデル
T
を構築 - 行動
A
を選択 - Gym の環境に対して 行動
A
を送り、状態S
や 報酬R
を受け取って、モデルT
を学習
ハンズオン
ハンズオン環境
- Python 3.5以上(3.6以上推奨)
- OpenAI Gym(
CartPole-v0
環境) - ChainerRL
ハンズオン環境補足
- Linux / macOS:基本的に OpenAI Gym の README の手順通りに環境を作成できていればOK
- Windows:以下のいずれかの方法
- VirtualBox 等の仮想環境上に Linux 環境を構築
- WSL(+ Linux) + XServer 環境を構築(補足資料)
- Docker(制限あり)
ハンズオン0:準備
- OpenAI Gym 等の準備は省略(別資料等参照ください)
- 今回も 勉強会用 Git リポジトリ を用意しています(↓適当なディレクトリで以下のコマンドを実行して clone してください)
$ git clone https://github.com/mlnagoya/MLN_201806
動作確認。
※ python -V
の実行結果が Python 3.x.x
と表示されるなら(その環境下に OpenAI Gym をインストールしていれば)以下の python3
は python
と読み替えてください。
$ python3 handson_dqn.py --train-episodes=20 --outdir=_output20
エラーが起きたら後述の「トラブルシューティング」参照
ハンズオン1:パラメータ調整
$ python3 handson_dqn.py -h
usage: handson_dqn.py [-h] [--outdir OUTDIR] [--gamma GAMMA]
[--final-exploration-steps FINAL_EXPLORATION_STEPS]
[--start-epsilon START_EPSILON]
[--end-epsilon END_EPSILON]
[--replay-buffer REPLAY_BUFFER]
[--replay-start-size REPLAY_START_SIZE]
[--target-update-interval TARGET_UPDATE_INTERVAL]
[--update-interval UPDATE_INTERVAL]
[--train-episodes TRAIN_EPISODES]
[--max-episode-len MAX_EPISODE_LEN]
[--test-episodes TEST_EPISODES]
optional arguments:
-h, --help show this help message and exit
--outdir OUTDIR 出力ファイル保存先ディレクトリ。 存在しなければ自動生成されます。 (default: _output)
--gamma GAMMA 割引率 (default: 0.95)
--final-exploration-steps FINAL_EXPLORATION_STEPS
探索ステップ数 (default: 10000)
--start-epsilon START_EPSILON
ε-greedy法 の開始ε値 (default: 1.0)
--end-epsilon END_EPSILON
ε-greedy法 の終了ε値 (default: 0.1)
--replay-buffer REPLAY_BUFFER
Experience Replay のバッファサイズ (default: 1000000)
--replay-start-size REPLAY_START_SIZE
replay-start-size (default: 500)
--target-update-interval TARGET_UPDATE_INTERVAL
target-update-interval (default: 100)
--update-interval UPDATE_INTERVAL
update-interval (default: 1)
--train-episodes TRAIN_EPISODES
訓練エピソード数 (default: 200)
--max-episode-len MAX_EPISODE_LEN
1回のエピソードの最大ステップ数 (default: 2000)
--test-episodes TEST_EPISODES
検証エピソード数 (default: 10)
コマンドライン引数で各種パラメータを弄ってみる。
例:
-
--gamma=0.99
(割引率) -
--train-episodes=500
(訓練エピソード数) - …
ハンズオン2:実装修正
- handson_dqn.py(本体)
- util
- qfunctions.py(Q関数)
- explorers.py(戦略)
- replay_buffer.py(リプレイバッファ)
qfunctions.py(抜粋)
qfunctions.py(抜粋)
# :
class MyQFunction(chainer.Chain):
"""
Q^*をDNNを使って近似する(別実装)
"""
def __init__(self, obs_size, n_actions):
# TODO: 必要なら引数を追加して、QFunction3LP の実装を参考にネットワークを構築する
raise NotImplementedError
def __call__(self, obs, test=False):
# TODO: QFunction3LP の実装を参考にネットワーク適用を実装する
raise NotImplementedError
- 自分で実装してみる!
explorers.py(抜粋)
explorers.py(抜粋)
# :
class ConstantEpsilonGreedy(explorer.Explorer):
"""ε-greedy 法(ε固定)"""
def __init__(self, epsilon, random_action_func):
assert epsilon >= 0 and epsilon <= 1
self.epsilon = epsilon
self.random_action_func = random_action_func
def select_action(self, t, greedy_action_func, action_value=None):
return select_action_epsilon_greedily(
self.epsilon, self.random_action_func, greedy_action_func)
def __repr__(self):
return 'ConstantEpsilonGreedy(epsilon={})'.format(self.epsilon)
- 実装を弄ってみる!
replay_buffer.py(抜粋)
replay_buffer.py(抜粋)
# :
class BestReplayBuffer(SimpleReplayBuffer):
"""報酬の高いものを優先的に記憶する ReplayBuffer"""
def __init__(self, capacity=1000):
super().__init__(capacity)
# TODO: より報酬の高いものを優先的に残すような実装をする
# def append(self, state, action, reward, next_state=None, next_action=None, is_state_terminal=False):
# pass
- 自分で実装してみる!
handson_dqn.py(抜粋)
from util.qfunctions import QFunction3LP as QFunction
# from util.qfunctions import MyQFunction as QFunction
# ↑ココ
# : 《中略》
def get_agent(env, args):
# : 《中略》
# Use epsilon-greedy for exploration
# explorer = ConstantEpsilonGreedy(
# epsilon=args.start_epsilon,
# random_action_func=env.action_space.sample)
explorer = LinearDecayEpsilonGreedy(
args.start_epsilon, args.end_epsilon, args.final_exploration_steps,
random_action_func=action_space.sample)
# ↑ココ
# Experience Replayの設定
replay_buffer = SimpleReplayBuffer(capacity=args.replay_buffer)
# replay_buffer = BestReplayBuffer(capacity=args.replay_buffer)
# ↑ココ
# : 《後略》
- 実装変更を反映して、学習させてみる!
ハンズオン(その後)
- ChainerRL に用意されている他のアルゴリズム・手法等も試してみる
- OpenAI Gym の他の環境でも試してみる
- Gym に登録されていない環境(例:自動運転シミュレータとか)も試してみる
補足
Q関数(おさらい)
- $Q^*(s,a)$:状態$s$で行動$a$をとったときの割引累積報酬の最大値
- Q学習:このQ関数を機械学習で学習(≒モデルを学習)
- DQN:Q関数をDNNで近似(して学習)
ε-greedy 法
- 行動選択戦略:
- $0.0 \le \varepsilon \le 1.0$
- $\varepsilon$ の確率で行動をランダムに選択
- $1-\varepsilon$ の確率で Q値 が最大となる(過去の)行動を選択
- $\varepsilon$ を固定化(例:$\varepsilon=0.3$)するも良し、減衰(例:初期値$\varepsilon=1.0$、10000ステップ後に$\varepsilon=0.1$、線形に変化)するも良し
-
ConstantEpsilonGreedy
/LinearDecayEpsilonGreedy
-
Experience Replay(経験再生)
- データごとの相関をなくすための手法:
- 過去の経験(≒「状態」「行動」「報酬」(など)の組合せ)を記憶しておく
- その中からランダムに選択して学習に利用する
-
SimpleReplayBuffer
:過去の経験を出来るだけ多く記憶、制限を超えたら古いものから忘却、記憶している「経験」を乱択 - 少し賢く:
-
BestReplayBuffer
:成績の良い経験を優先的に記憶、経験の乱択を従来通り -
PrioritizedReplayBuffer
:成績で優先順位を付けておき、乱択時に優先順位の高いものが高確率で選択されるようにする
-
トラブルシューティング
学習・テストの様子がGUIで表示されない
- Docker 利用の場合:仕様です
- Windows + WSL 利用時:
- エラーが出ている:XServer との連携設定がうまくいってない可能性が高いです。
DISPLAY
環境変数の値を見直してみましょう - 固まっている:Python と OpenGL との相性問題かも。XServer 起動時に「ネイティブの OpenGL(WinGL)を利用しない」設定にして再度試してみてください
- エラーが出ている:XServer との連携設定がうまくいってない可能性が高いです。
- Linux / macOS の場合:Python / OpenAI Gym / その他依存ライブラリの再インストールが必要かも…
学習はうまくいくがテスト開始時にエラーで落ちる
-
gym.wrappers.Monitor
を利用して動画保存するために必要なffmpeg
がたぶんインストールされていません。- Linux(Ubuntu)の場合:
sudo apt install ffmpeg
(他のディストリビューションでも同様)(バージョンによってはsudo add-apt-repository ppa:〜
が必要、詳細はググってくださいm(_ _)m) - macOSの場合:
brew install ffmpeg
- もし Anaconda を利用していたら:
conda install ffmpeg
- Linux(Ubuntu)の場合:
-
ffmpeg
入ってるのにうまくいかない:ffmpeg
へのパスが通っているか確認しましょう