TadaoYamaokaの開発日記

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

将棋AIの進捗 その7(詰み探索の有効性)

df-pnの検証のために、詰みの局面でテストしていたが、やねうら王では詰みと出る局面で不詰みの判定になる局面があった。

調べてみると、次のような王手でない局面で、相手がどんな手を指しても次の王手で詰みとなる局面だった。
f:id:TadaoYamaoka:20170926203309p:plain

df-pnの指し手生成に王手のみという条件を入れてしまうと、こういう局面が正しく判定できなくなる。
しかし、連続王手以外を探索に含めてしまうと、df-pnの中間ノードでのpnとdnの値がほとんど無意味になってしまうので、探索空間が膨大になってしまう。

これを解決しないと、df-pnを実戦の局面で使うのは厳しそうです。

詰みの探索は、モンテカルロ木探索の末端ノードでの数手の探索のみして、ルート局面での探索はαβ+評価関数で行った方が良い気がしてきました。

ということで、実装までしておきながらdf-pnは不採用ということにしようと思います。

追記

15手で1秒はかかりすぎとTwitterでコメントを頂いたので、なのは詰めで測定してみました。

結果は、42ms。
自分の実装は、少し無駄があったので、修正しても1088msです。

なのは詰めはpnとdn以外のヒューリスティックを採用しているようなので、その差がでているようです。

42msだと末端ノードで呼び出しても良いくらいですね。

2017/9/27 追記

ループを適切に処理していないのが遅い原因の一つかと思い、ループしている数をカウントしてみました。
結果、24,523ノードでした。
全探索ノードが1,158,018だったので、連結したノード数は2%程ですが、ループしたノードの下のノードも調べることになるので、かなりの無駄が発生していると思われます。
長手詰めの性能を上げるには、ループの対処が必要そうです。

追記 必死を含めた詰み探索の必要性について

おそらくαβで探索しているプログラムの場合、必死を含めた詰み探索までする必要はないです。
モンテカルロ木探索の場合、有利な局面だと手を緩めて無駄に長い手順になることがあるので、必死を含めた詰み手順を求めたいという動機があります。

将棋AIの進捗 その6(df-pn)

前回の日記で書いた通り、df-pnの実装を行いました。

実装の参考にしたのは、以下の論文です。

上記の論文にはほぼ同じ疑似コードが掲載されていますが、ANDノードとORノードで処理を共通化しており、理解しづらかったため、ANDノードとORノードを別々の処理として記述した。

速度比較

次の15手詰めの局面で、df-pnと優先なし探索で速度を比較した。
f:id:TadaoYamaoka:20170926081954p:plain
position sfen 1n1g3+Pl/k1p1s4/1ng5p/pSP1p1pp1/1n3p3/P1K3P1P/1P7/9/L1G5L b 2R2BG2SL5Pn 161

df-pn 1,688 msec
優先なし 52,794 msec

31倍高速になった。

課題

ハッシュを利用しているが、上記の15手詰めで1,158,018ノードを使用した。
手数が増えるとノードが指数的に増えるので、ハッシュクリアの仕組みがないと長手詰めには対応できない。
また、詰みが見つからないないときに途中で打ち切る仕組みが必要。

将棋AIの進捗 その5(王手の指し手生成)

前回の日記で、Aperyに王手の指し手生成がないという話を書いたが、仕方がないので自分で実装した。

やねうら王には王手の指し手生成が実装されていたので、実装方法を参考にさせてもらった。
YaneuraOu/movegen.cpp at master · yaneurao/YaneuraOu · GitHub

やねうら王ではマクロを使っていたが、少々分かりにくかったのでマクロを使わずに実装した(その分冗長になっている)。

使用方法
for (MoveList<Check> ml(pos); !ml.end(); ++ml) {
    // ....
}

のようにして王手の指し手を生成できる。

ライブラリにAperyを使用していて、王手の指し手を生成したい方はご自由にどうぞ。

実装したコード

実装したコードは、このコミットです。
github.com
※cppshogi/init.cppとcppshogi/generateMoves.cppが主な処理

効果

詰み探索の王手の指し手生成を差し替えたところ、実行速度が約半分になった。

11手 13手
変更前(1手動かして王手をチェック) 770 msec 8402 msec
変更後(王手の指し手を生成) 429 msec 4475 msec

※終盤の複雑な局面


これでもまだ遅いので、df-pnを実装する予定。

将棋AIの進捗 その4(詰みの探索)

前回の日記で、末端ノードで詰みの探索を行う予定と書いた通り、詰みの探索をするようにしました。

ディープラーニングは詰みの探索が苦手なので、ディープラーニングと詰み探索を組み合わせるのは有効だと思っています。
Policy Network、Value Networkの計算中は、CPUが空いているので、詰み探索を行ってもNPSへの影響はないので、確実に終盤の棋力向上につながるはずです。
といっても、棋力でいえばPolicy Network、Value Networkの精度の方が重要ですが。

詰み探索の実装は、AND/OR木を使って、とりあえず優先度を考慮しないで探索しました。
かなり遅いコードですが、深さ7までは、NPSに影響でないので、採用することにします。

コードはこれ↓
https://github.com/TadaoYamaoka/DeepLearningShogi/blob/master/usi/mate.cpp

ルートノードでの詰みの探索を今までは、Aperyを使って探索していましたが、詰み探索の実装に置き換えました。
終盤局面で深さ11までは1秒以内探索できるようですが、深さ13にすると10秒くらいかかる時がありました。

長手の詰みを探索するには、df-pnなどまともな実装が必要そうです。

王手の指し手の生成も全合法手を1手動かして王手になるか調べているので、遅いです。
Aperyに王手の指し手生成があれば、それを使えたのですがどうやら実装されてないようです。
この部分を自力で実装するのは大変なのでどうしようかな・・・。

将棋AIの進捗 その3

以前の日記で、電王トーナメントに出るつもりと書いていましたが、申し込みをしました。
予選通過も厳しそうですがとりあえず頑張ります。


さて、前回からの進捗ですが、35億局面の学習が3エポック回したところで飽和しました。
一致率は、Policy Networkが46%、Value Networkが78.1%となりました。

Policy Networkは強化学習を行っているので、単純に一致率では評価できませんが、少し微妙な感じです。
入力特徴、ネットワーク構成、フィルターサイズなど変えて実験したいですが、やり直す時間もなさそうなので、一旦これで完了として他の改良に着手しようかと思います。

モデル学習が終わったので、昨晩からfloodgateに放流してみました。

f:id:TadaoYamaoka:20170917091642p:plain

レーティングは、2710となっています。

gpsfish_normal_1cと同じくらいの強さにはなっています。
同じディープラーニングを使っているShogiNetSearchには勝っているようなので、ディープラーニングモンテカルロ木探索の有用性はそれなりに示せているかと思います。

上位ソフトには全く勝てていません。
原因がどこにあるか詳細に分析をしたいと思っていますが、気づいたところでは終盤になるにつれPolicy Networkで読み漏れが発生していて、読み漏れが起きる局面ではValue Networkも正しい値をつけられていないようです。

終盤では従来の手法の方が有効そうなので、終盤は従来の手法も取り入れた方がよさそうです。

AlphaGoでも、末端局面の評価は、Value Networkとプレイアウトの平均としているので、それを参考にValue Networkと従来の手法(3手読みくらい)の平均とした場合にどうなるか次に試す予定です。
Value Networkの実行中はCPUは遊んでいるので、数手くらいであれば従来の手法で探索を行っても速度面のデメリットはありません。
Policy Networkの読み漏れ対策としては、最小選択確率を調整したり、遷移確率にノイズを付加して、読み漏れする局面も低い確率で探索させるようにする予定です。

2017/9/18 追記

末端ノードで従来手法での探索を行って平均をとるのを試してみましたが、逆に弱くなってしまいました。
浅い探索の評価値よりはValue Networkの精度の方がよいということでしょうか。
Policy Networkで読み漏れが発生する件は、ノイズを付加するとやはり弱くなってしまうようです。

素直にPolicy NetworkとValue Networkの精度を上げることを考えた方がよさそうです。

  • 効果的な入力特徴を増やす
  • ネットワーク構成、フィルターサイズなどを見直す
  • 中盤以降の学習局面の数、バリエーションを増やす
  • 深さ8よりも上げて棋譜を生成する

など。

2017/9/19 追記

Value Networkの計算中に1手詰め計算をするようにしました。
デメリットは特にないので、少しは効果がでるはずです。

できれば3手詰めにしたいけど、elmo(Apery)に3手詰めが実装されていないので、自力で実装が必要になります。
それほど難しくはないと思うので、実装する予定です。

将棋AIの進捗 その2

elmo_for_learnを使ってdepth8で35億局面の生成ができたので、DNNの学習を開始しました。

前に7.5億局面を学習したときは、4日と20.5時間かかったので、35億局面を学習するには22日15.6時間かかる見込みです。

elmo_for_learnで生成した局面には重複局面が4%程含まれるため、前処理として重複局面を削除する処理を行いました。

自作のC++ツールで、std::uniqueを使って重複を削除していますが、35億局面のファイルは合計で127GBあってメモリに乗らないため、ファイルを分割し、分割したファイル同士で重複を削除するツールを作成して処理しました。
ElmoTeacherDecoder/hcpe_uniq2 at master · TadaoYamaoka/ElmoTeacherDecoder · GitHub

DNNの学習では、学習データがシャッフルされていることが精度を上げるために重要なため、これもC++でツールを作成し、std::shuffleでシャッフルを行いました。
これもメモリに乗らないため、まずは全データのインデックス(連番)を格納した配列を用意し、それをシャッフルしたあと、インデックスを使って実際のデータを分割して処理するツールを作成しました。
ElmoTeacherDecoder/hcpe_shuffle at master · TadaoYamaoka/ElmoTeacherDecoder · GitHub

あと、初期局面のroots.hcpのバリエーションを増やすため、まふ定跡の局面とネットで集めた棋譜の初期局面を追加しています。

あとは、どれだけ精度が上がるか楽しみにして、学習が終わるのを待つだけです。

将棋AIの進捗

検証しているディープラーニングを使った将棋AIは、学習データを増やさないと精度が上げられないため、elmo_for_leanを使ってひたすら学習データを生成中です。

現在、ようやく20億局面くらい。
PCを占有されると困るので、10コアのPCを1台買ってしまいました。
仕組みを作っている間は楽しいですが、精度を上げるフェーズになるとつらいですね・・・

次の電王トーナメントに出るつもりでいますが、上位のソフトに届く可能性は低そうですが、とりあえず頑張ってみるつもりです。

大会のマシンのGPUがしょぼかったらどうにもできないので、Titan Xか1080Tiを複数枚用意してくれないかなぁ。