従来手法に基づくプロの棋譜を用いない評価関数の学習

先日、elmo絞りを用いればプロの棋譜から学習をスタートさせなくともプロレベルの将棋ソフトになることを実証したが、実はelmo絞りを用いず、従来手法でも同じことが出来ることをここに手短に示す。

elmo式で、lambda = 0とした場合、プレイアウト時の勝敗しか考慮しない。このとき次式になる。

grad = winning_rate(eval) – teacher

teacher : その局面からの期待勝率。その局面の手番側が最終的に勝っているなら1、負けているなら0である。
eval : その局面での評価値。正確に言うとqsearch(静止探索)をした値。
winning_rate : evalの値を勝率に変換する関数。シグモイド関数を用いている。

これをSGDやAdaGradなどの更新式で用いる勾配とする。強化学習の教科書なんかにもよく載っているオーソドックスな手法である。

やねうら王を用いて、これをやってみる。
以下では追試が楽なように、極めて緩い条件で行なう。

やねうら王の現時点での最新のcommitを用いる。これより古いバージョンでも新しいバージョンでもここに書いているのとは異なる挙動である可能性がある。

Step 1.
リゼロ評価関数epoch0をevalフォルダにぶち込む。やねうら王のGitHubからダウンロード出来る。これはゼロベクトルの評価関数である。

Step 2.
これをもとに教師局面をdepth 3で1億局面生成する。(40c80tで20分。4c8tでも5時間程度)

> gensfen depth 3 eval_limit 32000 loop 100000000

Step 3.

生成した教師局面から学習させる。eta = 30 , lambda = 0(勝敗のみ) (40c80tで10分。4c8tでも1時間程度)

> evalsavedir rezero0.1

> learn batchsize 300000 eta 30 lambda 0 loop 1 generated_kifu.bin

Step 4.

1スレッド1秒でepoch 0と対戦させてみる。

engine1 = YaneuraOuV460.exe , eval = rezero0.1/0
engine2 = YaneuraOuV460.exe , eval = eval_zero_epoch0
T1,b1000,622 – 2 – 376(62.32% R87.44) win black : white = 53.41% : 46.59%

R80ほど強くなった。ここで作成した評価関数epoch 0.1として、やねうら王のGitHubで公開しておいた。短い時間で簡単に作れるので興味のある人は自分でも作ってみて欲しい。

補足

ここでは追試が楽なようにdepth 3にして、1億局面と、局面数も大幅に減らしたが、局面数を増やしたりdepthを深くしたりして繰り返しこの手法を適用することによりBonanza 6の強さには簡単に到達できることを確認している。

つまり、elmo絞りというオーパーツを持ち出すこともなく、従来手法でも人間の棋譜を用いずに評価関数の学習をさせ、プロ棋士レベルに到達させることは、本当は可能だったのだ。

では、いままで何故、誰も同じことが出来なかったのか?

・局面数が足りてなかった。
・学習部にバグがあった。
・学習部の精度が低かった。
・学習部に理論的に間違った、もしくはSGD・AdaGradより性能の悪い独自手法を採用していた。
・バグ持ちの探索部で教師局面を生成していた。
・Bonanza6より大幅に弱いような独自に書かれた探索部で教師局面を生成していたので教師局面の精度に問題があった。
・Bonanza6より大幅に弱いような独自に書かれた探索部だと、評価関数が多少改善されても、強くなっていることを客観的に示すことが難しかった。
・駒得のみの評価関数よりは強くなっていたが、ソースコードが公開されていないので第三者による追試が出来なかった。
・研究している人達のプログラマーとしての実装能力に問題があった。

枚挙に暇がない。やねうら王も学習部や探索部には、長い間、細かいバグも含めると様々なバグを内包していたし、精度的な問題も抱えていた。なので従来、研究していた人たちをここでこき下ろすつもりは決してない。それほどに探索部・学習部をきちんと作りきるのは難しいということであるし、やねうら王にしても多くの人の支えがあって、やっとここまでこれたのだ。

とは言え、今回の結果を踏まえるとBonanza6を改造して、教師局面を生成し、そこから学習させ、プロ棋士レベルの評価関数を作成すること自体は技術的には出来たはずではある。まあ、しかしそれは結果論にすぎない。

追記[2017/6/20 14:40] 激指(WCSC26 / 2016年)が人間の棋譜を使わない学習に成功していたらしい。

追記[2017/6/20 20:20] 

追記[2017/6/20 15:20] 上で書いた手法はQ-learningそのもの。逆に言うと、この手法より学習効果としてはelmo式のほうが優れているので、Q-learningの補正項として深い探索のスコアを用いる(≒RootStrap)と良いという知見が自動的に得られる。

従来手法に基づくプロの棋譜を用いない評価関数の学習” への5件のコメント

  1. やねうら王本体をダブルクリックして「Step 2.」のコマンドを打つだけで簡単に教師局面を作ることが出来たので驚きました。
    教師局面生成時について質問があります。
    定跡指し手選択数は16手で固定でしょうか?変更するコマンドがあれば教えて下さい。
    (コマンドが無ければ将棋学習用の短い定跡を作るのは簡単なので、次回のバイナリ更新時にでもBookMovesのデフォルト値を70手とかに変更して頂ければと思います)

    持論ですが、将棋は36手目までお互いが最善を尽くした場合は千日手ルートが存在し、評価関数は初手から楕円形のような非線形で始まり、そのまま千日手になると評価値0の引き分け。
    どちらかが勝敗を決するルートを指した瞬間に勝利へ向かって線形に変化すると考えています。
    このことから将棋を学習する場合、16手では局面をバラつかせるのも微妙に短く、戦法を学習しようにも短いと感じます。

    • > 定跡指し手選択数は16手で固定でしょうか?変更するコマンドがあれば教えて下さい。

      そのへんは思考エンジン設定に従います。例えば定跡を採用する手数は”BookMoves”オプションなのでUSIプロトコルに従って、
      setoption name BookMoves value 32
      あるいは単に
      bookmoves 32
      のようにすれば変更できます。

      教師局面を作るときに採用する定跡/手数によって生成される評価関数の性質・棋力がどう変わるかはまだデータがあまりなくてよくわかりません(´ω`)

      • 教えて下さってありがとうございました。
        無事に評価関数を作成することが出来ました。
        たぶん私のPCスペックが要求ギリギリなので書いておきます。

        PC=i3-3240
        YaneuraOu-2017-early-sse42-4.70使用

        教師局面生成
        Threads 1
        ※2コア使うと落ちました
        1スレッド、定跡使用、depth 3で2億局面生成に21時間

        学習
        Threads 1
        ※2コア使うと落ちました
        1スレッド、elmo絞りで2億局面で1時間30分
        ※uuunuuun氏が1億局面で8スレッド1時間だから異常に早いと思う。定跡使ったから?

        軽く対局を見た限りでは、かなり強くなっているので問題ないと思います。
        この程度のPCでも1日1回鍛えることが出来そうです。

        学習時に質問です。
        私はオリジナル定跡でbook.binしか入れておらず、学習時にstandard_book.dbが無いよ!ってエラーが出たのですが普通に評価関数の作成が出来ました。
        standard_book.dbが無いと何かマズいのですか?

        • > ※2コア使うと落ちました

          置換表減らしてはどうでしょうか。
          Hash 16
          とかでも。学習のときには置換表は用いないので
          Hash 0
          でも。

          > 1スレッド、elmo絞りで2億局面で1時間30分

          2億局面1時間30分はまあそんなものかなと。uuunuuunさんのは8スレッドと言ってもHTなので実質4スレッド相当ですし、1スレッドのみの動作のときはTurbo Boostかかりますし。そう考えると1スレッドのみの場合、8スレッド時の3/8ぐらいの性能は出ます。あとはHDDなのかSSDなのかだとかそのへんの違いだとか。

          > 私はオリジナル定跡でbook.binしか入れておらず、

          教師局面生成時は関係ありますが、学習時は定跡ファイル関係ないです。

          • そういや、配布してる実行ファイル、OpenMPオフにしてあるので学習時の重み配列を更新するときの並列化がされてないのでした…(´ω`)
            msys2環境下でg++がインストールされていれば、make learnと打ち込むと、OpenMPが有効な学習用の実行ファイルが出来ます。
            あるいは、mini-batchサイズを1000000ぐらいにすれば、重み配列の更新回数が減るので学習が速くなるはず。(その代わり、値の変動回数が減るので教師局面が少ないとあまり値が変化しない)

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です