はじめに
2021/08/17: ライブラリ名を変更したことに伴い、内容を更新
本記事は、前回の記事の続きです。ただ、このまま読み進めても理解できるようにしています。
前回の記事では、有力なAutoMLツールであるAutoGluonのテーブルデータ学習用クラス、TabularPredictor
の話をしました。
そのとき、「このクラスのfit
メソッドはscikit-learnのものとは異なり、説明変数と目的変数の両者を同じデータフレームにまとめて渡す作りになっている」ということを書きました。また、「簡単なラッパクラスを書けば(scikit-learnとの)互換性を実現できそうに見える」とも書きました。
今回は、scikit-learn互換のためのTabularPredictor
のラッパクラスを実際に作ってみましたので、その紹介をしていきます。これがあればTabularPredictor
の持つAutoMLの機能を、既存のコードのscikit-learnの学習処理と差し替えることが容易になります。
TabularPredictorのラッパクラス
TabularPredictorのラッパクラスは、サンプルを含めて「skautogluon」という名前で公開しています。MITライセンスです。
https://github.com/kzkymn/skautogluon/
インストール方法
お使いのLinuxにある、Python3環境で以下のコマンドを実行してインストールできるようにしています。Python3.7以降であれば問題ないと思います。
Macでも動くかもしれませんが、WindowsはAutoGluon自体が非対応のためおそらく動かないと思います。
pip install git+https://github.com/kzkymn/skautogluon.git#egg=skautogluon
使い方
AutoGluonのTabularPredictor
のかわりに、先ほどインストールしたskautogluonにあるTabularPredictorWrapper
を使います。下記のコードでインポートができます。
from skautogluon import TabularPredictorWrapper
学習機能の使い方
TabularPredictorWrapper
はscikit-learnのものと同じく、fit
に説明変数X
と目的変数y
を渡すことで学習ができるようになっています。
save_path = 'agModels-predictClass'
predictor = TabularPredictorWrapper(path=save_path).fit(X=X_train, y=y_train)
なお、TabularPredictorWrapper
のコンストラクタに渡しているpath
はオリジナルのTabularPredictor
にもあったもので、AutoGluonの学習結果やモデルファイルを保存する先のパスです。
このように、オリジナルのTabularPredictor
の持つコンストラクタ引数は基本的に、TabularPredictorWrapper
でもサポートしています。
ちなみに、本記事の例として使っているデータはsklearn.datasets.fetch_openml
関数でdata_id=179
を指定して取得したものです。これはちょうど公式チュートリアルのtabular-quickstartで使っているデータとほぼ等価1なものにあたります。
具体的には下記のようなコードでデータを取得し、学習用・テスト用にデータを分けていると考えて下さい。
X, y = sklearn.datasets.fetch_openml(data_id=179, return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.33, random_state=42)
説明変数・目的変数の外観は、それぞれ以下のとおりです。
- 説明変数5行プレビュー
age | workclass | fnlwgt | education | education-num | marital-status | occupation | relationship | race | sex | capitalgain | capitalloss | hoursperweek | native-country | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2 | State-gov | 77516 | Bachelors | 13 | Never-married | Adm-clerical | Not-in-family | White | Male | 1 | 0 | 2 | United-States |
1 | 3 | Self-emp-not-inc | 83311 | Bachelors | 13 | Married-civ-spouse | Exec-managerial | Husband | White | Male | 0 | 0 | 0 | United-States |
2 | 2 | Private | 215646 | HS-grad | 9 | Divorced | Handlers-cleaners | Not-in-family | White | Male | 0 | 0 | 2 | United-States |
3 | 3 | Private | 234721 | 11th | 7 | Married-civ-spouse | Handlers-cleaners | Husband | Black | Male | 0 | 0 | 2 | United-States |
4 | 1 | Private | 338409 | Bachelors | 13 | Married-civ-spouse | Prof-specialty | Wife | Black | Female | 0 | 0 | 2 | Cuba |
- 目的変数5行プレビュー2
0 <=50K
1 <=50K
2 <=50K
3 <=50K
4 <=50K
Name: class, dtype: category
Categories (2, object): ['>50K', '<=50K']
学習が始まると、以下のようなメッセージが出力されていきます。
Beginning AutoGluon training ...
AutoGluon will save models to "agModels-predictClass/"
AutoGluon Version: 0.2.0
Train Data Rows: 32724
Train Data Columns: 14
Preprocessing data ...
AutoGluon infers your prediction problem is: 'binary' (because only two unique label-values observed).
2 unique label values: ['<=50K', '>50K']
If 'binary' is not the correct problem_type, please manually specify the problem_type argument in fit() (You may specify problem_type as one of: ['binary', 'multiclass', 'regression'])
Selected class <--> label mapping: class 1 = >50K, class 0 = <=50K
(後略)
推論やその他機能の使い方
fit
以外のメソッドの使い方は、特段TabularPredictor
のものとは変わりません。
例えばpredict
なら、説明変数のみが入ったデータフレームを渡せば推論結果を得ることができます。
y_pred = predictor.predict(X_test)
print("Predictions: \n", y_pred)
上のコードであれば、以下のような出力が得られるはずです。
Predictions:
7762 <=50K
23881 <=50K
30507 <=50K
28911 <=50K
19484 <=50K
...
15968 >50K
37984 >50K
31513 >50K
46024 <=50K
2946 <=50K
Name: y, Length: 16118, dtype: object
オリジナルのTabularPredictor
にはleaderboard
メソッドがあり、学習時に作ったモデルを精度順に表示することができます。
TabularPredictorWrapper
にもleaderboard
メソッドがあります。
ただし上で説明したfit
メソッドと仕様を合わせるため、オリジナルのものとは違って、説明変数と目的変数を別々の引数でleaderboard
に渡す仕様にしています。
predictor.leaderboard(X_test, y_test, silent=True)
こちらの実行結果は以下のような表になります。今回のデータではブースティング木やニューラルネットが上位を占めていることがわかります。
model | score_test | score_val | pred_time_test | pred_time_val | fit_time | pred_time_test_marginal | pred_time_val_marginal | fit_time_marginal | stack_level | can_infer | fit_order | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | LightGBMXT | 0.856744 | 0.86 | 0.0326574 | 0.0175004 | 0.327207 | 0.0326574 | 0.0175004 | 0.327207 | 1 | True | 3 |
1 | LightGBM | 0.856682 | 0.8596 | 0.0928633 | 0.0175211 | 0.314495 | 0.0928633 | 0.0175211 | 0.314495 | 1 | True | 4 |
2 | XGBoost | 0.856062 | 0.8536 | 0.143337 | 0.0195582 | 1.18695 | 0.143337 | 0.0195582 | 1.18695 | 1 | True | 11 |
3 | NeuralNetMXNet | 0.855813 | 0.858 | 2.01173 | 0.307559 | 56.0177 | 2.01173 | 0.307559 | 56.0177 | 1 | True | 12 |
4 | NeuralNetFastAI | 0.854821 | 0.8564 | 0.202868 | 0.0504737 | 22.9124 | 0.202868 | 0.0504737 | 22.9124 | 1 | True | 10 |
5 | CatBoost | 0.85451 | 0.8536 | 0.0263336 | 0.0155103 | 2.28564 | 0.0263336 | 0.0155103 | 2.28564 | 1 | True | 7 |
6 | WeightedEnsemble_L2 | 0.854014 | 0.8636 | 3.74805 | 1.71425 | 90.8635 | 0.00588965 | 0.00274515 | 0.953759 | 2 | True | 14 |
7 | LightGBMLarge | 0.851594 | 0.8528 | 0.0429571 | 0.0317025 | 3.88792 | 0.0429571 | 0.0317025 | 3.88792 | 1 | True | 13 |
8 | RandomForestEntr | 0.833664 | 0.8352 | 0.264694 | 0.227056 | 1.31782 | 0.264694 | 0.227056 | 1.31782 | 1 | True | 6 |
9 | RandomForestGini | 0.833478 | 0.8348 | 0.27859 | 0.112005 | 1.09688 | 0.27859 | 0.112005 | 1.09688 | 1 | True | 5 |
10 | ExtraTreesEntr | 0.831679 | 0.8348 | 0.319609 | 0.459777 | 0.928697 | 0.319609 | 0.459777 | 0.928697 | 1 | True | 9 |
11 | ExtraTreesGini | 0.830996 | 0.8344 | 0.354856 | 0.458674 | 0.898111 | 0.354856 | 0.458674 | 0.898111 | 1 | True | 8 |
12 | KNeighborsUnif | 0.726765 | 0.7328 | 0.114152 | 0.108575 | 0.0209086 | 0.114152 | 0.108575 | 0.0209086 | 1 | True | 1 |
13 | KNeighborsDist | 0.717769 | 0.7164 | 0.122203 | 0.112647 | 0.0328131 | 0.122203 | 0.112647 | 0.0328131 | 1 | True | 2 |
ちょっと進んだfitの使い方
TabularPredictorWrapper
のfit
の引数には、説明変数や目的変数に加えてTabularPredictor
のものと同じオプションを渡すことができます。
以下の例では、学習の制限時間にあたるtime_limit
を渡しています。
time_limit = 60
predictor.fit(X_train, y_train, time_limit=time_limit)
もし、オリジナルのTabularPredictor
におけるtuning_data
にあたる引数をfit
に渡したい場合は、X
やy
と同様に、チューニング用のバリデーションデータを説明変数と目的変数に分けたまま、それぞれX_tuning
とy_tuning
に渡します。
具体例は以下のとおりです。
# load datasets same as train.csv and test.csv in https://autogluon.s3.amazonaws.com/datasets/Inc/
X, y = sklearn.datasets.fetch_openml(data_id=179, return_X_y=True)
X_train, X_test_base, y_train, y_test_base = train_test_split(
X, y, test_size=0.33, random_state=42)
X_val = X_test_base[:int(len(X_test_base)/2)]
y_val = y_test_base[:int(len(X_test_base)/2)]
X_test = X_test_base[int(len(X_test_base)/2):]
y_test = y_test_base[int(len(y_test_base)/2):]
predictor = TabularPredictorWrapper(eval_metric=metric).fit(
X=X_train, y=y_train,
X_tuning=X_val, y_tuning=y_val,
time_limit=time_limit)
おわりに
本記事で紹介したTabularPredictorWrapper
があれば、冒頭の説明どおりにTabularPredictor
の機能を既存のコードのscikit-learnの学習処理と差し替えることができ、すぐさまAutoGluonの持つ豊富なAutoMLの機能を試すことができます。また、Pipelineに組み込んで実行することもできるようになります。
TabularPredictorWrapper
により、AutoGluonがより使いやすく・活用されやすくなることを期待しています。