Auto-sklearn2.0試してみた

# はじめに

2020年7月8日にAuto-sklearn2.0の論文( https://arxiv.org/abs/2007.04074 )がarXiv上に公開されました。
今までAuto-sklearnの存在は知っていたものの、使ったことがなかったのでこれを機に試してみました。

### 論文のななめ読み

著者はFreiburg-Hannoverのグループ( https://www.automl.org/ )の方々。
論文によるとAuto-sklearn2.0のアップデート内容は、モデル選択のストラテジーの改善、ポートフォリオの構築、自動ポリシー選択とのことですが、詳細は論文を参照してください。
（モデル選択、ハイパラチューニング、前処理部分含めた全体の構成の３点を改善したと理解しましたが、チラ見程度なので間違えていたらすみません）

### やること

あるデータに対して、Auto-sklearn1.0、Auto-sklearn2.0をそれぞれ実行して、予測精度がどうなるのか比較してみたいと思います。
また、Auto-sklearnの中で閉じるのは面白くないので、同じデータに対してAuto-Gluonでも予測させて精度がどうなるのか見てみたいと思います。

# 環境

今回はGoogle Colaboratoryを使用します（GPUは使っていません）。

# 実施した内容

## Auto-sklearnのインストール

https://automl.github.io/auto-sklearn/master/installation.html
こちらに記載されているように以下の内容を実行します。
2020年7月22日時点でインストール時にエラーなどは起こりませんでした。

```py
!sudo apt-get install build-essential swig
!curl https://raw.githubusercontent.com/automl/auto-sklearn/master/requirements.txt | xargs -n 1 -L 1 pip install
!pip install auto-sklearn
```

https://automl.github.io/auto-sklearn/master/
こちらにAuto-sklearn2.0のインポート方法が記載されているので、以下のように実行します。
なお、Github( https://github.com/automl/auto-sklearn )の中身を見ると、Auto-sklearn2.0のRegressorは見当たりませんでした。今後のアップデートに期待です。

```py
import sklearn.model_selection
import sklearn.datasets
import sklearn.metrics
from sklearn import preprocessing

from autosklearn.experimental.askl2 import AutoSklearn2Classifier
```


## データのロード

Auto-sklearn2.0がClassifierしかないので、公式のexample( https://automl.github.io/auto-sklearn/master/examples/example_feature_types.html )を参考にしました。
データは[こちら](https://www.openml.org/d/179)にある、収入が一定の額以上か否かを当てるタスクの物を使用しています。

```py
X, y = sklearn.datasets.fetch_openml(data_id=179, return_X_y=True)

# y needs to be encoded, as fetch openml doesn't download a float
y = preprocessing.LabelEncoder().fit_transform(y)

X_train, X_test, y_train, y_test = \
     sklearn.model_selection.train_test_split(X, y, random_state=1)

# Create feature type list from openml.org indicator and run autosklearn
data = sklearn.datasets.fetch_openml(data_id=179, as_frame=True)
feat_type = ['Categorical' if x.name == 'category' else 'Numerical' for x in data['data'].dtypes]
```

## Auto-sklearn2.0の実行

今回はお試しなので、時間を5分に設定して次のように実行しました。


```py
%%time 

cls = AutoSklearn2Classifier(
    time_left_for_this_task=300,
    seed=1,
    metric=autosklearn.metrics.log_loss
)
cls.fit(X_train, y_train, feat_type=feat_type)
#CPU times: user 16.8 s, sys: 557 ms, total: 17.3 s
#Wall time: 4min 56s
```

ただし、このまま実行すると以下のwarningが大量に表示されました。

```
/usr/local/lib/python3.6/dist-packages/sklearn/base.py:197: FutureWarning: From version 0.24, get_params will raise an AttributeError if a parameter cannot be retrieved as an instance attribute. Previously it would return None.
  FutureWarning)
```

とくに問題ないと思いますが、もし気になる場合は、``warnings``で無視するといいかもしれません。

```py
import warnings
warnings.simplefilter('ignore')
```

AccuracyとAUCで予測精度を出すと次のような結果になりました。

```py
predictions = cls.predict(X_test)
print("Accuracy score ", sklearn.metrics.accuracy_score(y_test, predictions))
print("AUC ", sklearn.metrics.roc_auc_score(y_test, predictions))
#Accuracy score  0.8585701416755385
#AUC  0.7749035627902573
```

## Auto-sklearn1.0の実行

従来のAuto-sklearnを使う場合は、``import autosklearn.classification``でライブラリをインポートして、同じように実行します。

```py

%%time 

cls = autosklearn.classification.AutoSklearnClassifier(
    time_left_for_this_task=300,
    per_run_time_limit=30,
    seed=1,
    metric=autosklearn.metrics.log_loss
)
cls.fit(X_train, y_train, feat_type=feat_type)
#CPU times: user 5.77 s, sys: 1.08 s, total: 6.86 s
#Wall time: 4min 55s
```

```py

predictions = cls.predict(X_test)
print("Accuracy score ", sklearn.metrics.accuracy_score(y_test, predictions))
print("AUC ", sklearn.metrics.roc_auc_score(y_test, predictions))
#Accuracy score  0.8490705101957252
#AUC  0.7580882714036629
```

今回はモデル構築時にCross-validationをしていないので、もう少し慎重に比較しないといけないところですが、単純に数値だけ比較するとAuto-sklearn2.0の方が良い結果となりました。


## Auto-Gluonの実行

Auto-Gluonについての詳細は別の記事( https://qiita.com/dyamaguc/items/dded739f35e59a6491c8 )を参照してください。
Auto-Gluonの場合は、インプットのデータに``numpy``の``ndarray``を指定できないため、``pandas``の``DataFrame``に変換する処理を追加しています。
それ以外は基本的に同じにしています。

```py
X, y = sklearn.datasets.fetch_openml(data_id=179, return_X_y=True)

# y needs to be encoded, as fetch openml doesn't download a float
y = preprocessing.LabelEncoder().fit_transform(y)

X_train, X_test, y_train, y_test = \
     sklearn.model_selection.train_test_split(X, y, random_state=1)

X_train_ = pd.DataFrame( X_train )
y_train_ = pd.DataFrame(y_train, columns=['class'])
train_data = pd.concat( [X_train_, y_train_ ], axis=1)
```

auto-stackを使用する設定として、実行します。

```py
%%time

long_time = 5*60 # for quick demonstration only, you should set this to longest time you are willing to wait
dir = 'agModels-predictClass-autostack' # specifies folder where to store trained models
predictor = task.fit(
    train_data=train_data, 
    label='class', 
    auto_stack=True, 
    output_directory = dir,
    eval_metric='log_loss',
    time_limits=long_time)
#CPU times: user 9min 21s, sys: 11.3 s, total: 9min 32s
#Wall time: 5min 15s
```


```py

import sklearn.metrics
X_test_ = pd.DataFrame( X_test )
predictions = predictor.predict(X_test_)
print("Accuracy score ", sklearn.metrics.accuracy_score(y_test, predictions))
print("AUC ", sklearn.metrics.roc_auc_score(y_test, predictions))
#Accuracy score  0.8609450495454918
#AUC  0.780458426444995
```

今回のデータセットと設定では、Auto-Gluonが一番良い結果となりました。

# まとめ

今回はAuto-sklearn2.0に触れて見ましたが、この手のAutoMLは本当に楽で、そこそこの結果を出してくれるので、便利だなと思いました。