将自定义 ML 模型转换为 MLflow 格式化模型

本文介绍如何将自定义 ML 模型转换为 MLflow 格式。 MLflow 是一个开放源代码库,用于管理机器学习试验的生命周期。 在某些情况下,你可能会使用没有内置 MLflow 模型风格支持的机器学习框架。 由于缺少内置的 MLflow 模型风格,你无法使用 MLflow 模型 Fluent API 记录或注册模型。 若要解决此问题,可以将模型转换为 MLflow 格式,这样就可以利用 Azure 机器学习和 MLflow 模型的以下优势。

借助 Azure 机器学习,MLflow 模型可获得以下附加优势:

  • 无代码部署
  • 采用开放源代码标准格式的可移植性
  • 能够部署在本地和云上

MLflow 支持各种机器学习框架,例如 Scikit-learn、Keras 和 PyTorch。 MLflow 可能不会涵盖每个用例。 例如,你可能希望使用 MLflow 不原生支持的框架来创建一个 MLflow 模型。 在运行作业时,可能需要更改模型执行预处理或后处理的方式。 若要详细了解 MLflow 模型,请参阅 MLflow 中从工件到模型

如果未使用 MLflow 训练模型,并且想要使用 Azure 机器学习的 MLflow 无代码部署产品/服务,则需要将自定义模型转换为 MLflow。 有关详细信息,请参阅自定义 Python 模型

先决条件

  • Python 3.10 或更高版本

  • 在 Python 环境中安装的以下包:

    pip install mlflow scikit-learn cloudpickle
    

注意

本文中的代码示例使用 scikit-learncloudpickle。 如果使用其他框架,请改为安装相应的包。

为模型创建 Python 包装器

将模型转换为 MLflow 支持的格式之前,需要为模型创建 Python 包装器。 以下代码展示了如何为 sklearn 模型创建 Python 包装器。


# Load training and test datasets
from sys import version_info
import sklearn
import mlflow.pyfunc


PYTHON_VERSION = "{major}.{minor}.{micro}".format(major=version_info.major,
                                                  minor=version_info.minor,
                                                  micro=version_info.micro)

# Train and save an SKLearn model
sklearn_model_path = "model.pkl"

artifacts = {
    "sklearn_model": sklearn_model_path
}

# create wrapper
class SKLearnWrapper(mlflow.pyfunc.PythonModel):

    def load_context(self, context):
        import pickle
        self.sklearn_model = pickle.load(open(context.artifacts["sklearn_model"], 'rb'))
    
    def predict(self, context, model_input, params=None):
        return self.sklearn_model.predict(model_input)

创建 Conda 环境

接下来,为包含所有必要依赖项的新 MLflow 模型创建 Conda 环境。 如果未指定,则会从当前安装推断环境。 如果没有,也可以指定它。


import cloudpickle
conda_env = {
    'channels': ['defaults'],
    'dependencies': [
      'python={}'.format(PYTHON_VERSION),
      'pip',
      {
        'pip': [
          'mlflow',
          'scikit-learn=={}'.format(sklearn.__version__),
          'cloudpickle=={}'.format(cloudpickle.__version__),
        ],
      },
    ],
    'name': 'sklearn_env'
}

加载 MLflow 格式的模型并测试预测

环境准备就绪后,将 SKlearnWrapper、Conda 环境和新创建的工件字典传递给 mlflow.pyfunc.save_model() 方法。 这样做可以将模型保存到磁盘中。

from mlflow.models import infer_signature
import pickle

mlflow_pyfunc_model_path = "sklearn_mlflow_pyfunc_custom"

# Create a model signature from a sample of your test data.
# Azure Machine Learning uses the signature to generate a scoring schema for deployed endpoints.
test_input = "<insert test data>"
sklearn_loaded = pickle.load(open(sklearn_model_path, 'rb'))
signature = infer_signature(test_input, sklearn_loaded.predict(test_input))

mlflow.pyfunc.save_model(path=mlflow_pyfunc_model_path, python_model=SKLearnWrapper(),
                         conda_env=conda_env, artifacts=artifacts, signature=signature)

为了确保你新保存的 MLflow 格式模型在保存期间未更改,请加载你的模型并输出测试预测来比较原始模型。

以下代码会从 mlflow 格式模型输出测试预测,并从 sklearn 模型输出测试预测。 它会将测试预测保存到磁盘以供比较。

loaded_model = mlflow.pyfunc.load_model(mlflow_pyfunc_model_path)

input_data = "<insert test data>"
# Evaluate the model
import pandas as pd
test_predictions = loaded_model.predict(input_data)
print(test_predictions)

# load the model from disk
import pickle
loaded_model = pickle.load(open(sklearn_model_path, 'rb'))
result = loaded_model.predict(input_data)
print(result)

注册 MLflow 格式化模型

确认模型已正确保存后,可以创建测试运行。 注册 MLflow 格式模型并将其保存到你的模型注册表。

with mlflow.start_run():
    mlflow.pyfunc.log_model(name=mlflow_pyfunc_model_path,
                            python_model=SKLearnWrapper(),
                            registered_model_name="Custom_mlflow_model",
                            conda_env=conda_env,
                            artifacts=artifacts,
                            signature=signature)

重要

在某些情况下,你可能会使用没有内置 MLflow 模型风格支持的机器学习框架。 例如,vaderSentiment 库是用于情绪分析的标准自然语言处理 (NLP) 库。 由于它缺少内置的 MLflow 模型风格,你无法使用 MLflow 模型 Fluent API 记录或注册模型。 有关如何保存、记录和注册没有受支持的内置 MLflow 模型风格的模型的示例,请参阅 Log MLflow 模型