Edited at

AlphaGo Zeroの手法でリバーシの強化学習をやってみる

More than 1 year has passed since last update.


はじめに

AlphaGo Zeroは、囲碁AIをゼロから強化学習で鍛え上げたもので、それまで最強だったAlphaGo Masterを打ち破るという偉業を成し遂げました。そしてこのZeroの手法自体は結構シンプル、かつ、強くなれるという美味しいところ取りな手法なのです。また、そのゲームの知識を知らなくても実装できます。

今回は手法の理解と検証のため、リバーシのAIを育てているので共有します。


システム概要


動作環境

確認済みなのは以下の環境です。


  • Python 3.6.3

  • tensorflow-gpu: 1.3.0


    • tensorflow==1.3.0 でも動きますが、非常に遅いです。play_guiの時は tensorflow(cpu) でもまあ問題ない感じで動きます。



  • Keras: 2.0.8


Modules


強化学習用

今回の実装はself, opt, eval の3つのWorkerで構成されています。



  • self は最善モデル同士の自己対戦で訓練データを生成します。


  • opt はモデルの学習をさせ、次世代モデルを生成します。


  • eval は次世代モデルが最善モデルより優れているかを評価します。もし優れていれば、最善モデルを置き換えます。


評価用

評価のために、最善モデルと対戦することができます。



  • play_gui は 最善モデルと対戦します。


Data



  • data/model/model_best_*: 最善モデル


  • data/model/next_generation/*: 次世代モデル


  • data/play_data/play_*.json: 生成された訓練データ


  • logs/main.log: ログファイル

もし初期状態からモデルの訓練を行いたい場合は、上記のディレクトリを削除してください。


使い方


Setup


install libraries

pip install -r requirements.txt

GPUを使いたい場合は、更に以下のようにしてください。

pip install tensorflow-gpu


環境変数の設定

.env ファイルを作成し、以下のように記述してください。


.env

KERAS_BACKEND=tensorflow



最善モデルのDownload (必要なら)

ちょっと対戦してみたい、という場合やランダムな初期モデルから始めるのが面倒だという場合にDownloadしてください。

sh ./download_best_model.sh


基本的な使い方

モデルの訓練には、以下の Self-Play, Trainer, Evaluator を実行します。


Self-Play

python src/reversi_zero/run.py self

実行すると、最善モデルによる自己対戦を開始します。

もし、最善モデルが存在しない場合は、ランダムな初期モデルを作成し、それを最善モデルとします。


options



  • --new: create new BestModel


  • --type mini: use mini config for testing, (see src/reversi_zero/configs/mini.py)


Trainer

python src/reversi_zero/run.py opt

実行すると、訓練を開始します。

基準となるモデルは最新の次世代モデルです。が、存在しない場合は最善モデルを使用します。

訓練されたモデルは 各Epoch終了後の2000step(ミニBatch)毎に次世代モデルとして保存されます。


options



  • --type mini: use mini config for testing, (see src/reversi_zero/configs/mini.py)


  • --total-step: specify total step(mini-batch) numbers. The total step affects learning rate of training.


Evaluator

python src/reversi_zero/run.py eval

実行すると、評価が開始されます。

最善モデルと一番古い次世代モデルを約200回対戦させます。

もし、次世代モデルが勝った場合(勝率55%以上)、最善モデルとなります。


options



  • --type mini: use mini config for testing, (see src/reversi_zero/configs/mini.py)


Play Game

python src/reversi_zero/run.py play_gui

play_gui.png

実行すると、リバーシの盤面が表示され、最善モデルと対戦できます。

最善モデルが打った後、数字が盤面上に表示されます(動作検証用)。


  • マス目の左上の数字(1) は最後に探索した その状態と指し手の探索回数 N(s,a) を表しています。

  • マス目の左下の数字(2) は最後に探索した その状態と指し手のQ値(AI側) を表しています。Q値は100倍されています(この方が見やすいかな...と)。


Note: Mac の pyenv 環境の場合

play_guiwxPython を使っています。

PythonがFrameworkとビルドされていない場合は、実行できなくなります。

その場合、pyenv でのPython Installを以下のようなOption付きで実行すると良くなると思います。

env PYTHON_CONFIGURE_OPTS="--enable-framework" pyenv install 3.6.3


Tips and Memo


GPU Memory

私の環境には GeForce GTX 1080 があり、メモリが約8GBなのですが、よくメモリ不足になります。

メモリ不足でも大抵Warning止まりで、エラーにはなりません。が、たまに謎のエラーが発生します(原因はメモリ不足)。

その場合は、環境にあわせて src/worker/{evaluate.py,optimize.py,self_play.py}per_process_gpu_memory_fraction を調整してみてください。

tf_util.set_session_config(per_process_gpu_memory_fraction=0.2)

また、各Workerの実行順序を変えるとメモリを確保する順序が変わるので、上手く行くことがあります。optがメモリをかなり使うので、最後に起動するとWarningを吐きますが、なんとか動いてくれいます。

また バッチサイズを小さくするとメモリ消費を抑えることになります(挙動も何かしら変わるとは思いますが)。

NormalConfigTrainerConfig#batch_size をいじってみてください。


学習速度


  • CPU: 8 core i7-7700K CPU @ 4.20GHz

  • GPU: GeForce GTX 1080

  • 自己対戦 1 game: 約47秒

  • 評価 1 game: 約50秒

  • 訓練 1 step(ミニバッチ, batch size=512) : 秒2.3秒


さいごに

AlphaGo Zero論文に比べて、評価時の対戦回数などなど、色々スケールが縮小していますが、リッチな計算機環境をお持ちの方は、もっと大規模に実行してもらうと楽しいかもしれません(正常に強くなっていくかはまだわかってないのですが...)。

実際に訓練で強くなっていくか(実装が正しいか、モデルのキャパシティが十分か、設定がおかしくないか)は、今後の経過を観察するしかない感じです。

既存のリバーシAIに勝てるといいなぁ。


学習進捗

次の表は、最善モデルの世代の記録です。

モデルの性能評価のために、 iOS アプリ(https://itunes.apple.com/ca/app/id574915961) と時々対戦させています。


2017/12/08 所感

このアプリは少なくともLV20程度ではわざと愚かな手を打つことがあり(たぶんハンデの実装としてそうなっているのだと思いますが)、それで単に勝ち進んでいる気もします。本当は100回くらい対戦して勝敗を比較すべきなのですが、自動対戦できる良いベンチマークアプリがあれば良いんですが。

ただまあ眺めていると、なかなか面白い手を打つことがありますが、人間が少し意識して打つとたぶん簡単に勝てる程度のレベルです。

初期(40世代頃)より弱くなっているような気もしないでもないです。MCTSのパラメータなどを結構いじっているのでその辺の影響もあるかもしれません。パラメータを変えた自己対戦で最適な値を先に求めないといけないのかもしれません。

最善モデル世代
日付
最善モデルに勝った時の勝率
世代交代にかかった時間
備考

1
-
-
-
 

2
2017/10/24
94.1%
-
 

3
2017/10/24
63.4%
13
 

4
2017/10/25
62.0%
3
 

5
2017/10/25
56.7%
8
 

6
2017/10/25
67.3%
7
 

7
2017/10/25
59.0%
3
 

8
2017/10/26
59.7%
6
 

9
2017/10/26
59.4%
3
 

10
2017/10/26
55.7%
5
 

11
2017/10/26
57.9%
9
 

12
2017/10/27
55.6%
5
 

13
2017/10/27
56.5%
7
 

14
2017/10/28
58.4%
20
 

15
2017/10/28
62.4%
3
 

16
2017/10/28
56.0%
11
 

17
2017/10/29
64.9%
17
 

18
2017/10/30
55.2%
19
 

19
2017/10/31
57.2%
33
 

20
2017/11/01
55.7%
12
 

21
2017/11/01
59.7%
20
 

22
2017/11/02
57.8%
19
 

23
2017/11/03
55.8%
15
 

24
2017/11/03
64.2%
12
 

25
2017/11/04
55.4%
21
 

26
2017/11/04
56.7%
6
 

27
2017/11/05
57.5%
11
 

28
2017/11/06
58.5%
15
 

29
2017/11/06
55.3%
5
 

30
2017/11/06
55.0%
8
 

31
2017/11/06
56.9%
5
 

32
2017/11/07
56.1%
9
 

33
2017/11/08
55.7%
22
 

34
2017/11/08
56.1%
3
 

35
2017/11/08
59.0%
3
 

36
2017/11/08
59.4%
3
 

37
2017/11/08
56.2%
9
 

38
2017/11/10
55.4%
52
App LV9,10 に勝った。

39
2017/11/12
57.2%
29
 

40
2017/11/12
55.1%
12
App LV11に勝った

41
2017/11/13
55.7%
14
App LV12, 13, 14に勝った。もう私では勝てなくなった。

42
2017/11/15
57.8%
18
App LV18, 19 に勝った

43
2017/11/15
55.8%
16
 

44
2017/11/16
57.5%
8
 

45
2017/11/16
56.2%
3
App LV20 に勝った

46
2017/11/18
55.6%
49
 

47
2017/11/19
55.9%
34
何故かまた私が勝てるようになった。弱くなっているのか、私が強くなったかはわからない。

48
2017/11/19
59.4%
9
 

49
2017/11/20
55.9%
6
 

50
2017/11/22
56.0%
44
 

51
2017/11/26
55.8%
112
11/25の朝に c_puct を 3 から 1.5 に変更

52
2017/11/26
59.7%
6
 

53
2017/11/28
56.2%
33
App LV21 に勝った

54
2017/11/29
59.0%
24
 

55
2017/12/01
56.6%
58
 

56
2017/12/03
58.1%
49
self-play: always save policy of tau=1

57
2017/12/04
55.1%
24
 

58
2017/12/05
55.9%
35
 

59
2017/12/06
55.4%
6
 

-
2017/12/06
-
-
implement https://github.com/mokemokechicken/reversi-alpha-zero/issues/13

60
2017/12/07
61.7%
25
 

61
2017/12/07
58.1%
3
 

62
2017/12/07
57.8%
11
 

-
2017/12/07
-
-
fix bug about virtual loss W

63
2017/12/08
57.5%
9
 

64
2017/12/08
56.0%
9