Pythonでのoptuna実装について、理論面にはノータッチの脳筋スタイルで連載をお送りしています。最終回です。
第1回では1変数の関数に対する最適解探索を、第2回では機械学習モデルのパラメータ最適化を実装しました。そして最終回となる第3回の今回は、デフォルトパラメータやscikit-learnのランダムサーチとの精度比較により、optunaの有用性を精度の観点から見ていこうと思います。
第一回の記事はこちら toeming.hatenablog.com
第二回の記事はこちら toeming.hatenablog.com
前回に引き続き、備忘録です。
1. optunaとは
略。第一回の記事を参照してください。
2. 他の最適化手法との精度比較
optuna以外のハイパーパラメータ探索の手法との精度比較を実施します。
2.1. 比較条件
第2回記事のoptuna実装と同様にタイタニック生存予測の2値分類モデルをSVMにて実装し、比較対象の各手法を用いてハイパーパラメータを探索した後、チューニング後のモデルの正答率によって各手法の精度を比較します。チューニングの対象となるパラメータは、C, kernel(ただし"rbf", "linear", "sigmoid"のみ。"poly"は学習がめっちゃ重くなることがあって面倒だったので除外。), gammaの3つとしました。
比較検討する最適化手法は以下の通りです。
手法 | 説明 |
---|---|
default | scikit-learnの非線形SVM(sklearn.svm.SVC())のデフォルト値 具体的には、C=1.0, kernel="rbf", gamma= "auto" (1/特徴量数)。 |
optuna | もはや説明不要 がんばれoptuna |
random search | scikit-learnに実装されているランダムサーチ(sklearn.model_selection.RandomizedSearchCV()) |
optuna, random searchとも、イテレーション数は100とします。 また、実験しているうちに正答率がばらつくことがわかったので、同様の試行を20セットほど繰り返して平均をとりました。
2.2. 精度比較用コードの実装
2.3. 結果
20回の試行における正答率及びその平均・標準偏差は以下の通りです。正答率の平均値の単純比較では、optunaによりチューニングされたモデルの精度が最も優れていることがわかります。
trial | default | optuna | random search |
---|---|---|---|
1 | 0.8246268657 | 0.8208955224 | 0.802238806 |
2 | 0.802238806 | 0.8134328358 | 0.776119403 |
3 | 0.8097014925 | 0.8470149254 | 0.776119403 |
4 | 0.8134328358 | 0.8470149254 | 0.7350746269 |
5 | 0.7873134328 | 0.8171641791 | 0.7611940299 |
6 | 0.7798507463 | 0.8059701493 | 0.8208955224 |
7 | 0.8358208955 | 0.8097014925 | 0.828358209 |
8 | 0.7873134328 | 0.8059701493 | 0.7985074627 |
9 | 0.7723880597 | 0.8059701493 | 0.7985074627 |
10 | 0.8582089552 | 0.8208955224 | 0.8246268657 |
11 | 0.7985074627 | 0.776119403 | 0.8134328358 |
12 | 0.8358208955 | 0.7798507463 | 0.776119403 |
13 | 0.7947761194 | 0.8171641791 | 0.7835820896 |
14 | 0.7835820896 | 0.828358209 | 0.8320895522 |
15 | 0.7985074627 | 0.7835820896 | 0.7910447761 |
16 | 0.8395522388 | 0.8097014925 | 0.8134328358 |
17 | 0.7985074627 | 0.8358208955 | 0.8097014925 |
18 | 0.8097014925 | 0.8358208955 | 0.7910447761 |
19 | 0.8134328358 | 0.8395522388 | 0.7835820896 |
20 | 0.7985074627 | 0.8246268657 | 0.7910447761 |
ave | 0.8070895522 | 0.8162313433 | 0.7953358209 |
std | 0.02232578403 | 0.02036107421 | 0.02419020019 |
各試行ごとの正答率を見ると、試行ごとにばらつきが大きいことがわかります。そこで、結果の差の有意性について仮説検定を行いましました。有意水準を5%と設定し、default vs optuna 及び random search vs optuna の2パターンで対応なしの両側t検定を行います。なお、事前に等分散検定を行った結果を考慮し、等分散性を仮定したt検定を行っています。
結果を以下の表に記載します。
組み合わせ | F検定のp値 | t検定のp値 |
---|---|---|
default vs optuna | 0.6920992937 | 0.1840413622 |
random search vs optuna | 0.4595881984 | 0.005337815223 |
random search vs optuna における精度差は有意であり、同じイテレーション数ではランダムに探索するよりもoptunaの方が効率的にチューニングできると言えそうです(仮説検定はあんまり慣れていないので、そもそもやり方が間違っていないかめちゃめちゃ不安です)。
一方でdefault vs optuna の差は有意水準を下回り、精度差があるとはいえない結果となりました。optunaで得られた最適解を確認すると、例えば「'prm_C': 0.7723506902995125, 'prm_kernel': 'rbf', 'prm_gamma': 14.517832809956605」のように、特にCとkernelについてはデフォルトと大差のない解が散見されました。ここから察するに、そもそもデフォルトのパラメータがそこそこ優秀であり、最適化の恩恵を受けにくい状況設定だったのかもしれません。
2.4. 結論
optunaを利用することで、少なくともランダムサーチよりは効率的にモデルの精度を上げることができるようです。一方、デフォルトパラメータから大きく精度向上が見込めるとは言い切れない結果となってしまいした(多分実験の問題設定が悪かった)。
しかしながら、少なくとも今回の連載中で作成した程度のプログラムであれば手間も学習コストも掛からず楽々実装可能なので、手軽にちゃちゃっとチューニングするには便利なパッケージだと感じました。
肌感としては「イイ感じ」「機会があれば使ってこ」って感じです。
3. おわりに
ということで、3回に渡る「optuna使ってみた」的連載はこれにて完結です。手軽に実装できて結果もそこそこ出そうなので、使ってみて損はない気がします。可視化周りや分散処理関連で今回触れなかった部分にもまだまだ深堀の余地がありますね。
あとoptuna関連の記事全体を通してなんですが、正直なところ実装して結果が見えた時点で割と満足してしまい、記事化するのが途中からマジで苦痛でした。ちゃんと終わらせることができてよかったです。
次はPRML周りに全然関係ない楽しいことを書きたいです。