パラメーター自動調整フレームワーク - mizar/YaneuraOu GitHub Wiki

パラメーター自動調整フレームワーク

探索パラメーターなどのチューニングを行うためのフレームワークです。

使い方

source/config.h で TUNING_SEARCH_PARAMETERSをdefineしてコンパイルすると探索パラメーターのチューニング用のエンジンが得られます。

makeコマンドの例)

make clean YANEURAOU_EDITION=YANEURAOU_ENGINE_NNUE
make -j8 tournament COMPILER=clang++ EXTRA_CPPFLAGS=-DTUNING_SEARCH_PARAMETERS YANEURAOU_EDITION=YANEURAOU_ENGINE_NNUE TARGET_CPU=AVX2

これは探索パラメーターをチューニングするための特殊な実行エンジンで、このエンジンは起動時に以下のような警告が表示されます。

info string warning!! TUNING_SEARCH_PARAMETERS.

探索パラメーターは、

source/engine/yaneuraou-engine/yaneuraou-param.h

で定義されています。

例)

// [PARAM] min:12,max:40,step:1,interval:2,time_rate:1, fixed
PARAM_DEFINE PARAM_ASPIRATION_SEARCH_DELTA = 17;
  • min,maxはこのパラメーターの最小・最大値
  • stepは可変させる量。
  • intervalは、stepを何個分まで広げるかという量。
  • 末尾にfixedと書いてあるパラメーターは、可変させないの意味。 例)
PARAM_ASPIRATION_SEARCH_DELTA = 17で
step:3,interval:2なら
17-6, 17-3, 17+0, 17+3, 17+6 の5通りの値がランダムに試されます。

source/engine/yaneuraou-engine/yaneuraou-param.h

を少し書き換えて

source/engine/yaneuraou-engine/param/

のほうにコピーしてやる必要があるのですが、これを行うPythonのスクリプトが

source/engine/yaneuraou-engine/param_conv.py です。

これでそのあと基準ソフトと連続対局させます。

そうすると、勝敗とそのときのパラメーターが以下のように勝敗ログに書き出されます。

gameover lose
PARAM_FUTILITY_MARGIN_ALPHA1:178,PARAM_FUTILITY_MARGIN_BETA:163,PARAM_FUTILITY_MARGIN_QUIET:130,PARAM_FUTILITY_RETURN_DEPTH:5,PARAM_FUTILITY_AT_PARENT_NODE_MARGIN1:278,PARAM_FUTILITY_AT_PARENT_NODE_GAMMA2:18,PARAM_LMR_SEE_MARGIN1:246,PARAM_REDUCTION_ALPHA:485,PARAM_NULL_MOVE_DYNAMIC_ALPHA:972,PARAM_NULL_MOVE_DYNAMIC_BETA:110,PARAM_NULL_MOVE_DYNAMIC_GAMMA:192,PARAM_NULL_MOVE_MARGIN0:24477,PARAM_NULL_MOVE_MARGIN1:24,PARAM_NULL_MOVE_MARGIN3:87,PARAM_NULL_MOVE_MARGIN4:177,PARAM_NULL_MOVE_RETURN_DEPTH:12,PARAM_PROBCUT_MARGIN1:201,PARAM_REDUCTION_BY_HISTORY:4578,PARAM_RAZORING_MARGIN:510,

この出力先のフォルダはエンジンオプションのPARAMETERS_LOG_FILE_PATHで変更できます。

例) エンジンを起動してからUSIコマンドで

setoption name PARAMETERS_LOG_FILE_PATH value \WS2012_860C_YAN\yanehome2\result_log\param_920_%%THREAD_NUMBER%%.log

これを集計するスクリプトが

script/analyze_result_log.py

です。

このスクリプトで集計すると、

total : 1276 - 142 - 1065(54.51% R31.4)
  total : 1276 - 142 - 1065(54.51% R31.4)
PARAM_FUTILITY_MARGIN_ALPHA1:
  163 : 223 - 21 - 161(58.07% R56.59)
  168 : 226 - 38 - 228(49.78% R-1.53)
  173 : 259 - 26 - 220(54.07% R28.35)
  178 : 283 - 29 - 212(57.17% R50.18)
  183 : 285 - 28 - 244(53.88% R26.98)
PARAM_FUTILITY_MARGIN_BETA:
  162 : 434 - 40 - 397(52.23% R15.48)
  165 : 398 - 52 - 301(56.94% R48.53)
  168 : 444 - 50 - 367(54.75% R33.09)
PARAM_FUTILITY_MARGIN_QUIET:
  127 : 439 - 47 - 375(53.93% R27.37)
  130 : 503 - 58 - 390(56.33% R44.2)
  133 : 334 - 37 - 300(52.68% R18.65)
…

のようなそれぞれのパラメーターをいくらにしたときに基準ソフトに対して勝率がどうであるかという表が出力されます。

パラメーターの自動調整を行うなら、これをもとに、

source/engine/yaneuraou-engine/yaneuraou-param.h

で定義されている値をよさげな方向に動かすとか、何かパラメーターの自動調整ソフト(Optunaなど)と組み合わせるだとかすると良いでしょう。

Optunaを用いた探索パラメーターの自動チューニング

dlshogiでもOptunaを用いて探索パラメーターをチューニングされています。

Optunaは使いやすく、少ない試行回数で最適なパラメーターを見つけてくれるので、いまどきOptunaを使っていないと「なんでOptuna使わないんですか?」というツッコミがたくさんやってきます。Optuna使いましょう。

しかし、DL系の探索部と違って、NNUE探索部(αβ型の探索部?)は、Optunaをそのまま適用すると嵌まるポイントがいくつかあります。

まず1つ目の問題として、NNUE探索部においては、次の記事のように、ある程度探索が深くなってきた時にしか用いない枝刈り/延長の技術が使われています。そのため、短い持時間での勝率をもとにチューニングしようにも、短い持時間では、そのような枝刈り/延長に関するパラメーターは実際は使われていないので、それらに関係するパラメーターがランダムな値に調整されてしまいます。

このように、使っていないパラメーターが変な方向に調整されてしまうという問題があるので、短い持時間での対局では、単純には調整できません。

2つ目の問題として、探索パラメーターによって勝率が変化して、いま勝率が最大となるパラメーターを見つけたいわけです。すなわち、勝率fは探索パラメーターを引数にとる関数なのです。

勝率f(探索パラメーター) ← これを最大化するパラメーターを知りたい

ところがこの関数fは、性質として、単峰性があるのではないかと言われています。パラメーターをどこかに持っていくと勝率が最大となり、そこからパラメーターを大きくするか小さくするとそこから勝率が下がっていく、そういう分布の山が1つだけであるのが、単峰性という性質です。

こういう性質がある場合、前回調整したときの値から、微小にプラスとマイナス方向に動かして、勝率が上がるか見て調整する程度で良いとも言えます。(むしろその方が正確に調整できる意味があります)

やねうら王の探索パラメーターをOptunaのようなパラメーター自動調整ライブラリ(フレームワーク?)で調整された例としては、WCSC27(2017年)の『蒼天幻想ナイツ・オブ・タヌキ』があります。これはhyperoptというパラメーター自動調整ライブラリを用いて調整されました。残念ながら、その時は、本家やねうら王を超えるようなパラメーターは発見できなかったようですが。

NNUE系の探索パラメーターをOptunaで自動調整できるかは今後の研究が待たれます。