AobaZeroの棋譜を用いた教師あり学習

 前回、AobaZeroの棋譜を取得できるようになった。floodgateの棋譜についてもダウンロードスクリプトを整備し、実験手順を再現しやすいように仕組みをやや変えたので教師あり学習をやり直すことにした。

棋譜について

floodgateの棋譜(いつも通りの設定)

 2016年~2019年の棋譜を学習用、2015年の棋譜を検証用として利用する。学習結果は古いものを使ったので厳密にはやや異なっている部分もあるが、学習に使う棋譜はおおむね以下の条件を満たすものとなる。

  • %TORYO,%SENNICHITE,%KACHIのいずれかで終わっている
  • 手数が60手以上である
  • 対局者のレートの高い方が2800以上である(レートが不明な対局者はレート0として扱う)

 学習データ数は約31,000,000局面, 検証データ数は約2,000,000局面である。重複局面の削除等はしていない。

 ダウンロードスクリプト

AobaZeroの棋譜

 AobaZeroの棋譜もfloodgateの棋譜と同様に以下の条件でフィルタをかけた。

  • %TORYO,%SENNICHITE,%KACHIのいずれかで終わっている
  • 手数が60手以上である

 AobaZeroの棋譜にレートについての制約はかけていない。

 AobaZeroの棋譜はこの一つでおおよそ3,000,00弱程度の局面があり、今回は13300000から14300000までの101個をダウンロードしたので約300,000,000局面ほどになる。(これはfloodgate側の約10倍の量であり、今回の学習設定では1エポックも回りきらない)

 ダウンロードスクリプト

実験設定

  • OptimizerはMomentum(0.9)付きSGD
  • バッチサイズ : 512
  • 初期学習率 : 0.025
    • 200,000、300,000ステップ時点で学習率を1/10
  • 学習ステップ数 : 400,000
  • 検証損失の計算はどちらもfloodgate2015年のデータに対して実行
  • 左右反転によるデータ拡張を実行
  • 使用したモデルはCategoricalモデル

 実験設定はできるだけ揃えたつもりだったが、AobaZeroの方でのみL2正則化があり(係数1e-4)になっていた。

実験結果

floodgateの棋譜からの学習

f:id:tokumini:20200915090809p:plainf:id:tokumini:20200915090813p:plain
左:Policy損失 右:Value損失

  • Policyについて、学習損失と検証損失の乖離が小さい
  • Valueについて、検証損失は200,000ステップ以降上がっていってしまう
    • 60,548ステップで1エポックであり、3エポック目あたりから過学習

AobaZeroの棋譜からの学習

f:id:tokumini:20200915091123p:plainf:id:tokumini:20200915091126p:plain
左:Policy損失 右:Value損失

  • Policyについて、学習損失と検証損失の乖離が大きい
  • Valueについて、検証損失も下がり続ける
    • 200,000ステップまではやや振動している感じがある?
    • 学習率の設定はfloodgateと同じだが、大きすぎる?
  • Valueの学習損失の挙動が奇妙?

検証損失を比較

f:id:tokumini:20200915091517p:plainf:id:tokumini:20200915091520p:plain
左:Policy損失 右:Value損失

  • Policy損失は明らかにfloodgateの方が小さい
  • Value損失は最終的にAobaZeroの方が小さくなる

対局による比較

 Kristallweizenの4スレッド、NodesLimit200,000と対局を行った。Miacis側は1手0.25秒である。 使用したスクリプト、使用したコマンドは以下

~/Miacis/scripts/vsYaneuraOu.py --time1=250 --time2=250 --NodesLimit=200000 --game_num=250

f:id:tokumini:20200916103925p:plain

 AobaZeroが200,000ステップ以降で大きく伸びた。両者、最も良かった点を比較するとAobaZeroが380,000ステップ時点のR+13.9、floodgateが280,000ステップ時点のR-243.0なので256.9ほどの差が出たことになった。

 追加のデータとして、Miacisの強化学習で1,000,000ステップ回したものをこの条件で対局させるとR+232.3となった。AobaZeroの学習よりもさらにR+220ほど強い。

所感

 学習設定が揃っていないことに記事を書いている途中で気づいたのでどうしようか悩んだが、とりあえずこの状態で一度公開する。AobaZeroの棋譜からの学習はもっとチューニングできそうなので、整えきってからまた公平な比較ができれば。

 今後は

  • 学習率を下げる
  • AobaZeroの利用する棋譜をもっと増やす
  • Scalarモデルでの学習
  • Swish, Mishなどの活性化関数

あたりを試してみたい。

付録

 L2正則化(Weight Decay : 以下WD)の有無による差は、古いデータだったり学習率減衰の設定が異なっていたり対局結果はなかったりするが一応損失推移のデータはあったので載せておく。

floodgate

f:id:tokumini:20200916110356p:plainf:id:tokumini:20200916110400p:plain
左:Policy損失 右:Value損失

 明らかにWDありの方がValue損失が小さくなっている。こちらで検証対局をするべきだった。4ヶ月以上前に行った実験なので、現在の設定でやり直して対局までやってみたい。

AobaZero

f:id:tokumini:20200916110609p:plainf:id:tokumini:20200916110613p:plain
左:Policy損失 右:Value損失

 これは最近取ったデータであり、これでWDありの方がやや良かったのでAobaZeroの検証対局はWDありの方でやってしまった。損失から見るとWDなしでもそこまで大きな差があるわけではないように感じられるが……。

 気になる点としては、WDなしの場合でもValueの学習損失が学習率を下げた200,000ステップ以降で上昇傾向にあることであり、これがどういう理由で起こっていることなのかよくわからない。

WDあり同士での比較

f:id:tokumini:20200916112029p:plainf:id:tokumini:20200916112033p:plain
左:Policy損失 右:Value損失

 これで見るとほとんど差はないかもしれない。しかしこうして見てもAobaZeroの棋譜を用いたときのValue学習損失の挙動が気になる。

 自分が想像していた以上にL2正則化が強力なのではないかと感じてきた。強化学習へ導入したときは学習序盤であまり効果がないと打ち切ってしまっておりL2正則化に対する信頼感がなかったのだが、学習率を下げた後半で強く効いてくるとしたら話は変わってくる。強化学習の方でも追加でやってみるべきかもしれない。

MCTSNetの学習結果(Simulation Policyの廃止)

 以下の続き。

 前回はMCTSNetの学習式に従って実験したが、結果は振るわなかった。学習の挙動などを見ていて、個人的な印象としてはSimulation Policyを方策勾配法のような形で学習していくのは難しいように感じている。

 具体的な要因としては、特に学習序盤でSimulation Policyが変に学習されてしまうと考えている。Simulation Policyは0回目からm回目までの探索で損失が改善した量を報酬として学習するわけだが、学習序盤では損失値はたいてい次のようになる。(以下は実際の学習で得られた値)

0回後 1回後 2回後 3回後 4回後 5回後 6回後 7回後 8回後 9回後 10回後
1.862 1.911 2.014 2.197 2.435 2.735 3.104 3.492 3.783 3.983 4.137

 Policyを事前学習しているので0回後の損失値はそこそこ良いものになっている一方で、Backupネットワークは事前学習できないので探索すればするほど損失値は悪くなる。つまり序盤ではどんな探索行動を取っていても悪化するというシグナルしか与えられない。

 方策勾配法が必要になるのはSimulation Policyを学習させるためだが、つまりSimulation Policyなんてものがなければ妙なことはしなくて済む。探索中に用いるSimulation Policyと最終決定で用いるReadout Policyが異なるというのは納得できる話なのだが、実践的に学習を安定化させるためには両者に同一のものを使ってしまうのが良いと考えた。

 まとめると改善案として次の2つの工夫を加えた。

  • Simulation PolicyとReadout Policyに同じパラメータを用いる
  • 学習方法を0回目からm回目までの各探索後のReadout結果と教師の交差エントロピーのみに変更する

実験

  1. 教師あり学習でEmbedネットワークおよびPolicyネットワークを事前学習
  2. Backupネットワークを追加して学習(このときEmbedネットワークは凍結する)

という手順で実験を行った。将棋ではfloodgateの棋譜を用い、オセロでは以前山岡さんが記事に書いていたサイトの棋譜を利用した。

将棋

 検証損失の推移は以下のようになった。

f:id:tokumini:20200914103128p:plain

 6万ステップを超えたタイミングで学習率を1/10にしており、そこからの減少で本当に少しだけ損失が改善するようになった。

 一番最後の検証損失は横軸に探索回数を取ってプロットすると次のようになっている。

f:id:tokumini:20200914103113p:plain

 3回目までは下がっていき、それ以降は上がってしまっている。

 MCTSNetの学習により0回目の損失値がやや悪化しているのだが、事前学習での検証損失は1.877444であるのに対して3回目での損失値は1.877302なので一応小さいことは小さい。しかし誤差レベルか。

オセロ

 検証損失の推移は以下のようになった。

f:id:tokumini:20200914103039p:plain

 オセロの方が学習が上手くいっている。3万ステップを超えたタイミングで学習率を1/10にしてからかなり差が出た。

 一番最後の検証損失は横軸に探索回数を取ってプロットすると次のようになっている。

f:id:tokumini:20200914103252p:plain

 とても綺麗な形で右肩下がりになっている。疑わしいくらいに理想的な結果だ。

 事前学習との比較では、オセロでの事前学習の検証損失は0.853867なのでそもそも0回後の時点で改善がされている。事前学習のチューニングが甘く、収束しきっていない状態からMCTSNetの学習を始めてしまっているかもしれない。

まとめ

 将棋では微妙だがオセロでは効果がありそうだという結果が得られた。以前も少し考察した通り、10回程度の探索が有効に機能するシーンが多そうなのは将棋よりもオセロのように感じている。将棋でも大駒をタダで捨ててしまう局面などでは有効かもしれないが、全体から見てそういう局面があまり多くないのではないか。オセロは最終盤でほぼ毎回有効に機能すると思われる。

 上手くいったとはいえ今回の手法はかなりMCTSNetの主張を無視しているのでこれで再現できたと言い張ってよいものかどうか。むしろこれで上手くいくならなぜMCTSNetはSimulation Policyを導入して複雑化したのだろうという気にもなるが、Simulation Policyを用いてランダムプレイアウトする由緒正しいMCTSの影響が強かったということなのだろうか。

 今後はオセロで実際に対局してみて性能が上がっているかどうかの検証や、どういう局面で損失が改善されているかなどの分析を行っていきたい。

AobaZeroの棋譜をコマンドラインからダウンロードする

 ありがたいことにAobaZeroの学習データはGoogleドライブで公開されている。

 Dockerコンテナ内などコマンドラインしか使えない環境でもダウンロードできるようにシェルスクリプトを作成した。

最終的なシェルスクリプト

これと同階層にAobaZero_kifuID.csvを置いて実行するとTHRESHOLD以降のファイルをダウンロードして適当な場所にダウンロードして解凍する。

メモ

 Googleドライブで公開されているファイルをcurlで取得する方法は以下を参考にした。

 また上記の手法には各ファイルのIDが必要になるのでそれの一覧を取得するために、Google スプレッドシートの関数を用いた。

 これで取得してcsvファイルで出力した。csvファイルをもとにいくらかの棋譜をダウンロードするシェルスクリプトを作った。文字列の加工については以下を参考にした。

事前学習を含めたMCTSNetの学習結果

 以下の続き。

 前回はエンコーダ部分(MCTSNetのEmbedネットワーク)だけ事前学習したものを用いた。結果的に0回探索でも事前学習より悪い損失に留まり、また探索回数を増やしたときに性能向上しなかった。対策案として今回は次の2点について修正を行った。

  • 勾配計算をMCTSNetの論文が主張する通りのものに修正した
  • 事前学習したネットワークのヘッド部分もMCTSNetのSimulationネットワークおよびReadoutネットワークの初期値として用いることにした

実験結果

学習損失

f:id:tokumini:20200902195811p:plain

 点線(損失2付近に収束しているもの)が10回探索後の推論結果(MCTSNetの勾配第一項)であり、その他各探索が損失低下に寄与した程度とその状態に至る確率の積(MCTSNetの勾配第二項)である。

 10回探索後の損失値が順調に減っていることは良いが、第二項の方は0最初に0になってからほとんど変わっていないのは良くないかもしれない。が、よく考えれば第二項は符号反転しているため負になることが望ましいが、値としてはそこまで大きくなり得るわけではないので0付近であることは仕方ないか。

 簡単に計算してみると、0回探索から10回探索をしたところで、大きく見積もってもPolicy損失の低下は0.5程度が関の山かと思われる。そしてそこへその状態へ至る確率がかけられるので、よっぽどPolicyが偏る局面でない限りこれの1/10としても約0.05程度となるので-0.05が理想的な値だろうか。

検証損失

f:id:tokumini:20200902200205p:plain

 残念ながら結果としては0回探索が常に一番下にあり、探索による性能向上は見られなかった。0回探索のものも徐々に損失値が悪化している点は気になる。事前学習の最終ステップでは1.877444だった損失値が、最終的には1.901313になってしまった。

3Mステップ時点での検証損失

f:id:tokumini:20200902194858p:plain

 わかりやすいように最終ステップでの検証損失を抜き出してプロットすると上のようになる。綺麗に右肩上がりとなっており、理想とは程遠い。

対局による検証

 損失の値が悪くともひょっとすると強くなっている可能性があるかもしれないため、実際に対局させることで性能の比較を行った。学習済みの同じパラメータを用いて、探索回数0回でReadout Policyに従って指すモデルと、探索回数10回でReadout Policyに従って指すモデルで1000局の対局を行った。序盤30手以内ではPolicyのSoftmaxに従う確率で指し、それ以降は最も確率が高い行動を選択するようにした。

 結果は10回探索側から見て

勝数 引分数 負数 勝率 Eloレート差
364 8 628 36.8% -93.9

であった。損失値の悪化通り、対局でも性能が落ちていることがわかった。

今後

 要するに現状はMCTSNetの再現がさっぱりできていない。実装ミスや理解の勘違いを含めもう一度見直して、とりあえずまず再現できることを確認しなくては始まらない。

 MCTSNetの元論文は一人ゲームで実験しており、二人ゲームに適用する上で視点が反転する(評価値で言えば符号が反転する)という事象が起こることで何か不具合が起きていないか気になる。Backupネットワークは全結合なので影響は考慮できると思っているし、Backupネットワークには常に(手番が自分の局面の表現, 次の相手が手番の局面の表現)という順番になっているのでそこでも悪影響はでないと考えているが……。なにか見落としているかもしれない。

エンコーダを凍結した探索系NNの学習結果

 以下の続き。

 前回の学習の反省としてエンコーダ側を事前学習し、凍結することにした。事前学習でのPolicy損失は1.85であった。

実験結果

全体の結果

 前回に比べて値が安定するようになり、MCTSnetはかなり低い値まで下がっていった。しかし単純な探索なしである事前学習よりも損失が高い値で留まっているため、探索が有効に機能しているわけではないことがわかる。

 提案手法とStacked LSTMはあまり値が下がらず、なんらかのミスを感じる。

MCTSnet

 学習初期こそ探索回数に応じて損失値が小さくなってはいるが、学習が進むとほとんど差がなくなってしまっている。

提案手法

 1,2回目よりは3回目以降のほうが損失値が小さくなっているが、7回を超えたあたりからまた上がり始めてしまっている。

Stacked LSTM

 提案手法とだいたい同じ傾向にある。

考察

 簡便さや統一性のため学習方法として「10回の探索(MCTSnetの場合はシミュレーション)を行い、各回の探索後にReadout方策を計算してそれと正解ラベルから交差エントロピーを算出し、最小化」という方法を取っているのだが、よく考えるとこれではReadout方策のみが学習可能でSimulation方策は勾配が流れてきていなさそうであることに気づいた。なのでどの手法もSimulationがほぼランダムに行われている状態のようなものに思われる。

 サボらずにMCTSnetの学習手法をちゃんと模倣するべきだが、そうなると少なくともStacked LSTMには同じ手法が使えないので平等な比較というのは難しくなる。とりあえず提案手法は同じ手法で学習できるはずなのでその2者での比較になるだろうか。もう少しMCTSnetの学習に対して理解を詰めてから実装パートへ向かう予定。

囲碁のルールについてのメモ

 Miacisをコンピュータ囲碁にも対応させようかと思って調べてみているが、意外と詰まるところが多そうだ。やっぱりあまり知らないゲームの実装は難しい。とりあえずここまでの考えをメモしておく。

プロトコル

 基本的にはGo Text Protocolに対応していれば良いのだろうか。

 まだちゃんと把握しているわけではないが、ボードサイズを可変にできるようにしないといけないとしたら少し実装を考えないといけないかもしれない。

ルール

 ルールがとにかく大変。プログラム的に実装しやすいのは中国ルールだと聞いたことがある気がするので「囲碁 中国ルール」などで調べてみたが、それでも問題が全くないわけではなさそう。

 というかそもそも終局判定が難しく、「パスが2回続いたら終了」が基本路線になるのだろうか。ただ気になるのは、自分の眼を潰すような手もルール上非合法手ではないとしたら、「パス = 合法手0」ではなくなる。自分の眼に打つと二眼がなくなるので相手に取られるようになり、でも相手もまたいずれ二眼を自ら潰すので……ということで合法手からランダムに選択するエージェント同士では何手やっていても合法手が0にならなさそう。

 コンピュータ将棋が基本的に歩とか香車の不成を生成しないのと同じようなノリで自分の眼には打つ手は生成しないということにするのだろうか。そうなると合法手生成自体にいくらか思考が混じっているような感じがして少し心地悪い感じがある。実際に自分の眼に打つことがときに有効手となったりしないのかどうか、囲碁に詳しくないのでさっぱりわからない。

 とりあえず

  1. 自分の眼には置かないという条件で合法手生成をして、その合法手が0だった場合のみにパスをする
  2. パスが連続したら終局とし、中国ルールで勝敗を計算する

という基準でなら想像する限りなんとかなりそうではある。当面はこれを実装予定。

 余談だが、仮にこれが正しいとすると、合法手がなくなるまで打つエージェント同士の対局の最後は、自分の陣地に打ち合うようなあまり勝敗に影響しない手が多くなりそうではある。AlphaZeroが自己対局において勝率予測95%だかなんだかで投了(自己対局の5%では予測が合っているか確認するために最後まで打つ)みたいな処理をしていたのはそういう理由があったからなのかなと思ったりした。将棋では入玉形にでもならない限り正直そういうことをする意義があまりない気がする(実際にMiacisでは簡単な詰み探索を入れつつ最後まで指すようにしている)。

 さらに余談。全くのゼロから強化学習をすることを想定すると、「合法手からランダムに選択するエージェント同士の対局が終わらない」ようなゲームは鬼門だったりするんだろうか。適当な手数で打ち切るとしても、途中局面での勝敗が決定できないとするとまともな報酬を得るのが難しそう。報酬が疎であるような環境の一種と言えばそれだけのことではあるのかもしれないが。

探索系NNの学習結果

 とりあえず試しで回した学習が一通り終わったので結果をまとめる。

実験設定

 将棋での教師あり学習でモデルの学習を行い、Policy損失を比較した。

比較手法

  1. 探索なしの全結合ネットワーク
  2. MCTSnet
  3. 提案手法
  4. Stacked LSTM(Deep Repeated ConvLSTMを意識したもの)

各手法の詳細

前提

 4つの手法はどれも同じアーキテクチャの状態エンコーダを用いる。これは3つの残差ブロックの(6層CNN)からなり、将棋の盤面を 32 \times 9 \times 9 = 2592次元の表現ベクトルへと変換する。

1.探索なしの全結合ネットワーク

 先のエンコーダによって得られた表現ベクトルを全結合層に入力し、 27 * 9 * 9 = 2187次元で表される行動について方策を得る。

2.MCTSnet

 先のエンコーダによって得られた表現ベクトルをMCTSnetにおけるEmbedネットワークとして利用し、それ以降はMCTSnetの動作に従う。

3.提案手法

 先のエンコーダによって得られた表現ベクトルをLSTMに対する入力とし、そこから探索方策用LSTMを用いて方策を出力し、最大の確率を持つ行動を選択し、次の状態に移る。ここで探索方策は一局面戻るという行動も付け加えており、2188次元の出力を持つ。

 最終的に得られた表現ベクトルの系列全体を最終決定用LSTMに全て入力し、実際に取るべき行動を選択する。ここでは一局面戻るという選択肢はないため出力は2187次元となる。

4.Stacked LSTM

 先のエンコーダによって得られた表現ベクトルを最初だけLSTMに入力し、以降は方策RNNと遷移モデルRNNと見なす2つのLSTMによってLSTMの推論のみで探索のようなことを行う。

 厳密にはDeep Repeated ConvLSTMとは違うところが多いが、探索という行為をLSTMに全て任せるということを試すために比較手法として採用した。

学習方法

探索なしの全結合ネットワーク

 単純にネットワークが出力した方策と正解ラベルから交差エントロピーを算出し最小化

MCTSnet、提案手法、Stacked LSTM

 10回の探索(MCTSnetの場合はシミュレーション)を行い、各回の探索後にReadout方策を計算してそれと正解ラベルから交差エントロピーを算出し、最小化

 MCTSnetの正しい学習方法とは異なるが、学習条件を平等に揃えることを重視した。

実験結果

全体の結果

 simple mlpの性能が妙に低くて違和感がある。やはりバッチサイズ1だと性能が悪くなってしまうのだろうか。また他のネットワークは同じ局面を10回の探索分学習しているので、擬似的に10倍の学習をしているとも考えられる。

 学習は全て3Mステップで統一したが、横軸をかかった時間でプロットすると次のようになる。

 時間で見ればsimple mlpも悪くはないのでやはり学習量の問題なのかもしれない。

個別の結果

MCTSNet

 シミュレーション回数が1回だろうが10回だろうがほとんど損失の値が変わらない。

提案手法

 探索回数(遷移回数)が増えるとむしろ性能が落ちる。全然ダメ。

Stacked LSTM

 探索回数(遷移回数)が1回よりは2回以上のほうが良くなっているところがあるが、探索回数が多くなればなるほど下がるという傾向は見られない。

結論

 全体的にそもそも学習があまり上手くいっていない感じがあった。バッチサイズ1というのが難しいのかもしれない。学習のバッチ化は各手法でそれぞれ個別に実装しなければいけなさそうなので実装量が重い気がしている。次はとりあえずBatch Norm以外のものを試してみる予定。

 またエンコーダ部分は事前学習してフリーズさせるのも再検討してみたい。表現ベクトルの次元数も、32chなので小さいように思えるがこれにボードサイズの9×9がかかると意外と大きくなるということに気がついていなかったのでこのあたりも変えてみるか。

128チャンネルで1ヶ月学習(2回目)

 5月の世界コンピュータ将棋オンライン大会が終わってから、実験サイクルを早めるため学習は64チャンネルのネットワークで行っていた。しかしlibtorch1.5.0版に対応した影響で後方互換性がなくなり、すぐ動かせる強いパラメータが手元ないと細かい動作の検証で困るため、128チャンネルのネットワークで1ヶ月の学習をやり直した。

実験

 ほぼMiacisのWCSOC2020版

と同じ内容で実験を行ったが、「学習スレッドのスリープ時間と学習速度の関係」から生成量2倍で学習ステップ数1/2にしてもほぼ変わらないという結果を得ており、それを追試も兼ねてそこ(と学習率の減衰)についてだけ変更を行った。

変更のある項目 今回 前回
生成量 1ステップあたり256局面 1ステップあたり128局面
学習ステップ数 1M 2M
学習率 学習の80%経過時点で1/10 学習の50%経過時点、75%経過時点で1/10

学習結果

 横軸に学習時間、縦軸にfloodgate棋譜を用いた検証損失を取りプロットすると次のようになった。

f:id:tokumini:20200727100602p:plainf:id:tokumini:20200727100604p:plain
左:Policy損失 右:Value損失

 今回の学習の方が進みが良く、前回の学習の学習率減衰が起きた後と同じくらいの損失値を学習率減衰が起こる前で実現できていた。

 横軸を学習ステップ数にして比較した結果も載せておく。

f:id:tokumini:20200727102916p:plainf:id:tokumini:20200727102920p:plain
左:Policy損失 右:Value損失

 最終的な学習時間は649時間28分(≒27日)であった。前回の672時間32分より約一日短くなったが、これは学習ステップ数が少なくなった影響である。

 最終ステップでの損失は具体的には

手法 Policy損失 Value損失
今回 1.897591 0.672531
前回 1.923749 0.677997
差分 -0.026158 -0.005466

となった。以前の検証ではEloレートと損失の間に線形な関係を仮定すると係数はPolicy:-2135、Value:-8649と算出され、今回の結果と合わせるとPolicy損失の差分から計算すると55.8、Value損失の差分から計算すると47.3のEloレート向上が予想できる。

対局結果

 Miacis(1手1秒)とYaneuraOu/Kristallweizen(1手0.2秒、4Thread、定跡オフ)で対局を行った。

手法 勝数 引分数 負数 勝率 相対Eloレート
前回 317 0 183 63.4% 95.4
今回 697 2 301 69.8% 145.5

 約Eloレート50の伸びであり、ほぼ想定通りといったところ。

 YaneuraOu/Kristallweizenは持ち時間を増やしていくとかなり強くなる印象なのでなかなか同条件で互角というところまではまだ遠そうだが、また少しは近づいたか。

MCTSnetの学習(仮)

 MCTSnetのだいたいの実装が終わり、将棋での教師あり学習を回し始めている。

 簡単に回してみたところ、Backupネットワークでの振る舞いが上手くいっていないように思えたので、論文の3.4 Design choicesに記載されているように、Backupネットワークをゲート付きの差分更新にして学習を行った。

f:id:tokumini:20200723101650p:plain

実験

 floodgateの2016年〜2019年の棋譜を用いて、棋譜で指された行動をOnehotの教師信号として交差エントロピーで損失を計算した。MCTSnetの正しい学習方法は以前記事に書いた通りだが、今回はとりあえず簡便のため、 M = 10回の探索まで都度ルートノードからReadoutを行い、教師と比較して損失を計算したものの和


\displaystyle
\sum _ {m = 1} ^ {M} l _ m

という単純な損失について学習を行った。

結果

f:id:tokumini:20200723095000p:plainf:id:tokumini:20200723095015p:plain
左:学習損失 右:検証損失

 図には1回探索後から10回探索後まで10本の学習曲線があるわけだが、それらがほぼ全て重なるような形になっている。学習が安定したようにも見えるが、Backupネットワークにゲートを追加した結果ゲートが常にOFFになるよう学習され、探索によってルートノードの埋め込みベクトルが全く更新されなくなっただけの可能性もある。

 ちなみにこのPolicy検証損失値が4.0付近という値は非常に悪い。今までのAlphaZeroモデル(10ブロック128チャンネル)などでほぼ同じデータに対して検証損失を計算すると、教師あり学習の場合なら1.5、強化学習の場合でも1.9ほどまでは落ちる。精度が低い原因としては

  • 埋め込みネットワークが3ブロック64チャンネルと小さい
  • バッチサイズ1なのでBatch Normalizationが機能していない
  • そもそも学習もやや足りていない

などが考えられる。どれも基本的にどうしようもない問題なので改善は難しいかもしれない。ネットワークは大きくしたくないし、バッチサイズ複数に対応するのもあまり現実的ではないように思える(MCTSのパスの長さが都度異なるのでどう実装すれば良いのかわからない)。今回の学習量でもかかった時間は2080tiのマシンで14時間ほどで、バッチサイズが1なのでどうしても学習速度は高くならない。

 そもそも探索回数10程度で将棋ではっきり強くなるかはやや疑問であり、どちらかというとオセロの終盤での評価がまともになる可能性を感じているため、オセロでどうにか棋譜を探して教師あり学習をやるというのが現実的な線だろうか。

時系列モデルが木構造を学習できることの検証

 前回の考察では、時系列モデルが暗黙のうちに木構造を学習できるので木の遷移履歴を時系列展開しても良いという仮説を立てた。この仮説を多少なりとも検証するため、今回は木に関する簡単なタスクを考えて、それが学習可能かどうかを実験により確かめた。

実験

 タスク概要:「木についての深さ優先探索での訪問順が与えられるので、幅優先探索での訪問順を出力せよ」

具体的なデータ生成手順

  1.  N頂点の木をランダムに生成する
  2. 生成した木についてランダムに根を決定
  3. 根から深さ優先探索を行い、訪問順を記録(これを時系列モデルへの入力とする)
  4. 根から幅優先探索を行い、訪問順を記録(これを正答とする)

f:id:tokumini:20200708111225p:plain

細かい点

  • DFSでは戻る際の訪問も記録しているので、系列から完全に木を復元可能(だと思う)
  • BFSにおける同じ深さでの優先度はDFSで先に探索された順と同じとする
  • ノードを入力する際はOnehotベクトルの形式にして入力
  •  N頂点の木から得られるDFSの系列(入力)は 2N - 1

実装

実験結果

頂点数 N = 6

f:id:tokumini:20200708111650p:plain

 単純なLSTMおよび以前実装したDNCのいずれにおいても50000データほど学習させると正答率(BFS順を完全一致で出力できた割合)が100%になった。 N = 6という小さい木ではあるが、訪問順を詳細に記録しておけば木構造を認識することはできていそうである。

頂点数 N = 20, 50

 LSTMについて N = 20, 50として実験を行った。

f:id:tokumini:20200710135415p:plain

 20ノード, 50ノードのものはバッチ学習として1ステップ32データにしているので、データ数としては5 * 32 = 160万データとなる。それだけ学習させると20ノードのとき正答率93.7%、50ノードのとき正答率8.0%となった。

頂点数 N = 50 その2

 50頂点くらいはなんとか学習してほしかったので、GPUを使うようにプログラムを変更してバッチサイズを256、学習ステップ数を20万(計データ数は5億程度)にして再度実験を行った。

f:id:tokumini:20200711101243p:plain

 最初は隠れ層の次元数512(青線)でやったところ正答率60%程度で頭打ちになり最後は突然nanになって崩壊してしまった。1024(赤線)でやり直したが、学習は遅いうえ損失も(nanではないが)爆発して正答率が崩壊するのは同様だった。LSTMで記憶容量を超えるとこういう感じで崩壊してしまうものなのだろうか。

雑記

 特に工夫していない1層のLSTMではそこまで長い系列(大きい木)は扱えないかもしれない。DNCをバッチ学習に対応させて可能性があるかどうか、あるいは違う系列モデルを実装するか。 N = 50だと入力系列の長さは 99であり、自然言語処理で考えて99単語からなる文となると長めではあるか。

 一方で30頂点くらいでもちゃんと探索できれば探索なしよりは強くなるんじゃないかという気もする。この記事でやっている実験は実際のゲーム木探索での状況とはやや異なるので、これの性能を追い求めていてもなぁとも思うところ。MCTSnetも実装するべきことを考えると結構実装が重たいので早めに実際の利用環境で試してみたいという気持ちはある。どちらの方針を取るにしてもとにかく実装を進めねば。