2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

AutoGluonのTabularPredictorをscikit-learn互換にしてみた

Last updated at Posted at 2021-06-28

はじめに

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の使い方

TabularPredictorWrapperfitの引数には、説明変数や目的変数に加えてTabularPredictorのものと同じオプションを渡すことができます。
以下の例では、学習の制限時間にあたるtime_limitを渡しています。

time_limit = 60
predictor.fit(X_train, y_train, time_limit=time_limit)

もし、オリジナルのTabularPredictorにおけるtuning_dataにあたる引数をfitに渡したい場合は、Xyと同様に、チューニング用のバリデーションデータを説明変数と目的変数に分けたまま、それぞれX_tuningy_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がより使いやすく・活用されやすくなることを期待しています。

  1. 下記でプレビューしている範囲で言えば、age列の値が異なっているように見えるのですが、今回の本題ではないので詳しい調査はしていません。

  2. カテゴリ値が['>50K', '<=50K']であることからわかるように、今回のデータは二値分類ができるものになっています。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?