使用 Azure Machine Learning 大規模定型 PyTorch 模型

適用於Python SDK azure-ai-ml v2 (目前)

在本文中,了解如何使用 Azure Machine Learning Python SDK v2 來執行 scikit-learn 定型指令碼。

本文中的範例指令碼用於分類鳶尾花影像,以根據 scikit-learn 的鳶尾花資料集來建立機器學習模型。

無論您是從頭開始定型機器學習 scikit-learn 模型,或是將現有的模型帶到雲端,您都可以使用 Azure Machine Learning,利用彈性的雲端計算資源來擴增開放原始碼定型作業。 您可以使用 Azure Machine Learning 建立、部署、版本設定和監視生產等級的模型。

必要條件

您可以使用 Azure Machine Learning 計算執行個體或您自己的 Jupyter Notebook 來執行本文的程式碼。

  • Azure Machine Learning 計算執行個體

    • 完成快速入門:開始使用 Azure Machine Learning,以建立計算執行個體。 每個計算執行個體都包含預先載入 SDK 和筆記本範例存放庫的專用筆記本伺服器。
    • 在 Azure Machine Learning 工作室中選取筆記本索引標籤。 在範例定型資料夾中,導覽至下列目錄來尋找已完整和擴充的筆記本:v2 > sdk > jobs > single-step > scikit-learn > train-hyperparameter-tune-deploy-with-sklearn
    • 您可以使用範例定型資料夾中預先填入的程式碼來完成本教學課程。
  • 您的 Jupyter 筆記本伺服器。

設定作業

本節會藉由載入必要的 Python 套件、連線到工作區、建立計算資源來執行命令作業,以及建立環境來執行作業,來設定定型作業。

連線到工作區

首先,您必須連線到您的 AzureML 工作區。 AzureML 工作區是服務的最上層資源。 其可以在您使用 Azure Machine Learning 時,提供集中式位置以處理您建立的所有成品。

我們正在使用 DefaultAzureCredential 來存取工作區。 此認證應該能夠處理大部分的 Azure SDK 驗證案例。

如果 DefaultAzureCredential 不適用於您,則請參閱 azure-identity reference documentationSet up authentication來取得更多可用的認證。

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

# Authentication package
from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()

如果您想要使用瀏覽器來登入並驗證,則應該移除下列程式碼中的註解,並改為使用瀏覽器。

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

# Authentication package
# from azure.identity import InteractiveBrowserCredential
# credential = InteractiveBrowserCredential()

接下來,提供您的訂用帳戶識別碼、資源群組名稱和工作區名稱,以取得工作區的控制代碼。 若要尋找這些參數:

  1. 在 Azure Machine Learning 工作室工具列的右上角,尋找您的工作區名稱。
  2. 選取您的工作區名稱以顯示您的資源群組和訂用帳戶識別碼。
  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 時不會將用戶端連線至工作區。 用戶端初始化作業是緩慢的,會等第一次它所需要的時間到時才會進行呼叫。 在本文中,這會在計算建立期間發生。

建立計算資源以執行作業

AzureML 需要計算資源才能執行作業。 此資源可以是採用 Linux 或 Windows OS 的單一或多節點機器,或 Spark 之類的特定計算網狀架構。

在下列範例指令碼中,我們會佈建 Linux compute cluster。 您可以查看 Azure Machine Learning pricing 頁面以取得 VM 大小和價格的完整清單。 我們只需要此範例的基本叢集;因此,我們將挑選具有 2 個 vCPU 核心和 7 GB RAM 的 Standard_DS3_v2 模型,以建立 AzureML 計算。

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).result()

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

建立作業環境

若要執行 AzureML 作業,您需要環境。 AzureML 環境會封裝相依性 (例如軟體執行時間和程式庫) 在您的計算資源上執行您的機器學習訓練指令碼。 此環境類似於本機電腦上的 Python 環境。

AzureML 可讓您使用策劃的 (或現成的) 環境,或是使用 Docker 映像或 Conda 設定來建立自訂環境。 在本文中,您將使用 Conda YAML 檔案為您的作業建立自訂環境。

建立自訂環境

若要建立自訂環境,您將在 YAML 檔案中定義 Conda 相依性。 首先,建立一個用來儲存檔案的目錄。 在此範例中,我們已將目錄命名為 env

import os

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

然後,在相依性目錄中建立檔案。 在此範例中,我們已將檔案命名為 conda.yml

%%writefile {dependencies_dir}/conda.yml
name: sklearn-env
channels:
  - conda-forge
dependencies:
  - python=3.8
  - pip=21.2.4
  - scikit-learn=0.24.2
  - scipy=1.7.1
  - pip:  
    - mlflow== 1.26.1
    - azureml-mlflow==1.42.0

規格包含您將在作業中使用的一些常用套件 (例如 numpy 和 pip)。

接下來,使用 YAML 檔案,在您的工作區中建立及登錄此自訂環境: 環境會在執行階段封裝至 Docker 容器。

from azure.ai.ml.entities import Environment

custom_env_name = "sklearn-env"

job_env = Environment(
    name=custom_env_name,
    description="Custom environment for sklearn image classification",
    conda_file=os.path.join(dependencies_dir, "conda.yml"),
    image="mcr.microsoft.com/azureml/openmpi4.1.0-ubuntu20.04:latest",
)
job_env = ml_client.environments.create_or_update(job_env)

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

如需有關建立和使用環境的詳細資訊,請參閱在 Azure Machine Learning 中建立和使用軟體環境

設定並提交您的定型作業

接著,我們將說明如何使用我們提供的定型指令碼來執行定型作業。 若要開始,您將設定用於執行定型指令碼的命令來建置定型作業。 然後,您將提交定型作業以在 AzureML 中執行。

建立定型指令碼

在本文中,我們已提供定型指令碼 train_iris.py。 在實務上,您應該能夠採用任何現狀的自訂定型指令碼,並在不需要修改程式碼的情況下使用 AzureML 加以執行。

注意

所提供的定型指令碼會執行下列動作:

  • 顯示如何將某些計量記錄到您的 AzureML 執行;
  • 使用 iris = datasets.load_iris() 下載並擷取定型資料;以及
  • 定型模型,然後儲存並註冊模型。

若要使用和存取您自己的資料,請參閱如何在作業中讀取和寫入資料,以在定型期間提供資料。

若要使用定型指令碼,請先建立您將儲存檔案的目錄。

import os

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

接下來,在來源目錄中建立指令碼檔案。

%%writefile {src_dir}/train_iris.py
# Modified from https://www.geeksforgeeks.org/multiclass-classification-using-scikit-learn/

import argparse
import os

# importing necessary libraries
import numpy as np

from sklearn import datasets
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split

import joblib

import mlflow
import mlflow.sklearn

def main():
    parser = argparse.ArgumentParser()

    parser.add_argument('--kernel', type=str, default='linear',
                        help='Kernel type to be used in the algorithm')
    parser.add_argument('--penalty', type=float, default=1.0,
                        help='Penalty parameter of the error term')

    # Start Logging
    mlflow.start_run()

    # enable autologging
    mlflow.sklearn.autolog()

    args = parser.parse_args()
    mlflow.log_param('Kernel type', str(args.kernel))
    mlflow.log_metric('Penalty', float(args.penalty))

    # loading the iris dataset
    iris = datasets.load_iris()

    # X -> features, y -> label
    X = iris.data
    y = iris.target

    # dividing X, y into train and test data
    X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

    # training a linear SVM classifier
    from sklearn.svm import SVC
    svm_model_linear = SVC(kernel=args.kernel, C=args.penalty)
    svm_model_linear = svm_model_linear.fit(X_train, y_train)
    svm_predictions = svm_model_linear.predict(X_test)

    # model accuracy for X_test
    accuracy = svm_model_linear.score(X_test, y_test)
    print('Accuracy of SVM classifier on test set: {:.2f}'.format(accuracy))
    mlflow.log_metric('Accuracy', float(accuracy))
    # creating a confusion matrix
    cm = confusion_matrix(y_test, svm_predictions)
    print(cm)

    registered_model_name="sklearn-iris-flower-classify-model"

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

    # # Saving the model to a file
    print("Saving the model via MLFlow")
    mlflow.sklearn.save_model(
        sk_model=svm_model_linear,
        path=os.path.join(registered_model_name, "trained_model"),
    )
    ###########################
    #</save and register model>
    ###########################
    mlflow.end_run()

if __name__ == '__main__':
    main()

建置定型作業

既然您已有執行作業所需的所有資產,接下來即可使用 AzureML Python SDK v2 來加以建置。 因此,我們將建立 command

AzureML command 是可指定在雲端中執行定型程式碼所需之所有詳細資料的資源。 這些詳細資料包括輸入和輸出、要使用的硬體類型、要安裝的軟體,以及如何執行程式碼。 command 包含執行單一命令的資訊。

設定命令

您將使用一般用途 command 來執行定型指令碼,並執行所需的工作。 建立 Command 物件以指定定型作業的設定詳細資料。

  • 此命令的輸入包括 epoch 數目、學習速率、訊號和輸出目錄。
  • 對於參數值:
    • 提供您為執行此命令所建立的計算叢集 cpu_compute_target = "cpu-cluster"
    • 提供您為執行 AzureML 作業所建立的自訂環境 sklearn-env
    • 設定命令列動作本身,在此案例中,命令為 python train_iris.py。 您可以透過 ${{ ... }} 標記法在命令中存取輸入和輸出;以及
    • 設定中繼資料 (例如顯示名稱和實驗名稱),其中實驗是在特定專案上執行之所有反覆項目的容器。 請注意,所有以相同實驗名稱提交的作業,都會在 AzureML 工作室中相鄰列出。
from azure.ai.ml import command
from azure.ai.ml import Input

job = command(
    inputs=dict(kernel="linear", penalty=1.0),
    compute=cpu_compute_target,
    environment=f"{job_env.name}:{job_env.version}",
    code="./src/",
    command="python train_iris.py --kernel ${{inputs.kernel}} --penalty ${{inputs.penalty}}",
    experiment_name="sklearn-iris-flowers",
    display_name="sklearn-classify-iris-flower-images",
)

提交工作

現在可以提交作業,以在 AzureML 中執行。 這次,您會對 ml_client.jobs 使用 create_or_update

ml_client.jobs.create_or_update(job)

完成後,作業會在工作區中註冊模型 (作為定型的結果),並輸出可用來在 AzureML 工作室中檢視作業的連結。

警告

Azure Machine Learning 藉由複製整個來源目錄來執行定型指令碼。 如果您不想上傳敏感性資料,請使用 .ignore 檔案,或不要將敏感性資料放入來源目錄中。

作業執行期間發生的情況

作業執行時,會經歷下列階段:

  • 準備:根據定義的環境來建置 Docker 映像。 映像上傳至工作區的容器登錄,並快取以供稍後執行。 記錄也會串流至執行歷程記錄,並可檢視以監視進度。 如果已指定策展環境,則將使用支援該策展環境的快取影像。

  • 縮放:如果叢集需要更多節點來執行該執行比目前可用的節點,則叢集會嘗試擴大規模。

  • 執行中:系統會將指令碼資料夾 [src] 中的所有指令碼上傳至計算目標,掛接或複製資料存放區,然後執行指令碼。 stdout./logs 資料夾的輸出都會串流到執行歷程記錄,並且可用來監視執行。

微調模型超參數

既然您已了解如何使用 SDK 執行簡單 Scikit-learn 定型執行,讓我們看看您是否可以進一步改善模型的正確性。 您可以使用 Azure Machine Learning 的sweep功能來微調和最佳化模型的超參數。

若要微調模型的超參數,請定義於定型期間要在其中搜尋的參數空間。 作法是您將使用來自 azure.ml.sweep 套件的特殊輸入來取代傳遞給定型作業的一些參數 (kernelpenalty)。

from azure.ai.ml.sweep import Choice

# we will reuse the command_job created before. we call it as a function so that we can apply inputs
# we do not apply the 'iris_csv' input again -- we will just use what was already defined earlier
job_for_sweep = job(
    kernel=Choice(values=["linear", "rbf", "poly", "sigmoid"]),
    penalty=Choice(values=[0.5, 1, 1.5]),
)

然後,您將使用一些掃掠特定參數 (例如要監看的主要計量,以及要使用的取樣演算法) 在命令作業上設定掃掠。

在下列程式碼中,我們會使用隨機取樣來嘗試不同的超參數設定組,以嘗試將主要計量 Accuracy 最大化。

sweep_job = job_for_sweep.sweep(
    compute="cpu-cluster",
    sampling_algorithm="random",
    primary_metric="Accuracy",
    goal="Maximize",
    max_total_trials=12,
    max_concurrent_trials=4,
)

現在,您可以如先前一樣提交此作業。 這次,您將執行掃掠作業,以掃掠定型作業。

returned_sweep_job = ml_client.create_or_update(sweep_job)

# stream the output and wait until the job is finished
ml_client.jobs.stream(returned_sweep_job.name)

# refresh the latest status of the job after streaming
returned_sweep_job = ml_client.jobs.get(name=returned_sweep_job.name)

您可以使用在作業執行期間呈現的 Studio 使用者介面連結來監視作業。

尋找並註冊最佳的模型

一旦完成所有執行,您就可以找到產生模型且精確度最高的回合。

from azure.ai.ml.entities import Model

if returned_sweep_job.status == "Completed":

    # First let us get the run which gave us the best result
    best_run = returned_sweep_job.properties["best_child_run_id"]

    # lets get the model from this run
    model = Model(
        # the script stores the model as "sklearn-iris-flower-classify-model"
        path="azureml://jobs/{}/outputs/artifacts/paths/sklearn-iris-flower-classify-model/".format(
            best_run
        ),
        name="run-model-example",
        description="Model created from run.",
        type="custom_model",
    )

else:
    print(
        "Sweep job status: {}. Please wait until it completes".format(
            returned_sweep_job.status
        )
    )

然後,您可以註冊此模型。

registered_model = ml_client.models.create_or_update(model=model)

部署模型

註冊模型之後,其部署方式會與 Azure ML 中任何其他已註冊的模型相同。 如需部署的詳細資訊,請參閱使用 Python SDK v2,搭配受控線上端點部署和評分機器學習模型

下一步

在本文中,您已定型並註冊 scikit-learn 模型,並了解部署選項。 若要深入了解 Azure Machine Learning,請參閱下列其他文章。