Qiita 初投稿です。研究で HandyRL を使うことになったので、使い方などを備忘録としてまとめようと思います。HandyRL を使ってみたいけどやり方が分からない人の参考になればと思います。
目次
HandyRLとは
使い方
- 準備
- 実行
応用
- 2台の計算機を使って並列学習をする
- 学習の勝率の可視化
そのほか
- パラメータの詳細
- 参考文献
HandyRLとは
HandyRL は DeNA が開発した最新の並列強化学習のフレームワークです。 この HandyRL は 「誰でも強化学習を手軽に扱える」「対戦ゲームにおいて強くて勝てるAIが作れる」「並列度を上げて学習がスケールする」ことの3つを目指して開発されたらしいです(参考元)。実際に kaggle で行われた Hungry Geese コンペティション(ヘビのゲーム)で優勝もしている強くて勝てるAIです。本当に手軽に動かすことができるので、強化学習に興味がある方はぜひ動かしてみてください。また実装するのが難しい並列強化学習を簡単に使うことができ、高速で学習することができるようになっています。
使い方
内容はほぼ GitHub の README 通りですが、ちょっと補足とか自分が詰まった点とかを書いときます。
書いてる人の動作環境
- MacBook Pro(2017)
- macOS Monterey バージョン:12.6.1( Ubuntu16.04.7 でも動かせた)
- Visual Studio Code バージョン:1.73.1
- anaconda バージョン:4.13.0
必要なもの
- Python バージョン:3.7 以上
準備
インストール
HandyRLのリポジトリを自分の手元の環境に落とします。
GitHubからクローンする場合
以下を実行でGitHubからクローンを作成
git clone https://github.com/DeNA/HandyRL.git
GitHubから直接ダウンロードする場合
1. HandyRLのGitHubページにアクセス
2. ページ内の< > Code ▼
(緑色のボタン)をクリック
3. Download Zip
から自分の手元の環境にzipファイルをダウンロード
4. お好きなところでzipファイルを解凍
HandyRLで使うライブラリのインストール
HandyRLのディレクトリに移動
cd HandyRL
追加のライブラリ (numpy、pytorch など) をインストール
pip3 install -r requirements.txt
Dockerや仮想環境上で実行(pythonの環境構築が必要)
kaggleの環境(Hungry Geeseなど)を使う場合には以下も追加でインストール
pip3 install -r handyrl/envs/kaggle/requirements.txt
実行
パラメータを設定する
config.yaml
でパラメータの設定をすることができます。デフォルトの環境は Tic-Tac-Toe(三目並べ) になっていて、他には geister や kaggleのコンペであった Hungry Geese, Parallel Tic-Tac-Toe を選択することができます。また自分で作成した環境を利用して学習させることも可能となっています。私自身研究用の環境を作成して追加したことがあります。興味がある方はぜひ別記事(後日公開予定)を読んでみてください。
env_args:
env: 'TicTacToe' #環境指定
train_args:
...
batch_size: 64 #バッチサイズ
...
上記のコードの場合は環境を Tic-Tac-Toe に, バッチサイズを64に設定しています。
学習させる
パラメータ設定後、以下のコマンドで学習させることができます。学習済みのモデルはmodels
内に保存されます。
python main.py --train
config.yaml
のエポック数を決めるパラメータが初期状態だとepochs:-1
になっていて学習が止まらないので注意
学習させたモデルを評価する
以下のコマンドで任意のモデルを評価することができます。下の場合は評価のプロセス数を4つに指定し、100ゲーム行ったときのmodels/1.pth
のモデルを評価してます。
python main.py --eval models/1.pth 100 4
応用
2台の計算機を使って並列学習をする
計算機の性能次第ですが、学習速度がめちゃめちゃ早くなります。
うまく使えば AWS とか GoogleColab とかでも動かせるかも?(やり方わからないので有識者いたらコメントください)
パラメータの設定
config.yaml
の以下の部分を設定します
woker_args:
server_address: '' # サーバーのIPアドレス
num_parallel: 8 # ワーカーの数
おそらく外部からアクセスできるアドレスじゃないと接続できないので注意
学習させる
以下を親サーバ側(server_addressに設定したIPアドレスの方)で実行します
python main.py --train-server
以下を子サーバ側で実行します
python main.py --worker
いろいろな実行方法
python main.py *** (***の部分は短縮可能)
- 通常の学習:
--train
or-t
- 学習サーバを起動:
--train-server
or-ts
- ワーカーを起動:
--worker
or-w
- モデルの評価:
--eval
or-e
学習させたモデルを評価する
通常時と同様
python main.py --eval models/1.pth 100 4
学習の勝率の可視化
scripts/win_rate_plot.py
を使うことで可視化ができます。
学習時の出力を任意の.txt
に出力する必要があります。
ちなみに公式はあまり推奨していなさそう?なので自己責任でお願いします。(可視化のコードに注意書きがありました)
ライブラリを追加インストール
pip3 install -r scripts/requirements.txt
可視化する際の学習方法(ファイル出力)
今回はtee
コマンドを使って txt ファイルに学習時のログを出力します。
python main.py --train | tee train-log-000.txt
上記コードの000の部分は任意の値でOK(txtファイル自体の名称も任意で大丈夫だったはず・・・)
学習の可視化
python3 scripts/win_rate_plot.py train-log-000.txt all
train-log-000.txt
の部分で可視化したいログファイルを指定し、all
でグラフのタイトルを指定できます。
ログのパスに注意(上記のコードだとmain.pyと同じ階層にtxtファイルがある)
可視化できずにエラーが出た場合
エラー内容
ValueError: x and y must have same first dimension, but have shapes (86,) and (87,)
原因
ログファイルの終わりの部分が前後している可能性があるので修正します。
epoch 98
win rate = 0.826 (73.5 / 89)
generation stats = 0.000 +- 0.928
loss = p:-0.038 v:0.104 ent:1.491 total:-0.037
updated model(295)
20300 20400 opened worker 0
closed worker 0
opened worker 3
~~~~~~~~~~~~ 省略 ~~~~~~~~~~~~~~~
disconnected
disconnected
epoch 99
win rate = 0.753 (67.0 / 89)
generation stats = 0.000 +- 0.939
loss = p:-0.041 v:0.114 ent:1.505 total:-0.031
updated model(298)
disconnected
finished server
上記の通り epoch 98
と epoch 99
の間にopend woker ~
などが入っています(上はepochs:100
で実行した場合です)。通常の場合は、epoch 99
の後に表示されるのが変な位置で表示されているためエラーが出ているっぽいです。
対処法
力技になりますがログファイルをちょっと書き換えます。
epoch 98
win rate = 0.826 (73.5 / 89)
generation stats = 0.000 +- 0.928
loss = p:-0.038 v:0.104 ent:1.491 total:-0.037
updated model(295)
20300 20400
epoch 99
win rate = 0.753 (67.0 / 89)
generation stats = 0.000 +- 0.939
loss = p:-0.041 v:0.114 ent:1.505 total:-0.031
updated model(298)
disconnected
finished server
open woker ~
などをバッサリ削除してepoch 98
とepoch 99
を繋げました。これで可視化できるはず・・・。
ちなみにopen woker ~
部分は可視化に影響しないので消して大丈夫です。
そのほか
パラメータの詳細
ここではconfig.yaml
内のパラメータについて記載します。
間違っていたらご指摘いただけると幸いです。
環境のパラメータ設定(env_args)
-
env
(string型)- 学習させる環境名
- TicTacToe, Geister, ParallelTicTacToe, HungryGeese
- 自身で作成した環境を使用する場合は
handyrl/envs/環境名.py
に自作環境を置く必要がある-
environment.py
のENV
にも追加する必要があるかも?
-
学習のパラメータ設定(train_args)
ここのパラメータは学習時に使われます。(python main.py --train
or python main.py --train-server
)
-
turn_based_training
(bool型)- 環境がターン制のゲーム(複数のプレイヤーが交互に行うゲーム)かどうかのフラグ
-
True
:ターン制のゲーム(Tic-Tac-Toe, Geister) -
False
:ターン制じゃないゲーム(HungryGeese)
-
observation
(bool型)- 学習時に対戦相手の機能を使用するかどうか
-
gamma
(double型)- 0.0 <=
gamma
<= 1.0 の範囲で設定 - 割引率
- 0.0 <=
-
forward_steps
(int型)- 学習に何ステップ先までの情報を用いるかの設定
-
compress_steps
(int型)- 効率的にデータを処理するためにエピソードのデータを圧縮する手順?
- 【注意点】システムで使われるパラメータらしいので初期設定でもOK
-
entropy_regularization
(double型)- 0.0 <=
entropy_regularization
の範囲で設定 - エントロピー正則化係数
- 0.0 <=
-
entropy_regularization_decay
(double型)- 0.0 <=
entropy_regularization_decay
<= 1.0 の範囲で設定 - ステップ進行中のエントロピー正則化の減衰率
- 【注意点】HandyRLの場合は、ターンが進むにつれて減衰するらしい
- 【注意点】値が大きいほど効果が小さく、値が小さいほど効果が大きくなる
- 0.0 <=
-
update_episodes
(int型)- モデルを更新して保存するエピソードの間隔の設定
- 設定したタイミングでワーカーのモデルが更新される
-
batch_size
(int型)- バッチサイズ
-
minimum_episodes
(int型)- エピソードのデータを保存するための最小のバッファサイズ
-
minimum_episodes
以上のエピソードのデータが貯まったら学習が開始される
-
maximum_episodes
(int型)-
minimum_episodes
<=maximum_episodes
の範囲で設定 - エピソードのデータを保存する最大のバッファサイズ
-
maximum_episodes
以上にデータが貯まると古いものから無くなる
-
-
epochs
(int型)- トレーニングを停止するエポックの設定
- 【注意】 0未満に設定した場合は無限にトレーニングする
-
num_batchers
(int型)- マルチプロセスでバッチデータを作成するバッチャーの数
-
eval_rate
(double型)- 評価に使うワーカーの割合
- 残りはデータ生成用のワーカー
-
worker
-
num_parallel
(int型)- ワーカーの数
-
-
lambda
(double型)- 0.0 <=
lambda
<= 1.0 の範囲で設定 - モンテカルロ法と1ステップTD法の両方で用いられるラムダの値
- 【注意】詳細はTD(λ)wikiを参照
- 【注意】HandyRLではTD, V-Trace, UPGOのラムダを使用して値を計算する
- 0.0 <=
-
policy_target
(enum型)- 方策の計算に使うアルゴリズム
-
MC
:モンテカルロ -
TD
:TD(λ) -
VTRACE
: IMPALA の論文の V-Trace -
UPGO
:AlphaStar の論文の UPGO
-
value_target
(enum型)- 価値の計算に使うアルゴリズム
-
MC
:モンテカルロ -
TD
:TD(λ) -
VTRACE
: IMPALA の論文の V-Trace -
UPGO
:AlphaStar の論文の UPGO
-
seed
(int型)- learnerとworkerのseedの設定
- 【注意】現状は再現性が保証されてない
-
restart_epoch
(int型)- 学習を再開するエポック数
-
100
と設定するとmodels/100.pth
から学習が再開されて、次のモデルmodels/101.pth
から保存されるようになる
ワーカーのパラメータ設定(worker_args)
ここのパラメータは並列学習するときにのみ使われます。(python main.py --worker
)
-
server_address
(string型)- ワーカーから接続されるトレーニングサーバーのアドレス
- 【注意】クラウドサービス(GCP,AWSなど)でモデルを学習する場合、仮想マシンの内部/外部のIPをここで設定できるらしい
-
num_parallel
(int型)- ワーカーの数
参考文献