やねうら王の学習ルーチンを使っている開発者の方へ大切なお知らせ。
やねうら王の学習ルーチンで、SGDで学習させるときにw[0](非手番)とw[1](手番)の値を更新するのに、w[0]側はeta、w[1]側はeta2という学習率の係数を掛けているのですが、etaをepochが進むにつれて減衰する値に修正したときに、etaをconstからglobal変数に変更していて、eta2はconst float eta2 = eta/4;のように定義してあるので、eta2が0のままになっていました。つまりは手番側の値を変動できなくなっていました。この変更してから、なんかおかしいと思ってたんだよ!そんなわけで#define eta2 (eta/4) のように修正するなどしてください。
その他、学習で困ったことがあればコメント欄で質問などどうぞ。
学習に関するありがちなQ & A (2016/08/29 24:00追記)
SGDでの学習に関して
Q) SGDは普通countみたいな変数は用意せずにw = w – η ∂J / ∂w で更新していくと思うのですが、やねうら王のように、この∂J / ∂wの項をcountで割ったほうが良いのですか?
A) mini-batchで学習させるときにmini-batchの量に応じてηを調整するのが面倒だったのでそうしてあります。また、比較的sparseで、あまり出現しない特徴因子もありますから、そういう特徴因子に対しても値はそれなりに変動して欲しいのでこのようにしてあります。
教師生成のdepth関して
Q) 教師局面を生成するときのdepthはいくらがベストなのですか?
A) depthが深いほうが雑巾が絞りやすい(1回のイテレーションにおける棋力の向上が大きい)と言われていますが、本当のところよくわかりません。depthが深いと教師局面の生成に時間がかかりますので、最初のうちはdepth3で回して、サチって(飽和して)から、depthを徐々に上げていくのが良いでしょう。
教師生成時のEVAL_LIMITに関して
Q) 教師局面を生成するときのEVAL_LIMITはいくらがベストなんですか?
A) 最初イテレーションでは大きめの値(VALUE_MAX_EVALなど)に設定したほうが早く強くなるようです。しかし勾配が大きくなりがちなので単に目的の値に早く収束しただけで学習率を大きくしたときのような効果しかない可能性があります。イテレーションが進むにつれて都度調整したほうが良いでしょう。
教師局面の数について
Q) 1回に生成する教師局面はどれくらいがベストなのですか?やはり80億局面ですか?
A) 最初のうちは数億局面程度でも問題ないようです。サチってから増やしていきましょう。
教師局面生成のときの優等局面/劣等局面の扱いについて
Q) 教師局面の生成のときに優等局面/劣等局面の値(VALUE_KNOWN_WIN)は局面の教師値として好ましくないと思うのですが、これは避けたほうが良いのではないですか?
A) 教師局面を生成するときのEVAL_LIMITを2000ぐらいに設定していれば、VALUE_KNOWN_WINが返ってきた時点でその対局はそこで打ち切られますから、実際にそのような局面の値を教師値として使うことはないのでは。
Q) EVAL_LIMIT = VALUE_INFINITEにしていると、VALUE_INFINITE ≫ VALUE_KNOWN_WINなので、生成されてしまいます。
A) それは確かにそうです。その動作が気持ち悪ければEVAL_LIMITをVALUE_KNOWN_WINより大きな値にはしないほうが良いです。
Q) 詰み寸前の形を学習させたいのでEVAL_LIMIT = VALUE_INFINITEにしたいです。
A) なるほど。であれば、教師生成のときには探索部の以下のように改造しましょう。(この改造をした思考エンジンは、通常の対局には向きません。)
1 2 3 4 5 |
auto draw_type = pos.is_repetition(); - if (draw_type != REPETITION_NONE) + if (draw_type != REPETITION_NONE + && draw_type != REPETITION_SUPERIOR && draw_type != REPETITION_INFERIOR) return value_from_tt(draw_value(draw_type, pos.side_to_move()), ss->ply); |
教師局面からの学習に関して
Q) 3億局面を生成して5周学習させていますが、何周ぐらいさせるのがベストなのですか?
A) SGDの場合、eta(学習率η)で収束の速さが変わります。うまく調整すれば(最初のほうのイテレーションでは)3億×3周ぐらいで収束します。(自己対戦させてもそれ以上は強くならないという意味で) 学習を開始して数分間のrmseなどを見ながらetaを調整してみてください。
Q) rmseが下がらなくなったところで学習を打ち切っても大丈夫ですか?
A) rmseが下がらなくなってもしばらく学習を回していると強くなることがあります。評価関数を定期的に保存してそれぞれを対局させてみると良いでしょう。
Q) 学習のときにqsearch()を呼び出して、その得られたpv通りにleaf nodeまで進めてもevaluate()がqsearch()の返し値とは異なるときがありますが、何故ですか?
A) qsearch()では置換表の値で枝刈りするため、pvでleaf nodeまで進めてもそこのevaluate()の値がqsearch()の返し値とは限りません。その局面のより適切な評価としてはそれで正しいと私は思うのですが、この動作が気持ち悪ければ、やねうら王ではDISABLE_TT_PROBEをdefineすれば置換表のprobeをしないようになります。(このとき、通常の思考エンジンとしては使えなくなります。学習のとき用にお使いください。)
rmseがサチった感じ(むしろ増える事もある)&mean_errorが減らない感じになったら、元の教師データを疑った方が良いでしょうか?
それとも学習を何回か回せばそれなりの値に収束して行く?
そこから10、20億局面ほどさらに回して、棋力が上がっているかどうかをチェック。
あとは、目的関数を設計しなおすだとか、学習方法を変えてみるだとか、学習率ηを少し抑えてみるとか、mini-batchのサイズを上げてみるだとか。rmse以外の指標を追加してみるだとか。(例えば、プロの棋譜との指し手一致率。)
YaneGladで回して置いて、家に帰って確認してみたら、rmseが見た事ない大きい値に…?(0.150956)
そして、mean_error=995.271400って…。
しかも経過を見ると、どんどん両方大きくなっている模様。
これは…棋力をチェックするまでもなく失敗してる気がorz
さて、棋力チェックするか…(´・ω・`)
それは、確かめるまでもなく発散してますなー。何がなんでもまずはSGDでそこそこうまく収束するところまで調整すべきだと思いますよ。他の更新式は、かなり丹念に調整すればSGDより短い時間でSGDよりいい値に収束するかも、みたいな感じなので、SGDで雑巾が絞れる状態でないなら時期尚早のような…。
逆にSGDで教師depth3だとこれ以上雑巾絞れなくなった感じだったので、手を出してみました(苦笑)。
もし鞍点に乗ってるなら、SGDじゃないアルゴリズムで(例えばAdaGladとか)抜け出せるかな、と。
> もし鞍点に乗ってるなら、SGDじゃないアルゴリズムで(例えばAdaGladとか)抜け出せるかな、と。
これだけ高次元のベクトル、そうそうローカルミニマムには陥らないのでは。
そう(ローカルミニマムに陥っていると)信じるのならば、Gradient Noiseを加えてみて良い結果が出るか試してみれば良いでしょう。
http://postd.cc/optimizing-gradient-descent/#gradientnoise
まぁ、鞍点に乗っているって半信半疑なのですけど、ちょっと土日に試してみます。
(プログラム、平日に書けない病気)
伸び悩んでるのは確かなので。
(現在、AperyWCSC版にR+100位?です。今のままでももう少し雑巾絞れそうに思うのですが。)
> 現在、AperyWCSC版にR+100位?です。
そのへんからは伸ばすのが大変でしょうね…。R2とか3とかを計測する技術がないと、学習率や学習時間の調整も容易ではないですし…。
まぁ、私の用意できる環境だと、これ位で限度かも知れません。R2やR3を計測しようと思うと、丸2日位対局にかかりそうですし…。
(おそらく、やねさんの作った評価値-100~+100の約10000局面だけだと測れない気がしています…。)
> (おそらく、やねさんの作った評価値-100~+100の約10000局面だけだと測れない気がしています…。)
何故でしょう?先後入れ替えると2万局面強ありますが足りませんか?
誤差をどれくらいに見積もればいいのか分かりませんが、R2の違いと言うと、勝率に換算して50.3%位(計算あってるかな?)だと思うと、
10000試合やって5030勝4970敗って、信頼区間95%だと思うと有意に強くなっていると言えないのではないかと…。
(どこかで計算間違えてたらすみません)
1万試合で足りないと思えば、先後入れ替えて2万試合にすればどうでしょう?
あと、1回のイテレーションでR2上がるはずの手法があるなら3回ぐらい回せばR6ぐらい上がるはずで、3回まわしてから棋力の伸びを計測すれば、学習率の調整とかはそれで出来なくはないかなと思うんですけど。
20000でも不足ですね。(95%信頼区間だと)
R2上がるハズの方法を繰り返してR6上がれば計測できそうなのはおっしゃるとおりだと思いますが…R2上がってる(ハズ)のを計測するのがなかなか困難ですね…。
まぁ色々考えてみます。
なるほど。2万局でも足りないんですね。まあ、95%信頼区間でなくていいような気がしますけどね。90%ぐらいであれば。それ3回イテレーションを回して、上がるかどうか見ればいいわけで…。
80%信頼区間20000局でも、10100勝9900敗で、ギリギリ強くなったと言える感じですね。(自作ツールで打ち込んでみました)
Rに換算してないですけど、R2とかR3とかを計測するのはやはりかなり辛いようです。
用意できる計算資源的には、今の評価関数では、ほぼほぼ限界なのかも知れません。(ここからR2~3上げるのに1イテレーション2~3日かかりそうですので…)
何かしら処理が軽い評価項目を足す方向でRを上げることを検討した方がよさそうです。
…さて、何足そう…。