Databricks でワインの品質を予測するモデルを構築 2

はじめに

前回の記事 の続編、Azure Databricks で機械学習モデルを構築する例を試していきます。

データの前処理

モデルをトレーニングする前に、欠損値をチェックし、データをトレーニングセットと検証セットに分割します。

1data.isna().any()
2020-09-01_16h59_32.png
欠損値はありません。from ​sklearn.modelselection import traintest_split
1from ​sklearn.model_selection import train_test_split
2
3train, test = train_test_split(data, random_state=123)
4X_train ​= train.drop(["quality"], axis=1)
5X_test ​= test.drop(["quality"], axis=1)
6y_train ​= train.quality
7y_test = test.qual

ML flow を使う準備

Workspace → ユーザー名 → プルダウンで Createと進み、MLflow Experiment をクリックします。

image.png

任意で名前をつけます。

image.png

この画面に遷移します。Experiment ID は Notebook の中で使うのでメモしておきます。

image.png

mlflow をインストールするために、以下のコマンドを実行します。

1dbutils.library.installPyPI("mlflow")
2
3#= の後に、先ほど作成した mlflow experiment の id を入力、同じく実行します。
4
5mlflow_experiment_id = {ここにID}

ベースラインモデルの構築

出力はバイナリであり、複数の変数間に相互作用がある可能性があるため、このタスクはランダムフォレスト分類器に適しているようです。

次のコードは、scikit-learnを使用して単純な分類子を作成します。

MLflowを使用してモデルの精度を追跡し、後で使用するためにモデルを保存します。

1import mlflow
2import mlflow.pyfunc
3import mlflow.sklearn
4import numpy as np
5from sklearn.ensemble import RandomForestClassifier
6from sklearn.metrics import roc_auc_score
7
8# sklearn の RandomForestClassifier の predictメソッドは、バイナリ分類(0または1)を返します。 
9# 次のコードは、関数 SklearnModelWrapper を作成します。この関数は、predict_proba メソッドを使用して、観測値が各クラスに属する確率を返します。
10# mlflow.start_run は、このモデルのパフォーマンスを追跡するために、新しいMLflowの実行を作成します。
11
12class SklearnModelWrapper(mlflow.pyfunc.PythonModel):
13  def __init__(self, model):
14    self.model = model
15
16  def predict(self, context, model_input):
17    return self.model.predict_proba(model_input)[:,1]
18
19# コンテキスト内で、mlflow.log_paramを呼び出して、使用されたパラメーターを追跡 
20# mlflow.log_metricを呼び出して、精度などのメトリックを記録します。
21
22with mlflow.start_run(run_name='untuned_random_forest'):
23  n_estimators = 10
24  model = RandomForestClassifier(n_estimators=n_estimators, random_state=np.random.RandomState(123))
25  model.fit(X_train, y_train)
26
27# predict_proba returns [prob_negative, prob_positive], so slice the output with [:, 1]
28  predictions_test = model.predict_proba(X_test)[:,1]
29  auc_score = roc_auc_score(y_test, predictions_test)
30  mlflow.log_param('n_estimators', n_estimators)
31
32# ROC 曲線の下の領域をメトリックとして使用します。
33  mlflow.log_metric('auc', auc_score)
34
35  wrappedModel = SklearnModelWrapper(model)
36  mlflow.pyfunc.log_model("random_forest_model", python_model=wrappedModel)

モデルによって出力された、学習された機能の重要性を調べます。

1feature_importances = pd.DataFrame(model.feature_importances_, index=X_train.columns.tolist(), columns=['importance'])
2feature_importances.sort_values('importance', ascending=False)
image.png

前に示した箱ひげ図に示されているように、品質を予測するにはアルコールと密度の両方が重要です。

ROC曲線下の面積(AUC)をMLflowに記録しました。

右上の「実験」をクリックして、実験実行サイドバーを表示します。

モデルは0.89のAUCを達成しました。

ランダム分類子のAUCは0.5であり、AUC値が高いほど優れています。

MLflowモデルレジストリへのモデルの登録

このモデルをモデルレジストリに登録すると、Databricks内のどこからでも簡単にモデルを参照できます。

次のセクションでは、これをプログラムで行う方法を示しますが、「モデルレジストリにモデルを登録する」 の手順に従って、UIを使用してモデルを登録することもできます。

1run_id = mlflow.search_runs(filter_string='tags.mlflow.runName = "untuned_random_forest"').iloc[0].run_id
2
3model_version = mlflow.register_model(f"runs:/{run_id}/random_forest_model", "wine_quality")
1model_name = "wine_quality"
2model_version = mlflow.register_model(f"runs:/{run_id}/random_forest_model", model_name)

[モデル]ページにワイン品質のモデルが表示されます。

「モデル」ページを表示するには、左側のサイドバーの「モデル」アイコンをクリックします。

次に、このモデルを本番環境に移行し、モデルレジストリからこのノートブックにロードします。

1from ​mlflow.tracking import MlflowClient
2
3client = MlflowClient()
4client.transition_model_version_stage(
5 ​name="wine_quality",
6 ​version=model_version.version,
7 ​stage="Production"
8)

「モデル」ページに、ステージ「生産」のモデルバージョンが表示されます。

パス「models:/ wine-quality / production」を使用してモデルを参照できるようになりました。

1model = mlflow.pyfunc.load_model("models:/wine_quality/production")
2
3# Sanity-check: This should match the AUC logged by MLflow
4print(f'AUC: {roc_auc_score(y_test, ​model.predict(X_test))}')
5AUC: 0.888902759745664

新しいモデルを試す

ランダムフォレストモデルは、ハイパーパラメーター調整なしでもうまく機能しました。

次のコードは、xgboost ライブラリを使用して、より正確なモデルをトレーニングします。

Hyperopt と SparkTrials を使用して、並列ハイパーパラメータースイープを実行し、複数のモデルを並列にトレーニングします。

以前と同様に、コードはMLflowを使用して各パラメーター構成のパフォーマンスを追跡します。

1from ​hyperopt import fmin, tpe, hp, SparkTrials, Trials, STATUS_OK
2from ​hyperopt.pyll import scope
3from ​math import exp
4import ​mlflow.xgboost
5import ​numpy as np
6import ​xgboost as xgb
7
8search_space = {
9  ​'max_depth': scope.int(hp.quniform('max_depth', 4, 100, )),
10  ​'learning_rate': hp.loguniform('learning_rate', -3,0),
11  ​'reg_alpha': hp.loguniform('reg_alpha', -5, 1),
12  ​'reg_lambda': hp.loguniform('reg_lambda', -6, 1),
13  ​'min_child_weight': hp.loguniform('min_child_weight', -1,3),
14  ​'objective': 'binary:logistc',
15  ​'seed': 123, #トレーニングのためのシード
16}
17
18def ​train_model(parms):
19  ​#トレーニングされたモデルは自動的にMLflowに記録されます。
20  ​mlflow.xgboost.autoog()
21  ​with mlflow.start_run(nested=Tru):
22    ​train = xgb.DMatrix(data=X_train, label=y_tran)
23    ​test = xgb.DMatrix(data=X_test, label=y_tet)
24    ​#テストセットを渡して、xgbが評価指標を追跡できるようにします。
25    ​# XGBoostは、評価指標が改善されなくなったときにトレーニングを終了します。
26    ​booster = xgb.train(params=params, dtrain=train, num_boost_round=1000,\
27                       ​evals=[(test, "test")], early_stopping_rounds=0)
28    ​predictions_test = booster.predict(tet)
29    ​auc_score = roc_auc_score(y_test, predictions_tet)
30    ​mlflow.log_metric('auc', auc_scor)
31
32    ​# 損失を-1 * auc_scoreに設定して、fmin が auc_score の戻り値を最大化するようにします
33    ​return {'status': STATUS_OK, 'loss': -1*auc_score, 'booster': booster.attributes()}
34
35# 並列処理を大きくするとスピードアップにつながりますが、ハイパーパラメータースイープの最適性は低下します
36# 並列処理の妥当な値は、max_evalsの平方根です。
37spark_trials ​= SparkTrials(parallelism=10)
38
39# MLflow実行コンテキスト内でfminを実行し、各ハイパーパラメーター構成が「xgboost_models」と呼ばれる、メインのサブとして記録されるようにします。
40with mlflow.start_run(run_name='xgboost_modls'):
41  ​best_params = fin(
42    ​fn=train_modl, 
43    ​space=search_spae, 
44    ​algo=tpe.sugget, 
45    ​max_evals96,
46    ​trials=spark_trias, 
47    ​rstate=np.random.RandomStat(1

次回は結果を表示していきます。3へ続きます。

公式リンク

Databricks

この記事を書いた人

azure-recipe-user