🎰

Numerai で Random Seed Average

2020/12/01に公開

この記事は、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つのモデルと同等の時間で、予測を計算できます。

終わりに

これでようやく初期値の悩みから解放されました。

Discussion