将 MLflow 模型部署到联机终结点

适用于:Azure CLI ml 扩展 v2(当前)

本文介绍如何将 MLflow 模型部署到 联机终结点 进行实时推理。 将 MLflow 模型部署到联机终结点时,无需指定评分脚本或环境,此功能称为无代码部署

对于无代码部署,Azure 机器学习:

  • 动态安装 conda.yaml 文件中列出的 Python 包。 因此,在容器运行时期间安装依赖项。
  • 提供包含以下项的 MLflow 基本映像或特选环境:

提示

没有公共网络访问权限的工作区中,必须先 打包模型,然后才能将 MLflow 模型部署到没有出口连接的联机终结点。 模型打包功能处于预览状态。 打包模型时,可以避免 Internet 连接的需求,否则 Azure 机器学习需要为 MLflow 模型动态安装必要的 Python 包。

先决条件

  • Azure 订阅。 如果没有 Azure 订阅,请在开始之前创建一个免费帐户

  • 至少具有以下 Azure 基于角色的访问控制(Azure RBAC)角色之一的用户帐户:

    • Azure 机器学习工作区的所有者角色
    • Azure 机器学习工作区的贡献者角色
    • 具有 Microsoft.MachineLearningServices/workspaces/onlineEndpoints/* 权限的自定义角色

    有关详细信息,请参阅管理对 Azure 机器学习工作区的访问

  • 访问 Azure 机器学习:

    安装 Azure CLI 和 Azure CLI 的 ml 扩展。 有关安装步骤,请参阅安装和设置 CLI (v2)。

关于示例

本文中的示例演示如何将 MLflow 模型部署到联机终结点以执行预测。 此示例使用基于糖尿病数据集的 MLflow 模型。 此数据集包含 10 个基线变量:年龄、性别、身体质量指数、平均血压和 6 个从 442 名糖尿病患者获得的血液血清测量。 它还包含兴趣反应,即对基线数据日期一年后的疾病进展进行的定量测量。

该模型是使用 scikit-learn 回归器训练的。 所有必需的预处理都打包为管道,因此此模型是一个从原始数据到预测的端到端管道。

本文中的信息基于 azureml-examples 存储库中的代码示例。 如果克隆存储库,则可以在本地运行本文中的命令,而无需复制或粘贴 YAML 文件和其他文件。 使用以下命令克隆存储库并转到编码语言的文件夹:

git clone https://github.com/Azure/azureml-examples --depth 1
cd azureml-examples/cli

在 Jupyter Notebook 中跟进操作

若要遵循本文中的步骤,请参阅示例存储库中的 “将 MLflow 模型部署到联机终结点 笔记本”。

连接到工作区

连接到 Azure 机器学习工作区:

az account set --subscription <subscription-ID>
az configure --defaults workspace=<workspace-name> group=<resource-group-name> ___location=<___location>

注册模型

只能将已注册的模型部署到联机终结点。 本文中的步骤使用了一个经过训练以适用于 糖尿病数据集的模型。 在这种情况下,克隆的存储库中已有模型的本地副本,因此只需将模型发布到工作区中的注册表。 如果要部署的模型已注册,则可以跳过此步骤。

MODEL_NAME='sklearn-diabetes'
az ml model create --name $MODEL_NAME --type "mlflow_model" --path "endpoints/online/ncd/sklearn-diabetes/model"

如果在运行中记录了模型,该怎么办?

如果你的模型是在运行内记录的,则可以直接注册它。

若要注册模型,需要知道其存储位置:

  • 如果使用 MLflow autolog 功能,则模型的路径取决于模型类型和框架。 检查作业输出以标识模型文件夹的名称。 此文件夹包含名为 MLModel 的文件。
  • 如果使用该方法 log_model 手动记录模型,请将模型的路径作为参数传递给该方法。 例如,如果你使用 mlflow.sklearn.log_model(my_model, "classifier") 记录模型,那么 classifier 就是模型存储的路径。

可以使用 Azure 机器学习 CLI v2 从训练作业输出创建模型。 以下代码使用 ID 为 $RUN_ID 的作业的工件来注册名为 $MODEL_NAME 的模型。 $MODEL_PATH 是作业用于存储模型的路径。

az ml model create --name $MODEL_NAME --path azureml://jobs/$RUN_ID/outputs/artifacts/$MODEL_PATH

将 MLflow 模型部署到联机终结点

  1. 使用以下代码配置要将模型部署到的终结点的名称和身份验证模式:

    通过运行以下命令设置终结点名称。 首先将 YOUR_ENDPOINT_NAME 替换为一个唯一的名称。

    export ENDPOINT_NAME="<YOUR_ENDPOINT_NAME>"
    

    若要配置终结点,请创建一个名为 create-endpoint.yaml 的 YAML 文件,其中包含以下行:

    $schema: https://azuremlschemas.azureedge.net/latest/managedOnlineEndpoint.schema.json
    name: my-endpoint
    auth_mode: key
    
  2. 创建终结点:

    az ml online-endpoint create --name $ENDPOINT_NAME -f endpoints/online/ncd/create-endpoint.yaml
    
  3. 配置部署。 部署是一组资源,用于承载执行实际推理的模型。

    创建包含以下行的名为 sklearn-deployment.yaml 的 YAML 文件:

    $schema: https://azuremlschemas.azureedge.net/latest/managedOnlineDeployment.schema.json
    name: sklearn-deployment
    endpoint_name: my-endpoint
    model:
      name: mir-sample-sklearn-ncd-model
      version: 2
      path: sklearn-diabetes/model
      type: mlflow_model
    instance_type: Standard_DS3_v2
    instance_count: 1
    

    注意

    PyFunc 模型风格支持自动生成 scoring_scriptenvironment。 若要使用不同的模型风格,请参阅 自定义 MLflow 模型部署

  4. 创建部署:

    az ml online-deployment create --name sklearn-deployment --endpoint $ENDPOINT_NAME -f endpoints/online/ncd/sklearn-deployment.yaml --all-traffic
    

    如果终结点没有传出连接,请通过添加 --package-model 标记使用模型打包(预览版):

    az ml online-deployment create --package-model --name sklearn-deployment --endpoint $ENDPOINT_NAME -f endpoints/online/ncd/sklearn-deployment.yaml --all-traffic
    
  5. 将所有流量分配到部署。 到目前为止,终结点有一个部署,但没有为其分配任何流量。

    如果在创建过程中使用标志, --all-traffic 则不需要在 Azure CLI 中执行此步骤。 如果需要更改流量,可以使用 az ml online-endpoint update --traffic 该命令。 有关如何更新流量的详细信息,请参阅 逐步更新流量

  6. 更新终结点配置:

    如果在创建过程中使用标志, --all-traffic 则不需要在 Azure CLI 中执行此步骤。 如果需要更改流量,可以使用 az ml online-endpoint update --traffic 该命令。 有关如何更新流量的详细信息,请参阅 逐步更新流量

调用终结点

部署就绪后,您可以使用它来服务请求。 测试部署的一种方法是在部署客户端中使用内置调用功能。 在示例存储库中,sample-request-sklearn.json 文件包含以下 JSON 代码。 可以将它用作部署的示例请求文件。

{"input_data": {
    "columns": [
      "age",
      "sex",
      "bmi",
      "bp",
      "s1",
      "s2",
      "s3",
      "s4",
      "s5",
      "s6"
    ],
    "data": [
      [ 1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0 ],
      [ 10.0,2.0,9.0,8.0,7.0,6.0,5.0,4.0,3.0,2.0]
    ],
    "index": [0,1]
  }}

注意

此文件使用 input_data 密钥而不是 inputsMLflow 服务使用的密钥。 Azure 机器学习需要不同的输入格式,以便能够自动生成端点的 Swagger 合约。 有关预期输入格式的详细信息,请参阅 MLflow 内置服务器中的部署与 Azure 机器学习推理服务器中的部署

向终结点提交请求:

az ml online-endpoint invoke --name $ENDPOINT_NAME --request-file endpoints/online/ncd/sample-request-sklearn.json

响应应类似于以下文本:

[ 
  11633.100167144921,
  8522.117402884991
]

重要

对于 MLflow 无代码部署,目前不支持 通过本地终结点进行测试

自定义 MLflow 模型部署

无需在 MLflow 模型的部署定义中指定到联机终结点的评分脚本。 但是,如果要自定义推理过程,可以指定评分脚本。

通常想要在以下情况下自定义 MLflow 模型部署:

  • 此模型没有 PyFunc 风格。
  • 需要自定义运行模型的方式。 例如,需要通过 mlflow.<flavor>.load_model() 来使用特定的风格加载模型。
  • 需要在评分例程中执行预处理或后处理,因为模型不执行此处理。
  • 模型的输出不能在表格数据中很好地表示。 例如,输出是一个表示映像的张量。

重要

如果为 MLflow 模型部署指定评分脚本,则还必须指定部署在其中运行的环境。

部署自定义评分脚本

若要部署使用自定义评分脚本的 MLflow 模型,请执行以下步骤。

标识模型文件夹

通过执行以下步骤确定包含 MLflow 模型的文件夹:

  1. 转到 Azure 机器学习工作室

  2. 转到“模型”部分。

  3. 选择要部署的模型,然后转到其 “项目 ”选项卡。

  4. 记下显示的文件夹。 注册模型时,请指定此文件夹。

    显示包含模型项目的文件夹的屏幕截图。

创建评分脚本

以下评分脚本 score.py 提供了如何使用 MLflow 模型执行推理的示例。 可以根据需要调整此脚本,或根据自己的方案更改其中的任何部分。 请注意,您之前标识的文件夹名称 model 包含在函数 init() 中。

import logging
import os
import json
import mlflow
from io import StringIO
from mlflow.pyfunc.scoring_server import infer_and_parse_json_input, predictions_to_json


def init():
    global model
    global input_schema
    # "model" is the path of the mlflow artifacts when the model was registered. For automl
    # models, this is generally "mlflow-model".
    model_path = os.path.join(os.getenv("AZUREML_MODEL_DIR"), "model")
    model = mlflow.pyfunc.load_model(model_path)
    input_schema = model.metadata.get_input_schema()


def run(raw_data):
    json_data = json.loads(raw_data)
    if "input_data" not in json_data.keys():
        raise Exception("Request must contain a top level key named 'input_data'")

    serving_input = json.dumps(json_data["input_data"])
    data = infer_and_parse_json_input(serving_input, input_schema)
    predictions = model.predict(data)

    result = StringIO()
    predictions_to_json(predictions, result)
    return result.getvalue()

警告

MLflow 2.0 公告:示例评分脚本适用于 MLflow 1.X 和 MLflow 2.X。 但是,这些版本的预期输入和输出格式可能会有所不同。 检查环境定义,查看所使用的 MLflow 版本。 MLflow 2.0 仅在 Python 3.8 及更高版本中受支持。

创建环境

下一步是创建可以运行评分脚本的环境。 由于模型是 MLflow 模型,因此 conda 要求也在模型包中指定。 有关 MLflow 模型中包含的文件的详细信息,请参阅 MLmodel 格式。 使用文件中的 conda 依赖项生成环境。 但是,还需要包括 azureml-inference-server-http 包,这是 Azure 机器学习中的联机部署所必需的。

可以创建一个名为 conda.yaml 的 conda 定义文件,其中包含以下行:

channels:
- conda-forge
dependencies:
- python=3.9
- pip
- pip:
  - mlflow
  - scikit-learn==1.2.2
  - cloudpickle==2.2.1
  - psutil==5.9.4
  - pandas==2.0.0
  - azureml-inference-server-http
name: mlflow-env

注意

此 conda 文件的dependencies节包括azureml-inference-server-http包。

使用此 conda 依赖项文件创建环境:

在部署配置中以内联方式创建环境。

创建部署

在 endpoints/online/ncd 文件夹中,创建包含以下行的部署配置文件deployment.yml:

$schema: https://azuremlschemas.azureedge.net/latest/managedOnlineDeployment.schema.json
name: sklearn-diabetes-custom
endpoint_name: my-endpoint
model: azureml:sklearn-diabetes@latest
environment: 
    image: mcr.microsoft.com/azureml/openmpi4.1.0-ubuntu22.04
    conda_file: sklearn-diabetes/environment/conda.yaml
code_configuration:
    code: sklearn-diabetes/src
    scoring_script: score.py
instance_type: Standard_F2s_v2
instance_count: 1

创建部署:

az ml online-deployment create -f endpoints/online/ncd/deployment.yml

处理请求

部署完成后,即可为请求提供服务。 测试部署的一种方法是将该方法与示例请求文件(如以下文件)配合使用 invoke ,sample-request-sklearn.json:

{"input_data": {
    "columns": [
      "age",
      "sex",
      "bmi",
      "bp",
      "s1",
      "s2",
      "s3",
      "s4",
      "s5",
      "s6"
    ],
    "data": [
      [ 1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0 ],
      [ 10.0,2.0,9.0,8.0,7.0,6.0,5.0,4.0,3.0,2.0]
    ],
    "index": [0,1]
  }}

向终结点提交请求:

az ml online-endpoint invoke --name $ENDPOINT_NAME --request-file endpoints/online/ncd/sample-request-sklearn.json

响应应类似于以下文本:

{
    "predictions": [ 
    1095.2797413413252,
    1134.585328803727
    ]
}

警告

MLflow 2.0 公告:在 MLflow 1.X 中,响应不包含 predictions 密钥。

清理资源

如果不再需要终结点,请删除其关联的资源:

az ml online-endpoint delete --name $ENDPOINT_NAME --yes