elmoは何故2周目の雑巾を絞れないのか

WCSC27のelmoのアピール文書より。

★ 雑記
elmoの評価関数は1月3日以降全く強くなってないです。
(ある程度手応えがあったのでxeon4つ買ってみたのですが、結果に結びつかず)

今回はelmoは何故2周目の雑巾を絞れないのかについて簡単に説明する。elmoの学習式についての説明は前回記事をご覧ください。

(再掲) elmoの学習式 :
dsig = (eval_winrate -t) + 0.5 * (eval_winrate – teacher_winrate);

まず、右辺の左側の項を「勝敗項」、右側の項を「勝率項」と名付ける。(tanuki-チームではそう呼ばれているらしいので)

0.5のところはelmoのソースコード上はLAMBDAという変数名の定数になっている。上式は、「勝敗項」と「勝率項」がLAMBDAで内分されていなくて気持ち悪いのでまず内分する式に変形する。

内分型elmoの学習式 :
dsig = (1 – LAMBDA)*(eval_winrate -t) + LAMBDA * (eval_winrate – teacher_winrate);

elmo(WCSC27)の0.5は、今回の式のLAMBDA = 0.33…相当である。

このLAMBDAが小さすぎて、勝敗項の寄与が大きすぎるというのが私が最初にこの式を見たときに直感したことであった。

というのも、tは0と1しか取らず、eval_winrateはほとんどのケースにおいて0.5付近(形勢互角)であるから、勝敗項の (eval_winrate – t) の部分の絶対値の平均は 0.3〜0.4ぐらいあるのではないかと思う。

一方、勝率項の (eval_winrate – teacher_winrate)は、浅い探索と深い探索の評価値から推定される勝率の差であるから、ほぼほぼ差はないはずであるから、絶対値の平均で言うと0.1未満であろう。

そう考えると、勝敗項の寄与が大きすぎるのではないかというのが私の最初の印象であった。そしてその予想はおおむね正しかった。

この予想が正しかったことを証明していく前に、では何故それでelmo(WCSC27)は強くなったのかという説明をしないといけない。

まず、雑巾絞りのときに勝敗を考慮するというelmoの発想自体は正しい。その詳しい説明は割愛するが、まあ、勝敗を考慮するのは、DeepLearning + 強化学習などではよくある手法なのであえて長々と説明するほどではないだろう。

私の予想ではelmo(WCSC27)のLAMBDAの値だと、発散するということであった。先に述べた通り、この予想は実は正しいのだが、ところが、AdaGradだとその発散途上にある評価関数パラメーターのスナップショットを捕捉することが出来る。

まず、AdaGradの更新式を再確認しよう。

勾配ベクトルをg、更新したいベクトルをv、η(eta)は定数として、
g2 = g2 + g^2
v = v – ηg/sqrt(g2)
である。

elmo(WCSC27)はAperyの学習部をそのまま用いており、アピール文書によると教師局面は50億局面とのことである。elmoのGitHubのソースコードからするとeta = 30.0で、おそらく、mini batchでの更新で、mini batchのサイズは1M(100万)局面である。

このことから、AdaGradの更新式は、50億局面 / 1M局面 = 5000回適用される。

mini batchのサイズがそこそこ大きい場合、勾配の絶対値はほぼ一定であると仮定できるので、n回目の更新でvの変化する値 ηg/sqrt(g2) は、eta / sqrt(n)と見積もれる。

つまり、eta = 30.0のとき、n = 900を超えると1より小さな変動しかしない。ここ以降、vにはほとんど変化がないと言っても良い。だから、AdaGradで5000回更新するのに、eta = 30.0は、やや小さいとも言える。

ところが、このetaについて、elmoのソースコードには以下のようなコメントがある

constexpr double UpdateParam = 30.0; // 更新用のハイパーパラメータ。大きいと不安定になり、小さいと学習が遅くなる。 tkzw:小さめが良い

30.0でもまだ大きいとでも言わんばかりである。

実は普通の雑巾絞りにおいてはこの項は、30より少しぐらい大きくともあまり問題とはならない。

しかし、elmoが30.0、もしくはそれより小さくしないといけないのは、elmo式だと値が発散していくので、その発散直前にある、一番強くなった瞬間を捉える必要があったからだ。

このことを証明するために、AdaGradのg2を減衰させてながら学習させてみる。例えば次のようにする。

g2 = g2×0.999 + g^2

こうしておけば、g2は減衰するのでnが大きくなってもvの変化量が0に漸近しない。

この状態にして、elmo式で学習させ、10億局面ごとの学習結果を取り出し、元の評価関数と対戦させ勝率を計測する。

【ここに資料を貼り付ける】

次に、elmoの学習式(内分型)でLAMBDAを調整しながら、学習させ、勝率がどのように変化するかを雑巾絞りと比較する。

elmoよりR40ほど低い評価関数ファイルから、depth 8で7.5億局面生成、4周。mini batch = 1M。

1) 普通の雑巾絞り。AdaGrad eta = 30.0
T1,b3000,1012 – 67 – 1161(46.57% R-23.86) win black : white = 50.9% : 49.1%

2) elmo式。AdaGrad eta = 30.0 , lambda = 0.33 (elmo(WCSC27)相当)
T1,b3000,1207 – 47 – 1046(53.57% R24.87) win black : white = 51.31% : 48.69%

3) elmo式。AdaGrad eta = 30.0 , lambda = 0.80
T1,b3000,845 – 54 – 1001(45.77% R-29.43) win black : white = 48.75% : 51.25%

普通のelmo式である2)ではR24.87弱くなったのに対して、lambdaを勝敗項の寄与が小さくなるように変更した3)ではR29.43強くなった。一応、普通の雑巾絞りである1)より強くなっているが、1)と3)とは、これが統計的な誤差の範疇である可能性もあるので1)より3)のほうが強いかどうかはさらなる検証が望まれる。

【ここに資料を貼り付ける】

次にlambdaを交差エントロピーの下がり方が最大になるようにadaptiveに調整してみる。

【ここに資料を貼り付ける】

それから、elmoは長時間では強くなっているが、短時間では弱くなっているので、プレイアウトの質が下がり、勝敗項が不正確になっているのではないかという指摘がある。これを検証するためにdepthを上げて比較した。

【ここに資料を貼り付ける】

書きかけ。

すまん、この記事は、書きかけだ。あとは適当に考察してくれ。

elmoは何故2周目の雑巾を絞れないのか」への13件のフィードバック

  1. 永遠に書きかけのままでしょうか…。
    だとしたら今から自分で頭使いますが、続きを書いてくれるならそれを読んでから考えたいです(苦笑)。

      • 了解です。
        学習部、また新たに自前で書いている(仕事が忙しくなければこの週末中に終わるハズだったけど仕事の都合で終わらない事が確定してますが…)ので、そちらで自分で手を動かして確認します。

        電王トーナメント出るなら「やねうら王」を素直に使うべきなんでしょうけど(苦笑)。

        • やねうら王の新しい学習部のソースコード、是非参考にしてみてください。マジ感動します。(半分ぐらいtanuki-さんのコードなんですけど…)

  2. 気になってるのですが、今年の電王戦に「やねうら王」は出るのですか?
    エルモちゃんに負け越して悶絶するやねさんが観たいような、コテンパンに打ち負かして「やっぱりスゲェwww」っていうのが観たいような、どちらともいえない気分です

  3. 勝率に、手数ボーナスをつけるのはあまり効果はないでしょうか。
    短手数で勝った場合には、勝率に+ボーナスを
    長手数で勝った場合には、勝率に-ボーナスを
    少し付ける。
    負けた場合も類似の補正を入れる。
    自分の囲碁のプログラムではシミュレーション部に入れていますが、効果の程は不明です。

    • > 勝率に、手数ボーナスをつける

      勝つために長手数必要な特徴があるとして、長手数必要なので紛れやすいはずなので、結果的に、勝敗は5割に引っ張られます。なので、そういう特徴は結局は小さな値に調整されるはずで、手数ボーナスは効果に乏しい気がします。まあ、やってみないと本当のところはよくわかりません。

コメントを残す

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