続) 評価関数をブリードすると何故強くなるのですか?

前回記事の続き。やねうら王の学習部をAperyと比較するところから。前回記事の続き。やねうら王の学習部をAperyと比較するところから。


やねうら王エンジンで教師生成
浮かむ瀬から50億、depth6、eval_limit=3000。lambda = 0.33。(elmo相当)ランダムムーブ、1〜6手目。
これでelmoとほぼ同等のはず。

lambda = 0.33
engine1 = YaneuraOuV460.exe , eval = elmo_WCSC27
engine2 = YaneuraOuV460learn.exe , eval = Apery20161007_23
T2,b1000,480 – 14 – 506(48.68% R-9.16) win black : white = 52.23% : 47.77%
T2,b2000,495 – 13 – 492(50.15% R1.06) win black : white = 52.28% : 47.72%
T4,b2000,504 – 28 – 468(51.85% R12.87) win black : white = 53.91% : 46.09%
T8,b2000,518 – 24 – 458(53.07% R21.39) win black : white = 50.82% : 49.18%

長い時間になってくると若干負けている。
同条件でlambda = 0.5に変更。

engine1 = YaneuraOuV460.exe , eval = elmo_WCSC27
engine2 = YaneuraOuV460learn.exe , eval = Apery20161007_25
T2,b1000,498 – 19 – 483(50.76% R5.31) win black : white = 52.5% : 47.5%
T2,b2000,502 – 18 – 480(51.12% R7.78) win black : white = 51.93% : 48.07%
T4,b2000,494 – 13 – 493(50.05% R0.35) win black : white = 52.58% : 47.42%
T8,b2000,447 – 17 – 376(54.31% R30.05) win black : white = 49.94% : 50.06%

さっきより少し良いかも知れないが、やはり長い時間で負けている。
追加で以下の実験をした。

1) 省メモリ化のために学習時の重み配列を三角配列にしている部分にバグがあるのかと思い、この機能をオフにして学習させてみたが、結果、ほぼ変わらなかった。

2) 学習時の重み配列がfloatであるので演算精度が足りないのかと思い、これをdoubleにしてみたが、これも結果は、ほぼ変わらなかった。

3) elmoはAperyの学習部を用いてあり、Aperyのランダムムーブは、やや特殊で、玉の移動が多めになるようにしてあり、かつ玉を移動させたときは1/2の確率で相手にも追加で1回ランダムムーブの権利を与えるというものである。これをやねうら王の教師局面の生成部にも実装してみて、depth 6で50億局面生成してみたが、これも結果はほぼ変わらなかった。

4) 学習時の次元下げ(ミラー)が良くないのかと思い、KKP、KPPのいずれもミラーもオフにして学習させてみたが、これは結果が若干悪化した。おそらく教師局面が50億しかないと相対的に教師が不足するためだと思われる。

5) 学習時のvの小数点以下(固定小数)を8bitで持っているのを16bitに変更してみた。これにより若干改善したかも知れない。(計測誤差かも) AdaGradでは学習の後半では1回の移動量が小さくなっていくが、このとき固定小数だとその小さな移動が出来なくなるので早い段階で値が動かなくなってしまい、教師が無駄になっている意味があるのかも知れない。ここは16bitに変更することにした。

6) Aperyのほうがやねうら王より枝刈りが甘いのでdepth 6の教師だとAperyのほうが質が良いという可能性が考えられる。そこでやねうら王でdepth 8で50億局面を生成してみた。depthは1上がるとR100以上、上がるので、depth 2も増えてこれでAperyより教師の質が悪いということはありえない。これで、elmo(WCSC27)とほぼ互角になったが、さすがにそれはおかしい。

そうこうしているうちに、やねうら王の評価関数の差分計算部にバグを見つけた。公開してから長らく経つのに、いまさらこんな部分にバグがあるとは自分でも信じられないが、こんな部分のコード、誰も読んでないのだろう。

内容的には、KKPのinverse(盤面を180度回転させた時の駒配置のこと。先手の45歩に対する後手の65歩の関係にあるもの)の値は同じ値が書き込まれていることを前提としたコードになっていた。差分計算をするループで、後手の計算をするときに、この性質を利用すると変数が1つ省略できるのでそうしていたのだが、このinverseの次元下げは、いまのやねうら王ではやっていない(inverseしたときの値が同一であるという保証がない)ので、これは間違ったコードである。

やねうら王でinverseの次元下げをやめたのは、将棋では先手なら成立する速攻が後手だと成立しないことがあり、盤面をinverseした時のポジションが同じだからと言って、同じ評価を下して良いとは限らないと私が考えたからである。

Aperyの学習部のコードは少し見通しが悪く(いまは使われていない古いコードが残っているのと、templateが多用してあるのとで)、実際にどの次元下げが行われているのか私にはよくわからないが、elmoの評価関数バイナリは、(やねうら王側のassertに引っかからないことから察するに)どうもinverseの次元下げをやっているようである。

つまり、この修正を行なう前のやねうら王のコードだと、elmoだとうまく機能して、やねうら王で学習させた評価関数だと差分計算がおかしくなるのである。とは言え、inverseしたところにもだいたいは近い値が書き込まれているだろうし、差分計算がおかしくなっても、影響を受けるのはその局面以降のノードだけだから影響は限定的である。もしかすると長い時間では「その局面以降のノード」の数が馬鹿にならないのでもう少し影響を受けるかも知れないが…。

ともかく、このバグは修正した。この新しいバージョンで計測しなおそうと思ったが、すでに上の実験をしたときに評価関数ファイルは削除してしまっていた。さすがに学習しなおすのは面倒なのでこの実験はしていない。

そもそもであるが、inverseの次元下げをやると教師局面を倍与えているのと同じ効果がある。elmo(Aperyの学習部)がそれをやっているなら、そこはやねうら王と同条件とは言い難いので、もしかすると長い時間でelmoのほうが強く見えたのは、その効果もあるのではないかと思う。

やねうら王の学習部のほうにもinverseの次元下げを実装すべきかも知れないが、これはやらないほうが最終的には強くなるはずであり(と私は信じている)、まふ評価関数などが、elmoより明らかに強いのはそのへんも影響していると私は考えている。だから、これは実装したくない。

そんなわけで、やねうら王の学習部がAperyと比べてどうなのかという実験はこのへんで終了としておく。実験結果がグダグダになってしまって申し訳ないのだが、総合すると、まあ、だいたい互角であろうという結論で良いかと思う。

評価関数をブリードすると何故強くなるのかについては、もう少し調べたいところだが、さすがにこんな実験ばかりやっていて、いまだ1㍉も強くなっていないのはまずい。次回の電王トーナメントがいつ開催されるのかは知らないが10月上旬だとしたらやねうら王は大爆死である。そんなわけで後続の記事は電王トーナメントが終わってからになるかも知れない。


続) 評価関数をブリードすると何故強くなるのですか?” への8件のコメント

  1. まじぇまじぇすると、確率的に評価関数のデコボコ(過大評価と過小評価)が均されて、先を読んだ時に誤った枝狩りをしなくなるのでは。

    何の説明にもなっとらんか…

    • その謎を解明するとブリードするより強いものが出来るはずで、解明していないチームに比べて+R30〜50ぐらいのアドバンテージを得られる気がするんですけど、私はまだ解明できてないです(´ω`)

  2. depthが1増えたらR100上がるならdepth12で50億局面生成、史上最強の評価関数誕生!…とはならないんですよねやっぱり

    • 教師がいくら優秀であっても生徒が馬鹿だとあまり差が出ないということはありまして。

      つまり、KPPTの評価関数の表現能力の限界を超えて学習は出来ないということですなー。

      • 戦型や進行度別にそれぞれ専用の評価関数を作って切り替えるとかで、表現力の少なさをカバーするとかは難しいですか?

        • その方法は、学習に必要な教師数が一気に増えますし、そのわりには評価関数同士がシームレスに接続してるわけではないので、言うほど棋力向上しないと私は思ってます。

コメントを残す

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