Numerai で Random Seed Average

3 min read読了の目安(約3300字

この記事は、Numerai Advent Calendar 2020の1日目の記事です。

2日目の記事はUKIさん「NumeariトーナメントのValid Corrをちょびっとだけ上げる小技」です。

参考資料

はじめに

ニューラルネットワークなどの機械学習ではモデルの初期値を乱数で生成しています。
その初期値によってスコアが変動しまうことに悩んでおりました。

初期値を変えながらモデルを作成して、validationのスコアがいいものを選んだらいいのか?どうアプローチをしたらいいのか?と悩んでおりましたところ、いいことを教えてもらいました。

ということで、ランダムシードアベレージという手法を試してみることにしました。

実験

実験Notebookはこちら(Gist)

  1. 公式example scriptの初期値を変えながら30個のモデルを生成します。
  2. 各モデルのvalidation予測のスコアの平均を計算します。
  3. 各モデルのvalidation予測を平均した予測のスコアを計算します。

結果

モデル validationスコア
model_0 0.028905115759917572
model_1 0.028839441329809517
model_2 0.02921323028079193
model_3 0.028522350017145304
model_4 0.02936801687338555
model_5 0.029079186323748136
model_6 0.028979724294433268
model_7 0.029251024058632485
model_8 0.02840886764966899
model_9 0.02880805730907734
model_10 0.02843635982530843
model_11 0.026877035233155034
model_12 0.02839237423196859
model_13 0.028494873071677432
model_14 0.02799380622096903
model_15 0.028915742343947268
model_16 0.02921264209585863
model_17 0.028761814861732047
model_18 0.029395473225945552
model_19 0.028925262488193715
model_20 0.02911980690722348
model_21 0.028839393923219304
model_22 0.02903148499758035
model_23 0.028984570921122724
model_24 0.029681396528901567
model_25 0.029568379432439205
model_26 0.028575497738446528
model_27 0.029951257363657842
model_28 0.028710364124751427
model_29 0.028693068012659983
スコアの平均値 0.028864520581512277
予測の平均のスコア 0.02916771995422608

考察

スコアの平均値よりも、予測を平均したもののスコアの方が高くなりました。
違う初期値で作成したモデルの予測をそれぞれsubmitするよりも、平均してからsubmitしたほうが、Payoutsは多くなると期待できそうです。

私のニューラルネットワークのモデルはXGBoostよりも更にばらつきがでるので、とりあえずRandom Seed Averageしておけば初期値ガチャに悩まなくて済みそうです。

また、予測は1アカウント10個までしか提出できないので節約できておトクですね!

Kerasで予測の平均を出力する

さて、10個の予測を平均しようとすると、予測の計算に10倍の時間がかかってしまいます。
Kerasなどを使用してGPUで予測を計算している場合、GPUの計算能力に空きがあれば、並行で実行して時間を短縮することができます。

Kerasで各モデルの平均を出力するモデルの作成方法をご紹介します。
KerasにはAverageレイヤーがあるのでこれを利用します。

models = []
for filename in model_filenames:
    model = keras.models.load_model(filename)
    # model.nameがレイヤー名になるので、かぶらないように変更する
    model = keras.Model(inputs=model.inputs, outputs=model.output, name=filename)
    models.append(model)

input = keras.layers.Input(models[0].input.shape[1:])

models_outputs = []
for m in models:
  models_outputs.append(m(input))

ave_layer = keras.layers.average(models_outputs)
ave_model = keras.Model(inputs=input, outputs=ave_layer)
ave_model.summary()

ave_model.save(save_model_filename)

この ave_model を使えば1つのモデルと同等の時間で、予測を計算できます。

終わりに

これでようやく初期値の悩みから解放されました。
tit_QASHさん、本当にありがとうございました。