はじめに
前回の記事 の続編、Azure Databricks で機械学習モデルを構築する例を試していきます。
データの前処理
モデルをトレーニングする前に、欠損値をチェックし、データをトレーニングセットと検証セットに分割します。
1data.isna().any()
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.qualML flow を使う準備
Workspace → ユーザー名 → プルダウンで Createと進み、MLflow Experiment をクリックします。
任意で名前をつけます。
この画面に遷移します。Experiment ID は Notebook の中で使うのでメモしておきます。
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)
前に示した箱ひげ図に示されているように、品質を予測するにはアルコールと密度の両方が重要です。
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へ続きます。