この記事はエイチーム引越し侍 / エイチームコネクトの社員による、Ateam Hikkoshi samurai Inc.× Ateam Connect Inc. Advent Calendar 2021 11日目の記事です。
本日の担当は@m-otsukaです。
1 はじめに
個人的に興味のあったPyCaretを試してみました。
PyCaretは、オープンソースの機械学習ライブラリーで、ローコードでモデル作成が行えることが特徴です。
今回は、なるべく複雑な設定などは行わずPyCaretまかせにして、どれくらいの精度のモデルを作成することができるのか、調べてみます。
1.1 学習データ
今回、学習用データとして、kaggleのコンペティションHouse Prices - Advanced Regression Techniquesのデータセットを用いました。
こちらのコンペは、住宅の敷地面積などの79の特徴変数を元に、住宅価格の価格を予測するという内容になります。
1.2 使用環境
- PyCaret 2.3.5
- Google Colaboratory
#2 モデル作成
##2.1 ライブラリのimport
PyCaretや、その他の必要なライブラリをimportします。
今回は、回帰のモデルを作成するので、pycaret.regression
をimportしています
! pip install pycaret
! pip install catboost
import numpy as np
import pandas as pd
from pycaret.regression import *
##2.2 データセットの取得
モデル学習に用いるデータセットをpandasで取得します。
train_df = pd.read_csv('../input/house-prices-advanced-regression-techniques/train.csv')
test_df = pd.read_csv('../input/house-prices-advanced-regression-techniques/test.csv')
submission_df = pd.read_csv('../input/house-prices-advanced-regression-techniques/sample_submission.csv')
train_df["SalePrice"] = np.log(train_df["SalePrice"])
このコンペではscoreとして、予測値の対数と実際の販売価格の対数の二乗平均平方根誤差(RMSE)が用いられています。
これは、一部の住宅の価格が飛び抜けて高く、そのままの価格でRMSEを求めると、価格が安い住宅と高い住宅でRMSEに与える影響の差が生じてしまうからみたいです。
今回はそれに倣って、販売価格の対数を目的変数として、モデルの作成を行いました。
##2.3 setup
PyCaretでモデル作成を行う際、必ずsetup
を実行する必要があります。
setupではパラメータを指定して、下記に示すような前処理などを、どのように行うかを指定することができます。
- データの型の指定(指定を行わなかった場合、勝手に推測してくれる)
- 欠損値の補完
- カテゴリ変数のエンコーディング
- データのサンプリング
- 学習用データとテスト用データの分割
今回は、PyCaretを信じて基本デフォルト値のままsetupを実行してみます。
exp = setup(
data = train_df, # 訓練用データ
target = 'SalePrice', # 目的変数
session_id=1234, # seedとして用いられている値、再現性を保つために指定
)
##2.4 compare_models
PyCaretには、compare_models
という関数が用意されています。
compare_models
では、様々な学習器でモデルを作成し、それらの予測精度のスコアの比較を行うことができ、
学習するデータセットに対して、有効なモデルを知ることができます。
様々な指標が表示されるのですが、今回はRMSEを指標とするため、RMSEの値で結果をソートしています。
そして、n_select
を指定することで、精度の高い順に指定した数値分のモデルを返り値として受け取っています。
top5 = compare_models(sort = 'RMSE', n_select=5)
結果
上位5つのみ表示
Model | MAE | MSE | RMSE | R2 | RMSLE | MAPE | TT (Sec) |
---|---|---|---|---|---|---|---|
CatBoost Regressor | 0.0844 | 0.0159 | 0.1244 | 0.8999 | 0.0096 | 0.007 | 7.458 |
Gradient Boosting Regressor | 0.0935 | 0.0183 | 0.133 | 0.886 | 0.0103 | 0.0078 | 0.661 |
Light Gradient Boosting Machine | 0.0946 | 0.0192 | 0.1372 | 0.8798 | 0.0106 | 0.0079 | 0.182 |
Bayesian Ridge | 0.0898 | 0.0217 | 0.1412 | 0.8548 | 0.0108 | 0.0075 | 0.179 |
Ridge Regression | 0.0919 | 0.0226 | 0.1452 | 0.8498 | 0.0111 | 0.0077 | 0.046 |
##2.5 predict_model
compare_models
でRMSEなどの指標の確認が行えたのですが、一応念の為predict_model
を用いてモデルの精度を確認します。
predict_model
では、setup時に分けられた訓練用のデータとテスト用のデータのうち、テスト用のデータを用いて、モデルの精度の確認を行います。
print([predict_model(model) for model in top5])
結果
※これ以降、RMSE以外の値は省略
Model | RMSE |
---|---|
CatBoost Regressor | 0.1273 |
Gradient Boosting Regressor | 0.1322 |
Light Gradient Boosting Machine | 0.143 |
Bayesian Ridge | 0.1396 |
Ridge Regression | 0.1396 |
comapare_modelとpredict_modelで得られた結果が異なります。
モデルの予測精度を検証するために使われているデータが異なるのかもしれません。
(以降、モデルの精度の比較は、predict_modelを用います)
##2.5 ハイパーパラメータの調整(今回はskip)
今回は、時間の関係でskipしてしまったのですが、ハイパーパラメータの調整に関して説明します。
PyCaretではハイパーパラメータの調整をtune_model
で行えます。
先ほどcompare_model
で作成されたモデルは、ハイパーパラメータがデフォルト値の状態で作成されたものになるため、tune_model
を実行することで、ハイパーパラメータの調整が行われ、精度の向上が期待できます。
たった一行で済むのが、便利。
tuned_top5 = [tune_model(model, optimize='RMSE') for model in top5]
tune_model
をしなかった理由
tune_model
を実行した結果、精度が全体的に悪化したためです。
おそらくデフォルトの設定では、試行回数が足りず、デフォルトのハイパーパラメータよりも精度の高いハイパーパラメータを見つけきれなかったことが原因だと思われます。
そのため、tune_modelを実行する際は、
しっかりとパラメータを指定してあげるほうが良さそうです。
- n_iterをもっと大きな値にする
- 調整するパラメータを絞る
- 調整を行う範囲を指定する(カスタムグリッドを渡す)
本来であれば、tune_model
で精度が向上するように、上記のことを試して試行錯誤すべきなのですが、
tune_model
は実行に時間がかかる上に、引数として設定できるものが多く、底無し沼にハマっていきそうな予感がしたので
今回はtune_modelを行わず、compare_model
で取得したモデルをそのまま活用していきことにしました。
いつか、tune_model
で効率よくハイパーパラメータの調整が行えるベターなパラメータを調べてみたいです。
##2.6 ensemble_model
PyCaretは、ensemble_model
を用いて、
baggingやboostingのようなアンサンブル学習も1行で実装できます。
詳しい説明は省きますが、bagging、boostingはそれぞれ下記のような効果のある手法になります。
- bagging: モデルの過学習によるバリアンスの向上(値の散らばり度)を抑えるための手法
- boosting: バイアス(実際の値と予測値の差)を低くするための手法
最適化したいのはRMSEだよ、という最低限のことだけをパラメータで指定して、ensemble_model
を実行してみます。
bagged_top5 = [ensemble_model(model, method = 'Bagging', optimize='RMSE') for model in top5]
boosted_top5 = [ensemble_model(model, method = 'Boosting', optimize='RMSE') for model in top5]
結果
|Model|bagging|boosting|compare_models|
|:----|:----|:----|:----|:----|:----|:----|:----|
|CatBoost Regressor|0.1303|0.1318|0.1273|
|Gradient Boosting Regressor|0.1329|0.1347|0.1322|
|Light Gradient Boosting Machine|0.1391|0.1347|0.143|
|Bayesian Ridge|0.1341|0.1551|0.1396|
|Ridge Regression|0.1332|0.1519|0.1396|
下3つのモデルは、baggingによって精度の改善が見られました!!
アンサンブル学習のメリットとして、精度の低い学習器でもある程度の精度が得られるということがよく挙げられるので、精度の低い学習器ほど、baggingやboostingの恩恵を得やすいのかもしれません。
TODO: それぞれのメソッドがどのように作用するかを踏まえて、考察
##2.7 blend_models
PyCaretでは、blend_models
を用いてblendingを実装できます
blendingとは、複数の異なるモデルの予測値をあわせて、最終的な予測値を求めるというアンサンブル学習の手法の1つです。
(分類なら多数決、回帰なら平均値を取るなど)
blendingを行うことで、精度が向上することがあります。
毎度同じく、ほぼデフォルトのまま実行してみます。
blender = blend_models(estimator_list = top5, optimize='RMSE')
結果
Model | RMSE |
---|---|
blending | 0.1266 |
CatBoost Regressor | 0.1273 |
Gradient Boosting Regressor | 0.1322 |
Light Gradient Boosting Machine | 0.143 |
Bayesian Ridge | 0.1396 |
Ridge Regression | 0.1396 |
compare_modelsで取得した単独のモデルと比較して、精度の改善が見られました。
ブレンディングでは、異なるアプローチのモデルを用いると精度が向上しやすいそうなので、もっと多くのモデルをブレンドする、より多様なロジックのモデルを選択するなどすると、より精度が上がるかもしれないです。
##2.8 stack_models
stackingも、ブレンディングと同じく複数の異なるモデルを組み合わせる手法です。
モデルの予測値を特徴量としたモデル(メタモデル)を作成することで、精度向上が期待できるというものです。
PyCaretでは、stack_models
でstackingの実装を行えます。
stacker = stack_models(estimator_list = top5, optimize='RMSE')
デフォルトの設定では、メタモデルにLinearRegression線形回帰が用いられているようです。
結果
Model | RMSE |
---|---|
stacking | 0.1273 |
CatBoost Regressor | 0.1273 |
Gradient Boosting Regressor | 0.1322 |
Light Gradient Boosting Machine | 0.143 |
Bayesian Ridge | 0.1396 |
Ridge Regression | 0.1396 |
compare_modelsで取得した単独のモデルと比較して、stackingでは精度の向上が見られませんでした。
下記のようなことを試してみることで、結果が異なってくるかもしれないです。
- モデルの数を増やす
- 異なるアプローチのモデルを用いる
- メタモデルを変更する
- 3層以上の層で行う(stackingして得られた値を、さらにstackingする)
##2.9 kaggleにsubmitしてみる
せっかくなので、今回作成したモデルの予測結果をkaggleにsubmitしてみます。
結果
|method|Model|kaggle score|
|:----|:----|:----|:----|
|compare_models|CatBoost Regressor| 0.13665 |
|compare_models|Gradient Boosting Regressor| 0.14140 |
|compare_models|Light Gradient Boosting Machine| 0.14465 |
|compare_models|Bayesian Ridge| 0.15173 |
|compare_models|Ridge Regression| 0.16382 |
|bagging|CatBoost Regressor| 0.13887 |
|bagging|Gradient Boosting Regressor| 0.14140 |
|bagging|Light Gradient Boosting Machine| 0.14465 |
|bagging|Bayesian Ridge| 0.15173 |
|bagging|Ridge Regression| 0.16382 |
|boosting|CatBoost Regressor| 0.13748 |
|boosting|Gradient Boosting Regressor| 0.14129 |
|boosting|Light Gradient Boosting Machine| 0.14800 |
|boosting|Bayesian Ridge| 0.18074 |
|boosting|Ridge Regression| 0.22986 |
|blend|-| 0.13321 |
|stack|-|0.13996 |
一番スコアが良かったのは、blending(0.13321)でした。
ちなみに、submit時の順位は5393チーム中の1467位だったため、何も考えずにPyCaretまかせにして作成したモデルでしたが、そこそこの精度がありそうです。
#3 最後に
##3.1 PyCaretをつかってみての感想
手間・時間をかけずにモデルを作成できる
想像以上に手間・時間をかけずにモデル作成ができたので驚きました。
PyCaretだけで精度を突き詰めるのは無理があるかもしれないですが、プロトタイプ的な使い方をするのであれば、全く問題ないとおもいました。
また、モデル作成はPyCaretにまかせて、特徴量の作成に集中するみたいな使い方もできるかなと思います。
comapre_modelsが便利
たくさんのモデルを作成して比較を行うとなるとかなり骨が折れる作業なので、それが1行で済むのはかなりメリットだと思います。
ハイパーパラメータのチューニングは、デフォルトの設定では不十分?
デフォルトでは試行回数が10回と少なすぎるため、精度改善に至らないケースが多そうです。
そのため、tune_model
を実行する際は、試行回数を大きめに設定してあげる必要がありそうです。
また、試行回数を増やすとチューニングにかかる時間が増えていくので、アーリーストップを設定したり、調整を行うハイパーパラメータや調整を行う範囲を限定したりするなどの、効率良くチューニングを行うための工夫が必要になるかなと思います。
ハイパーパラメータのチューニングのアルゴリズムとしてoptunaが使えるみたいなので、活用すればもっと高速化することもできるかもしれません。
アンサンブル学習がお手軽
アンサンブル学習も1行で実装できるのは、かなり便利だと思います。
昔、アンサンブル学習を自力で実装しようとしたことがあるのですが、コードがこんがらがって結局何をしているのかわからなくなって頓挫したことがあります。
そんな自分でも、PyCaretではローコードでアンサンブル学習の実装が行えるため、何層もstackするようなアンサンブル学習もシンプルに実装できるのではないかと思います。
ただ、tune_model
と同様にデフォルトの設定では精度改善につながらないケースが多そうなので、パラメータの試行錯誤は必要そうです。
事前に、「このパラメータで実行すれば精度改善することが多い」というベターな設定を見つけ出す作業はしておくと、効率良くアンサンブル学習を進められる気がします。
PyCaretのドキュメントを読むことで、学びがあった。
今回は、ほぼデフォルトの設定のままでモデルの学習を行ったため紹介できていませんが、PyCaretにはいろいろな機能や設定があります。
それらのドキュメントを読むことで、PyCaretに限らない精度向上のための手法や工夫などを学ぶことができました。
短時間で実装できる点も踏まえて、機械学習の初学者がPyCaretから学び始めるのも、一つの手なのかもと感じました。
##3.2 明日
Ateam Hikkoshi samurai Inc.× Ateam Connect Inc. Advent Calendar 2021 11日目の記事は、いかがでしたでしょうか。
今回始めてPyCaretに触れたのですが、とてもお手軽で便利だなと思いました。
今後も色々試していきたいと思っているので、もしかするとまたPyCaretに関する記事を投稿するかもしれないです。
明日は @lostfind さんがGoについての記事を投稿する予定です。
参考
https://pycaret.org/
https://pycaret.readthedocs.io/en/latest/index.html
https://www.kaggle.com/c/house-prices-advanced-regression-techniques/overview