你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

教程:一天中的 Azure 机器学习

适用于:Python SDK azure-ai-ml v2(当前版)

了解数据科学家如何使用 Azure 机器学习 (Azure ML) 来训练模型,然后使用模型进行预测。 本教程将帮助你熟悉 Azure ML 的核心概念及其最常见的用法。

你将了解如何提交命令作业,以在指定的计算资源上运行训练脚本,该计算资源配置了运行脚本所需的作业环境。

训练脚本处理数据准备,然后训练并注册模型。 拥有模型后,将它部署为终结点,然后调用终结点进行推理。

要执行的步骤如下所示:

  • 连接到 Azure ML 工作区
  • 创建计算资源和作业环境
  • 创建训练脚本
  • 创建并运行命令作业以在计算资源上运行训练脚本,该计算资源配置了适当的作业环境
  • 查看训练脚本的输出
  • 将新训练的模型部署为终结点
  • 调用 Azure ML 终结点进行推理

先决条件

运行笔记本

在顶部栏上,选择在快速入门:Azure 机器学习入门期间创建的计算实例以用于运行笔记本。

重要

本教程的其余部分包含教程笔记本的单元格。 将其复制/粘贴到新笔记本中,或者立即切换到该笔记本(如果已克隆该笔记本)。

若要在笔记本中运行单个代码单元,请单击代码单元,然后按 Shift+Enter。 或者,通过从顶部工具栏中选择“全部运行”来运行整个笔记本。

连接到工作区

在深入了解代码之前,需要连接到 Azure ML 工作区。 工作区是 Azure 机器学习的顶级资源,为使用 Azure 机器学习时创建的所有项目提供了一个集中的处理位置。

需要使用 DefaultAzureCredential 来访问工作区。 DefaultAzureCredential 用于处理大多数 Azure SDK 身份验证方案。

# Handle to the workspace
from azure.ai.ml import MLClient

# Authentication package
from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()

在下一个单元格中,输入你的订阅 ID、资源组名称和工作区名称。 若要查找这些值:

  1. 在右上方的 Azure 机器学习工作室工具栏中,选择你的工作区名称。
  2. 将工作区、资源组和订阅 ID 的值复制到代码中。
  3. 需要复制一个值,关闭区域并粘贴,然后返回下一个值。
# Get a handle to the workspace
ml_client = MLClient(
    credential=credential,
    subscription_id="<SUBSCRIPTION_ID>",
    resource_group_name="<RESOURCE_GROUP>",
    workspace_name="<AML_WORKSPACE_NAME>",
)

结果是用于管理其他资源和作业的工作区处理程序。

重要

创建 MLClient 不会连接到工作区。 客户端初始化是惰性操作,它会等待完成首次调用(在以下笔记本中,这种调用发生在计算资源创建期间)。

创建计算资源以运行作业

需要计算资源来运行作业。 它可以是具有 Linux 或 Windows OS 的单节点或多节点计算机,也可以是 Spark 等特定计算结构。

需要预配 Linux 计算群集。 请参阅 VM 大小和价格的完整列表

此示例只需要一个基本群集,因此你将使用具有 2 个 vCPU 核心、7 GB RAM 的 Standard_DS3_v2 模型并创建一个 Azure ML 计算资源。

from azure.ai.ml.entities import AmlCompute

# Name assigned to the compute cluster
cpu_compute_target = "cpu-cluster"

try:
    # let's see if the compute target already exists
    cpu_cluster = ml_client.compute.get(cpu_compute_target)
    print(
        f"You already have a cluster named {cpu_compute_target}, we'll reuse it as is."
    )

except Exception:
    print("Creating a new cpu compute target...")

    # Let's create the Azure ML compute object with the intended parameters
    cpu_cluster = AmlCompute(
        name=cpu_compute_target,
        # Azure ML Compute is the on-demand VM service
        type="amlcompute",
        # VM Family
        size="STANDARD_DS3_V2",
        # Minimum running nodes when there is no job running
        min_instances=0,
        # Nodes in cluster
        max_instances=4,
        # How many seconds will the node running after the job termination
        idle_time_before_scale_down=180,
        # Dedicated or LowPriority. The latter is cheaper but there is a chance of job termination
        tier="Dedicated",
    )

    # Now, we pass the object to MLClient's create_or_update method
    cpu_cluster = ml_client.compute.begin_create_or_update(cpu_cluster)

print(
    f"AMLCompute with name {cpu_cluster.name} is created, the compute size is {cpu_cluster.size}"
)

创建作业环境

若要在计算资源上运行 AzureML 作业,需要一个环境。 环境将列出你希望在要训练的计算资源上安装的软件运行时和库。 它类似于本地计算机上的 Python 环境。

AzureML 提供了许多特选或现成的环境,这些环境对于常见训练和推理方案非常有用。 还可以使用 docker 映像或 conda 配置创建自己的自定义环境。

在此示例中,你将使用 conda yaml 文件为作业创建一个自定义 conda 环境。

首先,创建一个目录来存储文件。

import os

dependencies_dir = "./dependencies"
os.makedirs(dependencies_dir, exist_ok=True)

现在,在依赖项目录中创建文件。

%%writefile {dependencies_dir}/conda.yml
name: model-env
channels:
  - conda-forge
dependencies:
  - python=3.8
  - numpy=1.21.2
  - pip=21.2.4
  - scikit-learn=0.24.2
  - scipy=1.7.1
  - pandas>=1.1,<1.2
  - pip:
    - inference-schema[numpy-support]==1.3.0
    - xlrd==2.0.1
    - mlflow== 1.26.1
    - azureml-mlflow==1.42.0
    - psutil>=5.8,<5.9
    - tqdm>=4.59,<4.60
    - ipykernel~=6.0
    - matplotlib

该规范包含一些将在作业中使用的常用包(numpy、pip)。

引用此 yaml 文件以在工作区中创建并注册此自定义环境:

from azure.ai.ml.entities import Environment

custom_env_name = "aml-scikit-learn"

pipeline_job_env = Environment(
    name=custom_env_name,
    description="Custom environment for Credit Card Defaults pipeline",
    tags={"scikit-learn": "0.24.2"},
    conda_file=os.path.join(dependencies_dir, "conda.yml"),
    image="mcr.microsoft.com/azureml/openmpi3.1.2-ubuntu18.04:latest",
)
pipeline_job_env = ml_client.environments.create_or_update(pipeline_job_env)

print(
    f"Environment with name {pipeline_job_env.name} is registered to workspace, the environment version is {pipeline_job_env.version}"
)

什么是命令作业?

你将创建一个 Azure ML 命令作业来训练用于信用违约预测的模型。 命令作业用于在指定计算资源上的指定环境中运行训练脚本。 你已创建环境和计算资源。 接下来需要创建训练脚本。

训练脚本将处理数据准备、训练和注册已训练模型。 在本教程中,你将创建 Python 训练脚本。

可以从 CLI、Python SDK 或工作室界面运行命令作业。 在本教程中,你将使用 Azure ML Python SDK v2 创建并运行命令作业。

运行训练作业后,将部署模型,然后使用它生成预测。

创建训练脚本

首先,创建训练脚本 - main.py python 文件。

首先为脚本创建源文件夹:

import os

train_src_dir = "./src"
os.makedirs(train_src_dir, exist_ok=True)

此脚本处理数据的预处理,将其拆分为测试和训练数据。 然后,该脚本使用此数据来训练基于树的模型并返回输出模型。

MLFlow 用于在管道运行期间记录参数和指标。

%%writefile {train_src_dir}/main.py
import os
import argparse
import pandas as pd
import mlflow
import mlflow.sklearn
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import classification_report
from sklearn.model_selection import train_test_split

def main():
    """Main function of the script."""

    # input and output arguments
    parser = argparse.ArgumentParser()
    parser.add_argument("--data", type=str, help="path to input data")
    parser.add_argument("--test_train_ratio", type=float, required=False, default=0.25)
    parser.add_argument("--n_estimators", required=False, default=100, type=int)
    parser.add_argument("--learning_rate", required=False, default=0.1, type=float)
    parser.add_argument("--registered_model_name", type=str, help="model name")
    args = parser.parse_args()
   
    # Start Logging
    mlflow.start_run()

    # enable autologging
    mlflow.sklearn.autolog()

    ###################
    #<prepare the data>
    ###################
    print(" ".join(f"{k}={v}" for k, v in vars(args).items()))

    print("input data:", args.data)
    
    credit_df = pd.read_excel(args.data, header=1, index_col=0)

    mlflow.log_metric("num_samples", credit_df.shape[0])
    mlflow.log_metric("num_features", credit_df.shape[1] - 1)

    train_df, test_df = train_test_split(
        credit_df,
        test_size=args.test_train_ratio,
    )
    ####################
    #</prepare the data>
    ####################

    ##################
    #<train the model>
    ##################
    # Extracting the label column
    y_train = train_df.pop("default payment next month")

    # convert the dataframe values to array
    X_train = train_df.values

    # Extracting the label column
    y_test = test_df.pop("default payment next month")

    # convert the dataframe values to array
    X_test = test_df.values

    print(f"Training with data of shape {X_train.shape}")

    clf = GradientBoostingClassifier(
        n_estimators=args.n_estimators, learning_rate=args.learning_rate
    )
    clf.fit(X_train, y_train)

    y_pred = clf.predict(X_test)

    print(classification_report(y_test, y_pred))
    ###################
    #</train the model>
    ###################

    ##########################
    #<save and register model>
    ##########################
    # Registering the model to the workspace
    print("Registering the model via MLFlow")
    mlflow.sklearn.log_model(
        sk_model=clf,
        registered_model_name=args.registered_model_name,
        artifact_path=args.registered_model_name,
    )

    # Saving the model to a file
    mlflow.sklearn.save_model(
        sk_model=clf,
        path=os.path.join(args.registered_model_name, "trained_model"),
    )
    ###########################
    #</save and register model>
    ###########################
    
    # Stop Logging
    mlflow.end_run()

if __name__ == "__main__":
    main()

如此脚本中所示,训练模型后,模型文件将会保存并注册到工作区。 现在可以在推理终结点中使用已注册的模型。

配置命令

现在已有一个可执行所需任务的脚本,你将使用可以运行命令行操作的常规用途命令。 此命令行操作可以直接调用系统命令或运行脚本。

在这里,你将创建输入变量来指定输入数据、拆分比、学习速率和注册的模型名称。 命令脚本将:

  • 使用之前创建的计算资源来运行此命令。
  • 使用之前创建的环境 - 可以使用 @latest 表示法在运行命令时指示环境的最新版本。
  • 配置某些元数据,例如显示名称、试验名称等。试验是针对特定项目执行的所有迭代的容器。 在同一试验名称下提交的所有作业将在 Azure ML 工作室中彼此相邻地列出。
  • 配置命令行操作本身 - 在这种情况下为 python main.py。 可通过 ${{ ... }} 表示法在命令中访问输入/输出。
from azure.ai.ml import command
from azure.ai.ml import Input

registered_model_name = "credit_defaults_model"

job = command(
    inputs=dict(
        data=Input(
            type="uri_file",
            path="https://archive.ics.uci.edu/ml/machine-learning-databases/00350/default%20of%20credit%20card%20clients.xls",
        ),
        test_train_ratio=0.2,
        learning_rate=0.25,
        registered_model_name=registered_model_name,
    ),
    code="./src/",  # location of source code
    command="python main.py --data ${{inputs.data}} --test_train_ratio ${{inputs.test_train_ratio}} --learning_rate ${{inputs.learning_rate}} --registered_model_name ${{inputs.registered_model_name}}",
    environment="aml-scikit-learn@latest",
    compute="cpu-cluster",
    experiment_name="train_model_credit_default_prediction",
    display_name="credit_default_prediction",
)

提交作业

现可提交作业以在 AzureML 中运行。 这一次你将对 ml_client.jobs 使用 create_or_update

ml_client.create_or_update(job)

查看作业输出并等待作业完成

选择上一个单元格的输出中的链接,以在 AzureML 工作室中查看作业。

此作业的输出在 AzureML 工作室中如下所示。 浏览选项卡,了解各种详细信息,如指标、输出等。完成后,该作业将在工作区中注册一个模型(这是训练的结果)。

显示作业概述的屏幕截图

重要

等待作业的状态变成“已完成”,然后再返回到此笔记本继续。 该作业需要 2 到 3 分钟才能运行。 如果计算群集已缩减到零个节点,并且自定义环境仍在生成,则可能需要更长时间(最多 10 分钟)。

将模型部署为联机终结点

现在,将机器学习模型部署为 Azure 云(一个 online endpoint)中的 Web 服务。

若要部署机器学习服务,通常需要:

  • 要部署的模型资产(文件、元数据)。 你已在训练作业中注册了这些资产。
  • 一些要作为服务运行的代码。 这些代码根据给定的输入请求执行模型。 此入口脚本接收提交到已部署的 Web 服务的数据并将其传递给模型,然后将模型的响应返回给客户端。 该脚本特定于你的模型。 入口脚本必须能够理解模型期望和返回的数据。 使用 MLFlow 模型时,如本教程所示,系统会自动创建此脚本。 可在此处找到评分脚本的示例。

创建新的联机终结点

注册模型并创建推理脚本后,接下来可以创建联机终结点。 终结点名称需在整个 Azure 区域中唯一。 对于本教程,你将使用 UUID 创建唯一的名称。

import uuid

# Creating a unique name for the endpoint
online_endpoint_name = "credit-endpoint-" + str(uuid.uuid4())[:8]

注意

创建终结点预计约需要 6 到 8 分钟。

from azure.ai.ml.entities import (
    ManagedOnlineEndpoint,
    ManagedOnlineDeployment,
    Model,
    Environment,
)

# create an online endpoint
endpoint = ManagedOnlineEndpoint(
    name=online_endpoint_name,
    description="this is an online endpoint",
    auth_mode="key",
    tags={
        "training_dataset": "credit_defaults",
        "model_type": "sklearn.GradientBoostingClassifier",
    },
)

endpoint = ml_client.online_endpoints.begin_create_or_update(endpoint).result()

print(f"Endpoint {endpoint.name} provisioning state: {endpoint.provisioning_state}")

创建终结点后,可按如下方式检索它:

endpoint = ml_client.online_endpoints.get(name=online_endpoint_name)

print(
    f'Endpoint "{endpoint.name}" with provisioning state "{endpoint.provisioning_state}" is retrieved'
)

将模型部署到终结点

创建终结点后,使用入口脚本部署模型。 每个终结点可以有多个部署。 可以使用规则指定发送到这些部署的直接流量。 在此处,你将创建单个部署来处理 100% 的传入流量。 我们为部署选择了颜色名称,例如蓝色、绿色和红色部署,该名称可任选。

可以查看 Azure ML 工作室中的“模型”页,以识别已注册模型的最新版本。 或者,以下代码可以检索可用的最新版本号。

# Let's pick the latest version of the model
latest_model_version = max(
    [int(m.version) for m in ml_client.models.list(name=registered_model_name)]
)

部署模型的最新版本。

注意

此部署预计需要大约 6 到 8 分钟。

# picking the model to deploy. Here we use the latest version of our registered model
model = ml_client.models.get(name=registered_model_name, version=latest_model_version)


# create an online deployment.
blue_deployment = ManagedOnlineDeployment(
    name="blue",
    endpoint_name=online_endpoint_name,
    model=model,
    instance_type="Standard_DS3_v2",
    instance_count=1,
)

blue_deployment = ml_client.begin_create_or_update(blue_deployment).result()

使用示例查询进行测试

将模型部署到终结点后,接下来可以使用它来运行推理。

按照评分脚本的 run 方法中所需的设计创建示例请求文件。

deploy_dir = "./deploy"
os.makedirs(deploy_dir, exist_ok=True)
%%writefile {deploy_dir}/sample-request.json
{
  "input_data": {
    "columns": [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22],
    "index": [0, 1],
    "data": [
            [20000,2,2,1,24,2,2,-1,-1,-2,-2,3913,3102,689,0,0,0,0,689,0,0,0,0],
            [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, 9, 8]
        ]
  }
}
# test the blue deployment with some sample data
ml_client.online_endpoints.invoke(
    endpoint_name=online_endpoint_name,
    request_file="./deploy/sample-request.json",
    deployment_name="blue",
)

清理资源

如果你不打算使用终结点,请将其删除以停止使用该资源。 在删除终结点之前,请确保没有其他任何部署正在使用该终结点。

注意

此步骤预计需要大约 6 到 8 分钟。

ml_client.online_endpoints.begin_delete(name=online_endpoint_name)

删除所有内容

使用这些步骤可删除 Azure 机器学习工作区和所有计算资源。

重要

已创建的资源可用作其他 Azure 机器学习教程和操作方法文章的先决条件。

如果你不打算使用已创建的任何资源,请删除它们,以免产生任何费用:

  1. 在 Azure 门户中,选择最左侧的“资源组” 。

  2. 从列表中选择你创建的资源组。

  3. 选择“删除资源组”

    用于在 Azure 门户中删除资源组的选项的屏幕截图。

  4. 输入资源组名称。 然后选择“删除”。

后续步骤