はじめに
Pycaret はとても便利なAutoMLサービスです。これは自動で前処理、ホールドアウト、交差検証、ハイパラチューニングなどの面倒な処理を行ってくれるのですが、前処理のせいで逆に「LightGBMを手書きするよりも精度が落ちるが、なぜかわからない」みたいなこともあります。そういうときに試すべきことをまとめました。
今回は、概ね次のようなコードで、(1)モデル比較、(2)ハイパラチューニング、(3)ブレンディング、(4)再度チューニング、(5)予測、という一連の操作を行う、という状況を考えています。
from pycaret.classification import * #回帰の場合は pycaret.regression
setup(train_data, target = "target_col")
compare_models()
model1 = create_model('some model')
model2 = create_model('some model')
tuned_m1 = tune_model(model1)
tuned_m2 = tune_model(model2)
blended_model = blend_model([tuned_m1, tuned_m2])
tuned_blended_model = tune_model(blended_model)
final_model = finalize_model(final_model)
prediction_result = predict_model(final_model, data = test_data)
Preprocess を切る
setup
を呼ぶと、Pycaretは自動でデータを前処理し、追加の行を作っている。
場合によっては邪魔なので切ったほうがよい。
test set のサイズを小さくする
デフォルトで setup
を呼ぶと、データの30%がテストデータとして完全にホールドアウトされる。この部分はCVにも使われず、チューニングにも使われない。30%はかなり大きいので、用意されたデータが十分ない場合は、これだけで精度を落とすこともありうる。(もちろん後述する finalize_model
を使うことでこの部分のデータも使ってくれるが、チューニングの時点で全データを使うか、70%のデータでチューニングをしてから、そのパラメータで全データを訓練するか、では結果が違ってくる)
特に、Kaggleでよく使われるLightGBMの実装では、特にホールドアウトをせずにCVのみ行うことが多い。こちらの方が訓練データが多いので、正確なCVの値が出ると思われる。
これはsetup(train_size = 0.999)
のように、train_sizeをほぼ100%にすることで無くすことができる。
finalize model をする
Pycaretに関する記事で、たまにこのように書かれている記事がある。
setup(train_data)
model = compare_models()
prediction = predict_model(model, test_data)
これでも動くのだけど、正しくはない。
まず setup
の時点でデータがtrain, valid, testに分割されている。create_model
は自動でK分割して交差検証をしてくれるが、このときはtrain, valid 間のみで行われる。testは一切触れられない。
testは完全にホールドアウトされて、最終的にできたモデルの精度を評価するために使われる。このときは predict_model(model)
を使う。(データセットの指定をしないと、ホールドアウトされたtestデータを使ってくれる)
そして、このtestも最終的には訓練データとして使って予測機を作りたい。このために finalize_model
をする。したがって、正しいコードはこのようになる。
setup(train_data)
model = compare_models()
final_model = finalize_model(model)
prediction = predict_model(final_model, test_data)
predict_model
の丸め込みに気をつける
predict_model
で最終的なモデルの推論をしたいとき、デフォルトでは小数点以下4桁の精度で丸められる。 Kaggleなど、0.001単位での精度を競う場合はすこし不安なので、predict_model(final_model, test_data, round = 30)
のようにして、round
引数を大きめに取っておいたほうがよい。
tune_model
に choose_better=True
を付ける
tune_model
や blend_model
をするとき、探索したパラメータによい値がないと、結局もとのモデルのほうがよかった、ということが起こり得る。なので tune_model(model, choose_better = True)
を付けておくとよい。この場合、元のモデルのほうが精度がよいなら、そちらを勝手に使ってくれる。どのメトリックを選ぶかは、optimize = "MSE"
のように指定できる。