TadaoYamaokaの開発日記

個人開発しているスマホアプリや将棋AIの開発ネタを中心に書いていきます。

将棋AIの実験ノート:Mask-AttentionでAIの着目点を可視化する

深層強化学習でAIが着目している箇所を可視化するという以下の論文の手法(Mask-Attention)を、将棋AIでも試してみたい。
http://mprg.jp/data/MPRG/F_group/F20200610_itaya.pdf

Mask-Attention

方策ヘッドに、位置情報をAttentionとして乗算する。
f:id:TadaoYamaoka:20200823000006p:plain

Attentionは、人間によるヒントは不要で、自動で学習される。
推論時に、Attentionの重みを取り出すことで、AIが着目している箇所を可視化できる。

可視化だけではなく、精度も向上すると報告されている。
f:id:TadaoYamaoka:20200823000626p:plain

将棋への応用

dlshogiのニューラルネットワークも、論文と同様に価値ヘッドと方策ヘッドで構成されており、Mask-Attentionの機構を導入するは簡単である。

なお、Leela Chess Zeroでは、SENetが導入されており、チェスではAttentionによる精度向上が確かめれている。
SENetは、チャンネルに対して乗算を行うため、どのチャンネルに注目しているかをAttentionで補助している。
dlshogiでもSENetを試したが、結果が得られるほど実験できていない。)
Mask-Attentionは、方策ヘッドのみで、位置に対してAttentionを導入しているという違いがあるが、将棋でも精度も向上が期待できそうである。

今後の予定

ということで、簡単に実装できそうなので、(やる気がでれば)まずは教師ありで学習してみて、可視化と精度の比較をしてみたい。
実現できれば、ディープラーニングの将棋AIならではの使い方ができて面白いのではないかと思う。

dlshogiにおける思考時間と強さの関係 更新

先日記事にしたdlshogiにおける思考時間と強さの関係について、思考時間8秒、16秒の結果と、水匠2のスレッド数を8にした場合の結果が測定できたので記事にする。

測定条件は前回と同じである。

dlshogi vs 水匠2(1000万ノード固定)の測定結果

思考時間(秒) 勝ち 引き分け 勝率 R
1 87 9 36.6% -95.44
2 132 7 54.2% 29.25
3 158 3 63.8% 98.44
4 165 2 66.4% 118.33
8 175 6 71.2% 157.24
16 197 6 80.0% 240.82

f:id:TadaoYamaoka:20200818223151p:plain

水匠2(8スレッド) vs 水匠2(1000万ノード固定)の測定結果

思考時間(秒) 勝ち 引き分け 勝率 R
1 54 19 0.254 -187.16
2 88 33 0.418 -57.50
3 119 33 0.542 29.25
4 184 24 0.784 223.94
8 203 15 0.842 290.66
16 218 20 0.912 406.20

f:id:TadaoYamaoka:20200818223503p:plain

思考時間に対するレーティングの伸び比較

f:id:TadaoYamaoka:20200818223921p:plain

dlshogiの方が思考時間が短い場合に強く、水匠2の方が思考時間を延ばした場合のレーティングの伸びが良い。
AlphaZeroの論文の通りであれば、dlshogiの方が思考時間に対してレーティングの伸びが良いはずだが、異なる傾向になった。

ただし、水匠2は同一ソフトなので勝ちやすいということもあるかもしれないので、別の機会にdlshogiのノード固定に対する測定も追試したい。

将棋AIの実験ノート:活性化関数Swishを試す 続き

先日試したSwishについて、推論速度がどれくら低下するのかと、精度が上がった代わりに速度が低下した場合に強さにどう影響するのかが気になったので調べてみた。

精度

先日は、8サイクル分学習した時点の結果を記したが、今回は16サイクル分学習したモデルを使用した。
16サイクル分学習した時点の精度は以下の通り。

条件 訓練損失平均 テスト損失 policy一致率 value一致率
Swishなし 0.84661563 1.61019968 0.44103022 0.69944063
Swishあり 0.86657027 1.58214659 0.44275271 0.71354634


Swishの方がvalueの学習が安定する傾向がありそうだ。

推論速度

floodgateの棋譜からサンプリングした100局面に対して、5秒思考した際のNPSを計測した。
測定プログラム:
https://github.com/TadaoYamaoka/DeepLearningShogi/blob/master/utils/benchmark.py

V100 1枚で、Onnx出力してTensorRTを使用。

Swishなし Swishあり
平均 34926.01 30477.17
中央値 37064 32797
最小値 17572 17036
最大値 41434 34941

NPSは、平均で87.3%に低下している。

強さの測定

互角局面集を使用して、先後を交互に入れ替え、250戦行った結果で測る。
引き分けも考慮するため、勝率は、勝ちを1ポイント、引き分けを0.5ポイントとして、ポイントの合計/250で計算する。
1GPU、秒読み1秒で、250対局行った結果は以下の通り。

Swishあり vs Swishなし
勝ち 引き分け 勝率 Eloレーティング
157 14 65.6% 112.14

R+112.14という結果になった。NPSは低下しているが、精度の向上の効果がそれを上回っているようだ。

ReLUを途中からSwishに変更できるか

Swishにすることで、同一データの学習で強くなることが確認できたが、現在学習済みのモデルのReLUをSwishに変更できるか検証してみた。

最新の1サイクル分だけ、ReLUをSwishに変更して学習した場合

373サイクル学習したモデルに対して、374サイクル目のデータをReLUをSwishに変更して学習してみた結果は以下の通り。

条件 訓練損失平均 テスト損失 policy一致率 value一致率
Swishなし 0.69250407 1.6051037 0.46532138 0.72403891
Swishあり 0.92641119 1.51048969 0.44681778 0.71891699

精度が大幅に低下している。
ReLUで学習したモデルはReLUで最適化されているため、Swishに変更することはできなそうだ。


過去5サイクル分まで遡って、同一データを学習した場合についても比較してみた。

条件 訓練損失平均 テスト損失 policy一致率 value一致率
Swishなし 0.69250407 1.6051037 0.46532138 0.72403891
Swishあり 0.76547083 1.52928974 0.46177364 0.72609071

policyの一致率は少し足りていないが、valueの一致率はReLUを上回っている。
十分にファインチューニングを行えば、既存のReLUのモデルをSwishに変更することはできそうということがわかった。

まとめ

活性化関数をReLUからSwishに変更するとNPSが低下するが、精度向上の効果の方が大きいことがわかった。
既存のモデルの活性化関数をReLUからSwishに変更すると精度が大幅に低下するが、十分にファインチューニングを行えばSwishに変更できる。


過去10サイクル分くらいで学習を行って、policy、valueの両方で精度が上回って、また強さも上回ることができれば、dlshogiの活性化関数をSwishに変更したいと思う。

将棋AIの実験ノート:活性化関数Swishを試す

画像認識で高い精度を達成しているEfficientNetで使われている活性化関数Swishが将棋AIでも効果があるか試してみた。

EfficientNetでは、残差ブロックにMBConvというアーキテクチャが使用されており、その中の活性化関数にSwishが使用されている。
MBConvについても別途検証を行ったが、今回はSwishの効果について記す。

Swishについて

Swishは以下の式で定義される活性化関数である。
\displaystyle
x \cdot \sigma(\beta x)
ここで、\sigma(z)シグモイド関数\sigma(z)=(1+exp(-z))^{-1}である。

グラフの形は以下のようになる。
f:id:TadaoYamaoka:20200814131227p:plain

どのような場合でもReLUに代わるものではないが、多くのタスクでReLUよりも精度が向上することが報告されている。

PyTorchのSwish実装

GitHubで公開されているPyTorchのEfficientNetの実装からSwishのコードを流用した。

この実装では、微分の計算が効率化されている。

ただし、Onnxに出力する際はエラーになるようなので、オリジナル実装に切り替える必要がある。

dlshogiのネットワークへの適用

dlshogiのpolicy_value_network.pyのreluをswishに置き換えたソースがこちら。
DeepLearningShogi/policy_value_network_swish.py at feature/experimental_network · TadaoYamaoka/DeepLearningShogi · GitHub

比較実験

測定条件

dlshogiの強化学習で生成した教師局面を使用して、教師あり学習を行い、floodgateからサンプリングした856,923局面に対する損失と一致率で評価する。
強化学習で生成した局面は、1サイクルあたり約270万局面生成しており、それを過去10サイクル分を1回のデータセットとして学習する。
8サイクル分のデータを学習した時点で比較した。

学習率:0.001(最初の1サイクルのみ0.01)
バッチサイズ:1024
最適化:Momentum SGD(係数0.9)
学習則:dlshogiと同じ

学習には、ampを使用した。

測定結果
条件 訓練損失平均 テスト損失 policy一致率 value一致率
Swishなし 0.85036430 1.62555117 0.43175799 0.70151462
Swishあり 0.86290113 1.60377155 0.43336603 0.71022165

f:id:TadaoYamaoka:20200814143424p:plain
f:id:TadaoYamaoka:20200814143705p:plain
f:id:TadaoYamaoka:20200814143714p:plain

テストデータに対する、損失、policyの一致率、valueの一致率すべてでSwishを使用した方が良い結果になった。

まとめ

dlshogiのResnetを使用したモデルの学習にSwishを使用すると精度が改善されることが確認できた。

今回は初期値からの学習を行ったが、現在学習済みのモデルに対して、活性化関数を変更した場合にどうなるかについても確認したい。
途中から変更しても効果があるなら、現在継続している学習に変更を取り入れる予定である。

Swishは深いモデルでうまく機能する傾向があるそうだが、もしかしたらNNUEの学習でも効果があるのかもしれないので(私は試さないので)興味のある方は試してみてほしい。


続き
将棋AIの実験ノート:活性化関数Swishを試す 続き - TadaoYamaokaの開発日記

dlshogiのautomatic mixed precision対応

48先生から頂いたautomatic mixed precision対応のプルリクに対応しました。
Pytorch 1.6 の Automatic Mixed Precision対応 by bleu48 · Pull Request #18 · TadaoYamaoka/DeepLearningShogi · GitHub

automatic mixed precisionは、PyTorch 1.6で追加されたTensorCoreを使用して学習を高速化する機能です。
詳細は↓こちらを参照。
Introducing native PyTorch automatic mixed precision for faster training on NVIDIA GPUs | PyTorch

学習時間

dlshogiの学習で測定した結果は以下の通り。

条件:

  • 27,051,941局面の学習
  • バッチサイズ 1024
  • SWA使用
条件 学習時間 SWAのbn_update 合計
ampなし 2:33:57 0:43:58 3:17:55
ampあり 1:15:53 0:31:52 1:47:45

学習時間とSWAのbn_updateの合計で、54%に短縮されている。

精度

テストデータにはfloodgateの棋譜からサンプリングした856,923局面を使用

条件 訓練損失平均 テスト損失 policy一致率 value一致率
ampなし 1.1555423 1.6557858 0.40078359 0.69063551
ampあり 1.15769344 1.65721888 0.40040172 0.68830110

精度が大幅に落ちるということは起きていない。
わずかに下がっているが、初期値の違いでも起きる差なのでampの影響は小さいと思われる。

補足

ampは、FP16への変換を自動で行い、精度が落ちないように計算中の値を自動でスケーリングする。
勾配がInfやNanになる場合は、そのstepはスキップされ、更新が連続で成功した場合に、自動でスケーリングパラメータを調整している。

dlshogiの初期モデルの学習は、初期値によってはモデルの出力がnanになることが良く起きていたが、上記の仕組みによりそれが発生しなくなった。
今の自己対局の仕組みでは起きていないが、以前は学習が進むと突然nanになるようなこともあったので、それも自動で防げるという効果もありそうだ。

まとめ

automatic mixed precisionを使用することで、精度を落とさずに学習を(上記の測定条件の場合)約1.8倍に高速化できる。


48先生、ありがとうございました。

dlshogiのgo nodes対応

少し前にQhapaqさんからもらったプルリクに対応しました。
add go protocol by qhapaq-49 · Pull Request #17 · TadaoYamaoka/DeepLearningShogi · GitHub

go byoyomiで、探索を打ち切らずに時間いっぱいまで探索するようになりました。
go nodesで、固定ノード数まで探索できるようになりました。
(USIオプションのConst_Playoutも継続利用可)

ついでに、今まで探索の打ち切り(最善手が変わる可能性がない場合に打ち切る)は全スレッドで確認していましたが、わずかですが高速化のために一つのスレッドのみで監視するようにしました。

Qhapaqさん、プルリクありがとうございました。

dlshogiにおける思考時間と強さの関係

MCTSと思考時間と強さの関係について、dlshogiのデータが知りたいという要望があったので測定してみた。

測定条件

対戦相手は、最新のやねうら王Ubuntu 18.04のclangでビルドしたもの+水匠2の評価関数で、1000万ノード固定とする。

dlshogiは、最新のソースに、最新のモデル(WCSOC1からR+76くらい)を使用した。


測定環境は、CPU Xeon E5-2698 v4(2.20GHz)、GPU NVIDIA V100、Ubuntu 18.04(Docker)。

水匠2は2スレッド、dlshogiは3スレッド1GPUを使用し、思考時間を変えて測定。

思考時間は、1秒、2秒、3秒、4秒、8秒、16秒とした(8秒、16秒は測定中)。
ポンダーはなし。
256手で引き分け。

強さは、互角局面集を使用して、先後を交互に入れ替え、250戦行った結果で測る。
引き分けも考慮するため、勝率は、勝ちを1ポイント、引き分けを0.5ポイントとして、ポイントの合計/250で計算する。

水匠2は、評価値-10000で投了、dlshogiは、勝率1%で投了する。

eloレーティングは、水匠2のeloレーティングを0、uを勝率として、
\displaystyle
R=400 \log_{10} \frac{u}{(1-u)}
で計算する。

測定結果

思考時間(秒) 勝ち 引き分け 勝率 R
1 87 9 36.6% -95.44
2 132 7 54.2% 29.25
3 158 3 63.8% 98.44
4 165 2 66.4% 118.33

f:id:TadaoYamaoka:20200810210828p:plain

dlshogiの思考時間ごとの探索ノード数は、以下の通り。

思考時間(秒) 探索ノード数(平均) 探索ノード数(中央値)
1 71971 61518
2 140604 121388
3 207204 179994.5
4 270545 232072

考察

dlshogiの思考時間を増やすことで、強さは対数に近い形で伸びているようだ。
もう少し先の形も確認すればはっきりしそうである(8秒、16秒のデータが測定できたら追記する)。

また、測定目的とは異なるが、水匠2の1000万ノードに対して、dlshogiは10万ノード(1/100)くらいで互角になることがわかった。


αβ探索での思考時間と強さの関係

αβ探索での思考時間と強さの関係についても調べた。

対戦相手は、上記と同様に水匠2の1000万ノード固定とする。

測定側は、水匠2 2スレッドで、思考時間を1秒、2秒、3秒、4秒、8秒、16秒とした(8秒、16秒は測定中)。

測定環境は、CPU Xeon Silver 4210 (2.20GHz)を使用した。

測定結果

思考時間(秒) 勝ち 引き分け 勝率 R
1 7 10 4.8% -518.96
2 18 15 10.2% -377.87
3 26 20 14.4% -309.64
4 55 18 25.6% -185.33

f:id:TadaoYamaoka:20200810214546p:plain

水匠2の思考時間ごとの探索ノード数は、以下の通り。
※ログから集計が面倒だったので1局面だけサンプリング

思考時間(秒) 探索ノード数
1 1298863
2 2252468
3 4359210
4 5334843

考察

2スレッドで測定したため、探索ノード数が1000万ノードよりも低すぎて、右側を見ないと対数の関係なのかどうかが見れないデータになっていた。
スレッド数を8にして測定をやり直すことにする。
測定ができたら別途追記する。

まとめ

MCTSの思考時間と強さの関係は、対数の関係になりそうであることがわかった。
探索深さに対してゲーム木のサイズが指数関数的に増えることと関係していると思われる。

AlphaZeroの論文では、αβよりも思考時間に対する強さの伸びが高いことが報告されている。
f:id:TadaoYamaoka:20200810220020p:plain

同じ対数的な伸びでも、伸び方に差がでている。

αβで思考時間を延ばした場合も測定をしようとしたが、今回は測定条件のミスで使えるデータがとれなかった。
測定できたら、別途記事にしたい。