MLflow モデルをログ記録する
この記事では、トレーニング済みのモデル (または成果物) を MLflow モデルとしてログする方法について説明します。 MLflow がモデルをパッケージ化する方法とそれらのモデルを実行する方法をカスタマイズするための、さまざまな方法を調べます。
成果物の代わりにモデルをログ記録する理由
「MLflow での成果物からモデルまで」では、成果物またはファイルのログと MLflow モデルのログの違いが説明されています。
MLflow のモデルも成果物です。 ただし、モデルは、モデルを作成した人とそれを使用する人の間のコントラクトとして機能する特定の構造を持っています。 このコントラクトは、成果物自体とその意味の間を橋渡しするために役立ちます。
モデルのログには次の利点があります。
mlflow.<flavor>.load_model
で推論のためにモデルを直接読み込むことができ、predict
関数を使用できます- パイプラインの入力でモデルを直接使用できます
- スコアリング スクリプトや環境を示さずにモデルをデプロイできます
- デプロイされたエンドポイントでは Swagger が自動的に有効になり、Azure Machine Learning スタジオでテスト機能を使用できます
- 責任ある AI ダッシュボードを使用できます
このセクションでは、Azure Machine Learning で MLflow のモデルの概念を使う方法について説明します。
自動ログを使用したモデルのログ記録
MLflow の自動ログ機能を使用できます。 自動ログを使うと、MLflow は使用中のフレームワークに、フレームワークが関連があると見なすすべてのメトリック、パラメーター、成果物、モデルをログするよう指示できます。 自動ログを有効にすると、既定でほとんどのモデルがログされます。 状況によっては、一部のフレーバーでモデルがログされない場合があります。 たとえば、PySpark フレーバーでは、特定のサイズを超えるモデルはログされません。
自動ログをアクティブにするには、mlflow.autolog()
または mlflow.<flavor>.autolog()
を使います。 次の例では、autolog()
を使って、XGBoost でトレーニングされた分類器モデルをログしています。
import mlflow
from xgboost import XGBClassifier
from sklearn.metrics import accuracy_score
mlflow.autolog()
model = XGBClassifier(use_label_encoder=False, eval_metric="logloss")
model.fit(X_train, y_train, eval_set=[(X_test, y_test)], verbose=False)
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
ヒント
Scikit-Learn パイプラインのような Machine Learning パイプラインを使う場合は、そのパイプライン フレーバーの autolog
機能を使ってモデルをログします。 モデルのログは、パイプライン オブジェクトで fit()
メソッドが呼び出されると自動的に行われます。 MLflow を使用した XGBoost 分類器のトレーニングと追跡のノートブックでは、パイプラインを使って前処理を含むモデルをログする方法が示されています。
カスタムのシグネチャ、環境、またはサンプルを使用したモデルのログ記録
MLflow の mlflow.<flavor>.log_model
メソッドを使うと、モデルを手動でログできます。 このワークフローでは、モデルのログのさまざまな側面を制御できます。
この方法は次のような場合に使用します。
- 自動的に検出されるものとは異なる pip パッケージまたはconda 環境を示す。
- 入力の例を含める
- 必要なパッケージに特定の成果物を含める
autolog
ではシグネチャが正しく推論されない。 これは、シグネチャが特定の形状になっている必要があるテンソル入力を処理するときに重要です- 何らかの理由で、目的が自動ログの動作でカバーされない
このコード例では、XGBoost 分類器のモデルがログされます。
import mlflow
from xgboost import XGBClassifier
from sklearn.metrics import accuracy_score
from mlflow.models import infer_signature
from mlflow.utils.environment import _mlflow_conda_env
mlflow.autolog(log_models=False)
model = XGBClassifier(use_label_encoder=False, eval_metric="logloss")
model.fit(X_train, y_train, eval_set=[(X_test, y_test)], verbose=False)
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
# Signature
signature = infer_signature(X_test, y_test)
# Conda environment
custom_env =_mlflow_conda_env(
additional_conda_deps=None,
additional_pip_deps=["xgboost==1.5.2"],
additional_conda_channels=None,
)
# Sample
input_example = X_train.sample(n=1)
# Log the model manually
mlflow.xgboost.log_model(model,
artifact_path="classifier",
conda_env=custom_env,
signature=signature,
input_example=input_example)
Note
autolog
では、log_models=False
という構成が指定されています。 これにより、MLflow モデルの自動ログは行われません。 MLflow モデルの自動ログは、後で手動プロセスとして行われます- 入力と出力からシグネチャを直接推論するには、
infer_signature
メソッドを使います mlflow.utils.environment._mlflow_conda_env
メソッドは、MLflow SDK のプライベート メソッドです。 この例では、それによりコードが簡単になりますが、慎重に使ってください。 将来変更される可能性があります。 代わりに、YAML 定義を Python ディクショナリとして手動で生成できます。
predict メソッドで別の動作を使用したモデルのログ記録
mlflow.autolog
または mlflow.<flavor>.log_model
でモデルをログすると、モデルのフレーバーによって推論の実行方法と、モデルから返される内容が決まります。 MLflow では、predict
の結果の生成についてどのような特定の動作も強制されません。 場合によっては、モデルの実行の前と後に、前処理または後処理が必要になることがあります。
このような状況では、入力から出力に直接移動する機械学習パイプラインを実装します。 このような実装は可能であり、パフォーマンス向上のために推奨されることもありますが、実現するのが困難になる可能性があります。 そのような場合は、次のセクションで説明するように、モデルが推論を処理する方法をカスタマイズすると役に立ちます。
カスタム モデルのログ記録
MLflow では、次のような多くの機械学習フレームワークがサポートされています
- CatBoost
- FastAI
- h2o
- Keras
- LightGBM
- MLeap
- MXNet Gluon
- ONNX
- Prophet
- PyTorch
- Scikit-Learn
- spaCy
- Spark MLLib
- statsmodels
- TensorFlow
- XGBoost
ただし、フレーバーの動作を変更したり、MLflow でネイティブにサポートされないモデルをログしたり、異なるフレームワークの複数の要素を使用するモデルをログしたりすることが必要な場合があります。 このような場合は、カスタム モデルのフレーバーの作成が必要になることがあります。
この問題を解決するため、MLflow には pyfunc
というフレーバーが導入されています (Python 関数から開始)。 このフレーバーを使うと、任意のオブジェクトが 2 つの条件を満たしている限り、そのオブジェクトをモデルとしてログできます。
- 少なくとも
predict
メソッドを実装している - Python オブジェクトが
mlflow.pyfunc.PythonModel
を継承している
ヒント
Scikit-learn API を実装しているシリアル化可能なモデルでは、モデルが Scikit-learn を使って構築されたかどうかに関係なく、Scikit-learn フレーバーを使ってモデルをログできます。 モデルを Pickle 形式で保存でき、オブジェクトに predict()
と predict_proba()
メソッドがある場合は、mlflow.sklearn.log_model()
を使って MLflow 実行の内部でモデルをログできます。
既存のモデル オブジェクトを囲むラッパーを作成すると、カスタム モデル用のフレーバーの作成が最も簡単になります。 MLflow によって自動的にシリアル化されてパッケージ化されます。 Python オブジェクトは、オブジェクトをファイル システムにファイル (通常は Pickle 形式) として格納できる場合、シリアル化できます。 実行時には、そのファイルからオブジェクトを具体化できます。 これにより、保存時に使用できたすべての値、プロパティ、メソッドが復元されます。
この方法は次のような場合に使用します。
- Pickle 形式でモデルをシリアル化できる
- トレーニング直後のモデルの状態を維持したい
predict
関数の動作をカスタマイズしたい。
このコード サンプルでは、XGBoost で作成されたモデルをラップして、XGBoost フレーバーの既定の実装とは異なる動作にしています。 クラスの代わりに確率を返します。
from mlflow.pyfunc import PythonModel, PythonModelContext
class ModelWrapper(PythonModel):
def __init__(self, model):
self._model = model
def predict(self, context: PythonModelContext, data):
# You don't have to keep the semantic meaning of `predict`. You can use here model.recommend(), model.forecast(), etc
return self._model.predict_proba(data)
# You can even add extra functions if you need to. Since the model is serialized,
# all of them will be available when you load your model back.
def predict_batch(self, data):
pass
実行でカスタム モデルをログします。
import mlflow
from xgboost import XGBClassifier
from sklearn.metrics import accuracy_score
from mlflow.models import infer_signature
mlflow.xgboost.autolog(log_models=False)
model = XGBClassifier(use_label_encoder=False, eval_metric="logloss")
model.fit(X_train, y_train, eval_set=[(X_test, y_test)], verbose=False)
y_probs = model.predict_proba(X_test)
accuracy = accuracy_score(y_test, y_probs.argmax(axis=1))
mlflow.log_metric("accuracy", accuracy)
signature = infer_signature(X_test, y_probs)
mlflow.pyfunc.log_model("classifier",
python_model=ModelWrapper(model),
signature=signature)
ヒント
この infer_signature
メソッドは、y_probs
を使ってシグネチャを推論します。 ターゲット列にはターゲット クラスがありますが、モデルでは各クラスの 2 つの確率が返されるようになりました。