TadaoYamaokaの開発日記

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

dlshogiのバグ報告

電王トーナメントバージョンを公開しましたが、致命的なバグがありました。

移動を表すラベルにバグがあり、いくつかの異なるラベルが同じラベルに割り振られていました。
このバグのため学習の精度がかなり落ちていたと思われます。

モデルの学習からやり直しが必要になるのでバイナリ公開は、電王トーナメントのままとします。
ソースを参考にしたい方は、masterのソースを参考にしてください。

バグ修正箇所

github.com

将棋でディープラーニングする その45(高速化)

現在のdlshogiの実装では、NPSが2500程度しかでていないため、高速化できる箇所がないかを検討している。

モンテカルロ木探索でpolicyとvalueGPUで計算すると、GPUの実行時間が処理時間のほとんどを占めているため、CPUの論理コア数以上のスレッドで並列に探索を行い、policyとvalueの計算要求をキューにためて、GPUは繰り返し溜まったキューをバッチ処理している。
dlshogiのモンテカルロ木探索の実装では、1つのスレッドはGPUに計算要求したら計算が終わるの待つため、ほとんどの時間CPUは遊んでいる状態になる。

開始局面で探索したときのGPUのバッチサイズを調べたところ、スレッド数36の設定の場合、平均で22.4 となっていた。
GPUは並列計算が可能なためバッチサイズが増えてもGPUの計算時間は変わらないため、バッチサイズは、スレッド数36と同じになっている方が効率がよい。
そこで、GPUの処理開始時に溜まっているキューのサイズが閾値未満の場合、1回だけ1msスリープする処理を入れてみた。

測定結果

閾値 平均キューサイ NPS
なし 22.4 2522
スレッド数×0.5 25.3 2680
スレッド数×0.6 30.9 3201
スレッド数×0.7 35.2 3286
スレッド数×0.8 35.6 3333
スレッド数×0.9 35.8 3458
スレッド数 35.7 3314

閾値をスレッド数×0.9にしたときに、平均キューサイズが35.8とほぼスレッド数と同じになった。
NPSは、閾値なしの1.37倍になった。

閾値なしだと論理スレッド数は36が最適だったが、閾値ありだと論理スレッド数をさらに増やせる可能性があるので、調整を行う予定。

2017/11/14 追記

スレッド数の調整を行った結果、スレッド数を128にしたときに、NPSが7027、平均キューサイズが119.5となった。
それ以上スレッド数を増やすと、NPSが低下した。
CPU使用率を見ると100%になっていたが、スレッド36で確認しても100%だった。
GPUの計算をスピンロックで待機しているためと思われる。
CPU使用率からは、はっきりわからなかったが、NPSがピークになっていることから、CPUが効率的に働いている状態になっていると思われる。
NPSは元の状態から、2.78倍になった。

NPSが上がっても、Root並列化の特性から、そのまま線形に強さにつながるわけではない。
どれだけ強さに影響があるか、GPSFishと1手3秒で10局ほど対局させてみたが、勝率は効率化前と変わらなかった(勝率4割)。
やはりDNNの予測精度が上がらないと高速化では強くするのは難しそうだ。

それでも自己対局で強化学習を行うことを計画しているので、できるだけ高速化はしておきたい。

dlshogiのビルド済みファイル公開

dlshogiの第5回将棋電王トーナメントバージョンのビルド済みファイルを公開しました。

elmoで生成した35.8億局面を学習済みモデルと、モンテカルロ木探索で事前探索した定跡も含んでいます。

CUDA、Pythonの環境構築が必要になるので、なるだけ丁寧に説明を記述しました。
この手順で実行できない場合は、ご連絡いただければ対応します。

Release 第5回将棋電王トーナメントバージョン · TadaoYamaoka/DeepLearningShogi · GitHub

第5回将棋電王トーナメント 出場結果

第5回将棋電王トーナメントに参加しました。

本日は予選が行われ、dlshogiは3勝5敗という結果で、予選落ちとなりました。
3回戦と6回戦は、秒読みに入ってから将棋所のinfo stringの出力に時間がかかり、優勢にかかわらず時間切れ負けとなってしまうという残念な結果でした。

infor stringはバッファリングされずに出力仕切るまで処理を返さないという仕様になっており、探索時間の制御は正しかったにも関わらずinfo stringの出力に5秒以上かかって時間切れを起こしていました。
info stringの表示が遅いのは認識していましたが、バッファリングして出力しているだろうと思い込んでいました。
テスト不足でしたorz

まあその問題がなくても、実力的に予選通過はほぼ無理でしたので、次回にチャレンジしたいと思います。


参加して他の開発者の方と意見を交わすことができて楽しい一日を過ごすことができました。
明日も観戦のため現地には行こうと思っています。


info stringの出力を抑止したバージョンを公開しました。
近々ライブラリ登録する予定です。
github.com

将棋でディープラーニングする その44(L2正則化)

将棋AIのPolicy NetworkとValue Networkのマルチタスク学習でのL2正則化の効果を測定してみた。

正則化なし

loss

f:id:TadaoYamaoka:20171108225146p:plain

policy accuracy

f:id:TadaoYamaoka:20171108225221p:plain

value accuracy

f:id:TadaoYamaoka:20171108225349p:plain

L2正則化係数10^{-4}

loss

f:id:TadaoYamaoka:20171108224557p:plain

policy accuracy

f:id:TadaoYamaoka:20171108224625p:plain

value accuracy

f:id:TadaoYamaoka:20171108225416p:plain

考察

正則化なしでも、trainとlossにそれほど差がないが、L2正則化を行うとtrainとtestの差が縮まっている。
その代わりに、policy、vlaueともに2%くらい一致率が下がっている。

この結果から汎化が行われていると考えらるが、一致率が下がった分で実際の対局でプラスに働くかは検証が必要そうだ。

AlphaGo Zeroのように自己対局のみで学習する場合は、局面の偏りが心配なのでL2正則化は行った方がよいだろう。


なお、L2正則化係数を10^{-6}にした場合は、正則化なしとほぼ同じグラフになった。
正則化の効果を得るには、L2正則化係数10^{-4}くらいが適している。

将棋でディープラーニングする その43(ValueNetの出力をtanhにする2)

前回Value Networkの出力をtanhにした場合とsigmoidにした場合で比較を行ったが、マルチタスク学習を行っているため、はっきりした結果がわからなかった。

今回は、Value Networkのみの学習で比較を行った。
以下の2パターンで比較した。

出力関数 損失関数
1 tanh 平均二乗誤差(MSE)
2 sigmoid 交差エントロピー

tanhとsigmoidの比較

測定条件
  • 5ブロックのWide ResNet
  • 訓練データ:7000万局面
  • テストデータ:100万局面
  • 1000万局面ごとに評価
  • 学習率:0.001
  • 最適化:SGD
  • ミニバッチサイズ:64
average train loss

f:id:TadaoYamaoka:20171108205522p:plain

test loss

f:id:TadaoYamaoka:20171108205552p:plain

test accuracy

f:id:TadaoYamaoka:20171108205618p:plain

考察

train lossはスケールが違うため比較できない。どちらも減少している。
test lossはtanhは1000万局面でほぼ減少が止まっている。
sigmoidはわずかに減少している。
test accuracyは、tanhの方が一致率が高い。

以上の結果から、tanhの方が学習効率が高いと言えそうだ。

前回と今回の実験結果からtanhの方が良さそうなので、Value Networkの出力はtanhに変更することにする。


なお、1000局面でtest lossがほぼ下げ止まっているのは、elmo_for_learnでの局面生成時に初期局面(1000万局面くらい)から数手のランダムムーブを行っているとは言え、似たような局面が大量に生成されているためと思われる。
AlphaGoでもValue Networkの学習には1ゲームから1局面しか使っていないので、Value Networkの汎化性能を上げるには、局面のバリエーションがもっと必要と思われる。
AlphaGo Zeroでは、自己対局のみで学習しているので、局面が偏りそうだが実際に強くなっているので不思議な気がしている。AlphaGo ZeroでL2正則化を行っているのは、それが理由かもしれない。
将棋でAlphaGo Zeroと同じように自己対局のみで学習した場合にもうまくいくのかはやってみないとわからない。

tanh vs sigmoid

AlphaGoのValue Networkの出力にはtanhが使用されている。
一方、将棋AIでは評価関数から勝率に変換する際、sigmoidが使われている。

tanhとsigmoidのどちらがよいか、dlshogiの学習で検証してみたが、Policy NetworkとValue Networkのマルチタスク学習を行っているためはっきりした結果が得られなかった。

そこで、MNISTのデータセットで多層パーセプトロンを学習するというシンプルなケースで比較を行ってみた。

MNISTは0から9の数値分類のデータセットだが、tanhとsigmoidを比較するため、偶数か奇数かの2値分類を行う。

以下の3パターンで比較を行う。

出力関数 損失関数
1 tanh 平均二乗誤差(MSE)
2 sigmoid 交差エントロピー
3 sigmoid 平均二乗誤差(MSE)

比較結果

測定条件
average train loss

f:id:TadaoYamaoka:20171107213115p:plain

test loss

f:id:TadaoYamaoka:20171107213131p:plain

test accuracy

f:id:TadaoYamaoka:20171107213207p:plain

考察

train lossは、それぞれスケールが異なるため大小では比較できないが、sigmoid+MSEは、lossの減少が他に比べて遅い。
test accuracyは、tanhが最も高くなっている。

このことから、MNISTの多層パーセプトロンによる2値分類では、tanh+MSEが最も効率よく学習できることがわかった。
また、出力関数がsigmoidならば、損失関数は平均二乗誤差より交差エントロピーにした方が良い。

他のデータセットや、深層畳み込みニューラルネットワークでも同じ傾向かは実験してみないとわからない。

検証に使用したソース

github.com