修行の場

知人が言っていました。これは修行だと。

AutoSklearnを使ってみた

背景

AutoSklearnを使ってみました。 ただ、実行してみた結果、GridSearch, Hyperoptよりも得られた分類器の性能が低かったです。 autosklearnのバージョンは0.5.0です。 ちなみに、AmazonDeep learning AMIで構築したUbutu1804のEC2インスタンスではエラーが出ます。 クリーニンストールされた、Ubuntu 18.04では動きました。 どうも動かしてみた感じだと、指定したmetricが直接使われているわけではなく、 別の目的関数で探索が行われてそうな感じです。

APIドキュメントとサンプルを元に通り使っただけですが、 私の環境とデータセットではout of boxで使えませんでした。 現状はautosklearnのソースコードを読む必要がありそうです。

ライブラリが提供する機能の概要

シンプルで、

  • classifierとregressorおよびハイパーパラメータの選択
  • データ処理手法の選択
  • 特徴量処理手法の選択

です。scikit-learnベースなのと、 ディープネットモデルは学習に時間がかかることを考えると、 おそらく、データが集まっていないプロジェクト初期段階で活躍する可能性を秘めています。 ただ、今の所、GridSearchやHyperoptの方が使いやすいです。

アルゴリズムの概要

アルゴリズムは論文にさらっと書かれています。

Efficient and Robust Automated Machine Learning

この論文のポイントは次の2点です。

  • meta learningから、ベイズ最適化をwarm startさせたこと。過去にベイズ最適化で学習させたものを、活用。メタ特徴ベクトル間の距離からtopkを選び、そのconfiguration(ベイズ最適化の探索空間の変数)を選び、それらのconfigurationで学習させることからベイズ最適化がスタートされる。空間は2つあって、メタ学習記録用の空間と、configurationの探索空間の2つです。
  • bayesian optimizationとemsemble selectionを組み合わせた点。meta learningは素人でもまっさきに思いつくけど、途中のアウトプットを組み合わせるのは確かにシンプルで効果的。ディープラーニングではEnsembleがbayesian optimizationより最適になりそうとのことです。

メタ学習には140個のモデルしか使われていないようで、 メタ学習で大まかな開始点が決まるから、メタ学習をうまく活用できていないと、 時間をかけても最終的に得られる性能が低くなってしまう懸念はあります。 なので、データセットによっては性能が低くても不思議ではないです。

インストールして実装する

並列実行刷るサンプルが実用的で役立つので、このサンプルを元に拡張しました。 あとは、APIドキュメントが役立ちます。 結果的にできたプログラムはこんな感じです。 あと、この方法に関しては、日本語のドキュメントもたくさんあります。

得られた結果の詳細を見る

期待と異なる結果が得られた場合や、 どういった結果が得られたか詳細を知る方法についてまとめます。 APIドキュメントには学習以外のことが何故かまとまっておらず... 上記サンプルプログラムのIPython内で実行刷る想定です。

Ensembleされた最終的なモデルの分析

Autosklearnの出力はEnsembleされたモデルです。 Ensembleに使われたモデル一つ一つの詳細を見たりできます。 例えば、下記の例はそれぞれの構成モデルのprecisionを計算します。

refitしていない場合は構成要素からはインデックスが返ってくるので変換します。

for m in automl.get_models_with_weights(): 
   print(sklearn.metrics.precision_score(y_test, np.array(automl._automl[0]._classes).take(np.array(m[1].predict(X_test)))))
    

refitしている場合は、素直です。

for m in automl.get_models_with_weights():  
    ...:    print(sklearn.metrics.precision_score(y_test, np.array(m[1].predict(X_test))))

探索された全モデルの分析

探索空間を調べるためのpublicメソッドは提供されておらず、 プライベートメンバにアクセスしなければなりません。 下記のコードは探索された全モデルのprecisionを計算します。

これはrifitしていない場合です。

import pickle 
 
scores = [] 
model_paths = [] 
for model_path in automl._automl[0]._backend.list_all_models(-1): 
    try: 
        model = pickle.load(open(model_path, 'rb')) 
    except EOFError: 
        print(f"skip eof error {model_path}") 
        continue 
    
    scores.append(sklearn.metrics.precision_score(y_test, np.array(model.predict(X_test) + 1)))
    model_paths.append(model_path)
     
scores = np.array(scores) 
scores.max()

refitするとエラーがでますが、原因は不明。 どちらにせよコードを読まないとだめな気がします。