本文将介绍如何将训练的机器学习模型或工件记录为 MLflow 模型。 MLflow 是用于管理machine learning工作流的开源框架。 本文探讨用于自定义 MLflow 包和运行模型的方式的各种选项。
先决条件
- MLflow SDK
mlflow包(版本 2.16.x 或更早版本) - Azure Machine Learning MLflow 插件
azureml-mlflow - 包
xgboost(版本 2.1.1 或更低版本) -
scikit-learn包
重要
Azure Machine Learning与 MLflow 2.16 及更早版本兼容。 MLflow 2.17 及更高版本引入的工件存储库和 LoggedModels API 变更目前不受 azureml-mlflow 插件支持。 锁定 MLflow 和 XGBoost 版本以避免兼容性问题。
pip install "mlflow<=2.16.2" azureml-mlflow "xgboost<=2.1.1" scikit-learn
使用自动日志记录记录模型
使用 MLflow autolog 功能自动记录模型。 使用自动日志记录时,MLflow 会捕获框架中的所有相关指标、参数、artifacts和模型。 记录的数据取决于框架。 默认情况下,如果启用自动日志记录,则会记录大多数模型。 在某些情况下,某些版本不会保存模型。 例如,PySpark 风格不会记录超过特定大小的模型。
使用mlflow.autolog或mlflow.<flavor>.autolog来激活自动日志记录。 以下代码使用 autolog 记录使用 XGBoost 训练的分类器模型:
import mlflow
from xgboost import XGBClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# Load sample data and split into train/test sets.
X, y = load_breast_cancer(return_X_y=True, as_frame=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
mlflow.autolog()
model = XGBClassifier(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)
参考:mlflow.autolog | XGBClassifier | accuracy_score
注释
本文中的其余代码示例重复使用X_train前面的示例数据设置中的变量X_testy_train和y_test变量。
小窍门
如果使用机器学习流水线(如 scikit-learn 流水线),请使用该流水线类型的 autolog 功能记录模型数据。 在管道对象上调用 fit 方法时,模型日志记录会自动运行。 有关记录模型的笔记本(其中包括预处理和使用流水线),请参阅使用 MLflow 训练和跟踪 XGBoost 分类器。
为什么选用日志模型而不是工件?
记录模型而非原始工件,为模型创建者和使用者之间提供了一个结构化的协议。 有关详细比较,请参阅 MLflow 中的 Artifacts 和模型。
模型日志记录具有以下优势:
- 可用于
mlflow.<flavor>.load_model直接加载模型进行推理,并且可以使用函数predict。 - 管道输入可以直接使用模型。
- 无需指定评分脚本或环境即可部署模型。
- 在部署的终结点中,Swagger 自动启用。 因此,可以使用Azure Machine Learning studio中的测试功能测试模型。
- 可以使用负责任 AI 仪表板。 有关详细信息,请参阅 在 Azure Machine Learning studio 中使用负责任的 AI 仪表板。
使用自定义签名、环境或示例的日志模型
使用 MLflow mlflow.<flavor>.log_model 方法手动记录模型。 此工作流可让你控制模型日志记录的各个方面。
在以下情况下使用此方法:
- 您希望指定一个与自动检测到的包或环境不同的 Conda 环境或 pip 包。
- 你想要包括输入示例。
- 你想要在软件包中包含特定构件。
- 该方法
autolog无法正确推断签名。 使用张量输入时,可能会出现此问题,这要求签名具有特定形状。 -
autolog方法不满足您的所有需求。
以下代码记录 XGBoost 分类器模型:
import mlflow
from xgboost import XGBClassifier
from sklearn.metrics import accuracy_score
from mlflow.models import infer_signature
mlflow.autolog(log_models=False)
with mlflow.start_run():
model = XGBClassifier(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)
# Infer the signature.
signature = infer_signature(X_test, y_test)
# Sample the data.
input_example = X_train.sample(n=1)
# Log the model manually.
mlflow.xgboost.log_model(model,
artifact_path="classifier",
pip_requirements=["xgboost>=2.0"],
signature=signature,
input_example=input_example)
参考:mlflow.xgboost.log_model | infer_signature
注释
- 对
autolog的调用使用log_models=False配置。 此设置关闭自动 MLflow 模型日志记录。 稍后使用log_model方法手动记录模型。 - 该方法
infer_signature尝试直接从输入和输出推断签名。 - 该
pip_requirements参数指定模型所需的包。 或者,可以将conda_env参数与字典或 YAML 文件一起使用。
使用修改后的预测行为的日志模型
使用 mlflow.autolog 或 mlflow.<flavor>.log_model 记录模型时,模型风格决定如何执行推理。 口味还决定模型的返回结果。 MLflow 不会强制实施有关生成 predict 结果的特定行为。 在某些情况下,可能需要预处理或后处理您的数据。
在这种情况下,可以实现机器学习管道,将输入直接转换为输出。 虽然这种类型的实现有时可以提高性能,但实现可能非常困难。 在这种情况下,自定义模型处理推理的方式会很有帮助。 有关详细信息,请参阅下一部分, 记录自定义模型。
记录自定义模型
MLflow 支持许多machine learning框架,包括 CatBoost、Keras、LightGBM、ONNX、PyTorch、scikit-learn、Spark MLlib、TensorFlow、XGBoost 等。 有关完整列表,请参阅内置模型版本。
但是,可能需要更改模型版本的运作方式,或记录 MLflow 原生不支持的模型。 或者,可能需要记录使用各种框架中的多个元素的模型。 在这些情况下,可以创建自定义模型风格。
为了解决此问题,MLflow 提供了 PyFunc 风格,这是 Python 模型的默认模型接口。 只要该对象满足两个条件,此模式即可将任何对象记录为模型:
- 您至少要实现
predict方法。 - Python 对象继承自
mlflow.pyfunc.PythonModel类。
小窍门
实现 scikit-learn API 的可序列化模型可使用 scikit-learn 风格来记录模型,无论该模型是否由 scikit-learn 构建。 如果可以将模型以 Pickle 格式持久化,并且对象至少具有 predict 和 predict_proba 方法,则可以使用 mlflow.sklearn.log_model 在 MLflow 运行中记录模型。
为自定义模型创建风格的最简单方法是围绕现有模型对象创建包装器。 MLflow 为你序列化和打包模型。 当对象可以作为文件(通常为 Pickle 格式)存储在文件系统中时,Python 对象是可串行化的。 在运行时,可以从该文件加载对象。 加载会还原保存时可用的所有值、属性和方法。
在以下情况下使用此方法:
- 可以使用 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, params=None):
# The next line uses a prediction function. However, you could also use model.recommend(), model.forecast(), or a similar function instead.
return self._model.predict_proba(data)
# You can add extra functions if you need to. Because the model is serialized,
# all of them are available when you load your model.
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)
with mlflow.start_run():
model = XGBClassifier(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(artifact_path="classifier",
python_model=ModelWrapper(model),
signature=signature)
参考:mlflow.pyfunc.log_model | PythonModel
小窍门
在前面的代码中,infer_signature 方法使用 y_probs 推断签名。 目标列包含目标类,但模型为每个类返回两个概率。