Trenowanie modeli scikit-learn na dużą skalę za pomocą usługi Azure Machine Learning

DOTYCZY: Zestaw PYTHON SDK azure-ai-ml w wersji 2 (bieżąca)

Z tego artykułu dowiesz się, jak uruchamiać skrypty szkoleniowe biblioteki scikit-learn przy użyciu zestawu SDK języka Python usługi Azure Machine Learning w wersji 2.

Przykładowe skrypty w tym artykule służą do klasyfikowania obrazów kwiatów irysów w celu utworzenia modelu uczenia maszynowego na podstawie zestawu danych iris scikit-learn.

Niezależnie od tego, czy trenujesz model scikit-learn uczenia maszynowego od podstaw, czy wprowadzasz istniejący model do chmury, możesz użyć usługi Azure Machine Learning, aby skalować zadania szkoleniowe typu open source przy użyciu elastycznych zasobów obliczeniowych w chmurze. Za pomocą usługi Azure Machine Learning można tworzyć, wdrażać, wersję i monitorować modele klasy produkcyjnej.

Wymagania wstępne

Kod tego artykułu można uruchomić w wystąpieniu obliczeniowym usługi Azure Machine Learning lub własnym Jupyter Notebook.

  • Wystąpienie obliczeniowe usługi Azure Machine Learning

    • Ukończ przewodnik Szybki start: rozpoczynanie pracy z usługą Azure Machine Learning w celu utworzenia wystąpienia obliczeniowego. Każde wystąpienie obliczeniowe zawiera dedykowany serwer notesów wstępnie załadowany z zestawem SDK i repozytorium przykładów notesów.
    • Wybierz kartę notesu w Azure Machine Learning studio. W folderze trenowania przykładów znajdź ukończony i rozwinięty notes, przechodząc do tego katalogu: zadania zestawu SDK >> w wersji 2 > w jednym kroku > scikit-learn > train-hyperparameter-tune-deploy-with-sklearn.
    • Aby ukończyć ten samouczek, możesz użyć wstępnie wypełnionego kodu w folderze trenowania przykładowego.
  • Serwer notesu Jupyter.

Konfigurowanie zadania

Ta sekcja konfiguruje zadanie do trenowania przez załadowanie wymaganych pakietów języka Python, nawiązanie połączenia z obszarem roboczym, utworzenie zasobu obliczeniowego w celu uruchomienia zadania polecenia i utworzenie środowiska do uruchomienia zadania.

Nawiązywanie połączenia z obszarem roboczym

Najpierw musisz nawiązać połączenie z obszarem roboczym usługi AzureML. Obszar roboczy usługi AzureML jest zasobem najwyższego poziomu dla usługi. Zapewnia ona scentralizowane miejsce do pracy ze wszystkimi artefaktami tworzonymi podczas korzystania z usługi Azure Machine Learning.

Używamy DefaultAzureCredential polecenia , aby uzyskać dostęp do obszaru roboczego. To poświadczenie powinno obsługiwać większość scenariuszy uwierzytelniania zestawu Azure SDK.

Jeśli DefaultAzureCredential nie działa dla Ciebie, zobacz azure-identity reference documentation lub Set up authentication w przypadku większej liczby dostępnych poświadczeń.

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

# Authentication package
from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()

Jeśli wolisz używać przeglądarki do logowania się i uwierzytelniania, należy usunąć komentarze w poniższym kodzie i użyć go zamiast tego.

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

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

Następnie uzyskaj dojście do obszaru roboczego, podając identyfikator subskrypcji, nazwę grupy zasobów i nazwę obszaru roboczego. Aby znaleźć następujące parametry:

  1. Wyszukaj nazwę obszaru roboczego w prawym górnym rogu paska narzędzi Azure Machine Learning studio.
  2. Wybierz nazwę obszaru roboczego, aby wyświetlić grupę zasobów i identyfikator subskrypcji.
  3. Skopiuj wartości dla pola Grupa zasobów i Identyfikator subskrypcji do kodu.
# 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>",
)

Wynikiem uruchomienia tego skryptu jest uchwyt obszaru roboczego, którego będziesz używać do zarządzania innymi zasobami i zadaniami.

Uwaga

Utworzenie MLClient nie spowoduje połączenia klienta z obszarem roboczym. Inicjowanie klienta jest leniwe i będzie czekać po raz pierwszy, aby wykonać wywołanie. W tym artykule wystąpi to podczas tworzenia zasobów obliczeniowych.

Tworzenie zasobu obliczeniowego w celu uruchomienia zadania

Usługa AzureML wymaga zasobu obliczeniowego do uruchomienia zadania. Ten zasób może być pojedynczym lub wielowęźle maszynami z systemem operacyjnym Linux lub Windows albo określoną siecią szkieletową obliczeniową, taką jak Spark.

W poniższym przykładowym skry skrycie aprowizujemy system Linux compute cluster. Zostanie wyświetlona Azure Machine Learning pricing strona zawierająca pełną listę rozmiarów maszyn wirtualnych i cen. W tym przykładzie potrzebujemy tylko podstawowego klastra; W związku z tym wybierzemy model Standard_DS3_v2 z 2 rdzeniami procesorów wirtualnych i 7 GB pamięci RAM w celu utworzenia obliczeń w usłudze 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}"
)

Tworzenie środowiska zadań

Aby uruchomić zadanie usługi AzureML, potrzebne jest środowisko. Środowisko AzureML hermetyzuje zależności (takie jak środowisko uruchomieniowe oprogramowania i biblioteki) wymagane do uruchomienia skryptu trenowania uczenia maszynowego na zasobie obliczeniowym. To środowisko jest podobne do środowiska języka Python na komputerze lokalnym.

Usługa AzureML umożliwia użycie nadzorowanego (lub gotowego) środowiska albo utworzenie środowiska niestandardowego przy użyciu obrazu platformy Docker lub konfiguracji conda. W tym artykule utworzysz środowisko niestandardowe dla zadań przy użyciu pliku COnda YAML.

Tworzenie środowiska niestandardowego

Aby utworzyć środowisko niestandardowe, zdefiniujesz zależności Conda w pliku YAML. Najpierw utwórz katalog do przechowywania pliku. W tym przykładzie nazwaliśmy katalog env.

import os

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

Następnie utwórz plik w katalogu dependencies. W tym przykładzie nazwaliśmy plik 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

Specyfikacja zawiera kilka zwykłych pakietów (takich jak numpy i pip), których będziesz używać w zadaniu.

Następnie użyj pliku YAML, aby utworzyć i zarejestrować to środowisko niestandardowe w obszarze roboczym. Środowisko zostanie spakowane w kontenerze platformy Docker w czasie wykonywania.

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}"
)

Aby uzyskać więcej informacji na temat tworzenia i używania środowisk, zobacz Tworzenie i używanie środowisk oprogramowania w usłudze Azure Machine Learning.

Konfigurowanie i przesyłanie zadania szkoleniowego

W tej sekcji omówimy sposób uruchamiania zadania szkoleniowego przy użyciu udostępnionego skryptu szkoleniowego. Aby rozpocząć, skompilujesz zadanie trenowania, konfigurując polecenie do uruchamiania skryptu szkoleniowego. Następnie prześlesz zadanie trenowania do uruchomienia w usłudze AzureML.

Przygotowywanie skryptu szkoleniowego

W tym artykule udostępniliśmy skrypt szkoleniowy train_iris.py. W praktyce powinno być możliwe użycie dowolnego niestandardowego skryptu szkoleniowego bez konieczności modyfikowania kodu i uruchamiania go przy użyciu języka AzureML.

Uwaga

Podany skrypt szkoleniowy wykonuje następujące czynności:

  • Pokazuje, jak zarejestrować niektóre metryki w przebiegu usługi AzureML;
  • pobiera i wyodrębnia dane treningowe przy użyciu ; iris = datasets.load_iris()i
  • trenuje model, a następnie zapisuje go i rejestruje.

Aby korzystać z własnych danych i uzyskiwać do nich dostęp, zobacz , jak odczytywać i zapisywać dane w zadaniu , aby udostępnić dane podczas trenowania.

Aby użyć skryptu trenowania, najpierw utwórz katalog, w którym będzie przechowywany plik.

import os

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

Następnie utwórz plik skryptu w katalogu źródłowym.

%%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()

Kompilowanie zadania szkoleniowego

Teraz, gdy masz wszystkie zasoby wymagane do uruchomienia zadania, nadszedł czas na skompilowanie go przy użyciu zestawu AZUREML Python SDK w wersji 2. W tym celu utworzymy element command.

AzureML command to zasób, który określa wszystkie szczegóły potrzebne do wykonania kodu szkoleniowego w chmurze. Te szczegóły obejmują dane wejściowe i wyjściowe, typ sprzętu do użycia, oprogramowanie do zainstalowania i sposób uruchamiania kodu. Zawiera command informacje umożliwiające wykonanie pojedynczego polecenia.

Konfigurowanie polecenia

Użyjesz ogólnego przeznaczenia command , aby uruchomić skrypt trenowania i wykonać żądane zadania. Command Utwórz obiekt w celu określenia szczegółów konfiguracji zadania trenowania.

  • Dane wejściowe dla tego polecenia obejmują liczbę epok, szybkość nauki, pęd i katalog wyjściowy.
  • Dla wartości parametrów:
    • podaj klaster cpu_compute_target = "cpu-cluster" obliczeniowy utworzony na potrzeby uruchamiania tego polecenia;
    • podaj środowisko sklearn-env niestandardowe utworzone na potrzeby uruchamiania zadania usługi AzureML;
    • skonfiguruj samą akcję wiersza polecenia — w tym przypadku polecenie to python train_iris.py. Dostęp do danych wejściowych i wyjściowych w poleceniu ${{ ... }} można uzyskać za pośrednictwem notacji ; i
    • skonfiguruj metadane, takie jak nazwa wyświetlana i nazwa eksperymentu; gdzie eksperyment jest kontenerem dla wszystkich iteracji, które wykonuje w określonym projekcie. Zwróć uwagę, że wszystkie zadania przesłane pod tą samą nazwą eksperymentu zostaną wyświetlone obok siebie w programie AzureML Studio.
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",
)

Przesyłanie zadania

Nadszedł czas, aby przesłać zadanie do uruchomienia w usłudze AzureML. Tym razem użyjesz polecenia create_or_update w systemie ml_client.jobs.

ml_client.jobs.create_or_update(job)

Po zakończeniu zadanie zarejestruje model w obszarze roboczym (w wyniku trenowania) i wyświetli link do wyświetlania zadania w programie AzureML Studio.

Ostrzeżenie

Usługa Azure Machine Learning uruchamia skrypty szkoleniowe, kopiując cały katalog źródłowy. Jeśli masz poufne dane, które nie chcesz przekazywać, użyj pliku ignoruj lub nie dołącz go do katalogu źródłowego.

Co się dzieje podczas wykonywania zadania

W miarę wykonywania zadania przechodzi on przez następujące etapy:

  • Przygotowywanie: obraz platformy Docker jest tworzony zgodnie ze zdefiniowanym środowiskiem. Obraz jest przekazywany do rejestru kontenerów obszaru roboczego i buforowany do późniejszego uruchomienia. Dzienniki są również przesyłane strumieniowo do historii uruchamiania i można je wyświetlić w celu monitorowania postępu. Jeśli zostanie określone wyselekcjonowane środowisko, zostanie użyty buforowany obraz obsługujący środowisko wyselekcjonowane.

  • Skalowanie: klaster próbuje skalować w górę, jeśli klaster wymaga większej liczby węzłów do wykonania przebiegu niż jest obecnie dostępne.

  • Uruchomione: wszystkie skrypty w folderze skryptu src są przekazywane do docelowego obiektu obliczeniowego, magazyny danych są instalowane lub kopiowane, a skrypt jest wykonywany. Dane wyjściowe z pliku stdout i folderu ./logs są przesyłane strumieniowo do historii uruchamiania i mogą służyć do monitorowania przebiegu.

Dostrajanie hiperparametrów modelu

Teraz, gdy już wiesz, jak wykonać prosty przebieg trenowania Scikit-learn przy użyciu zestawu SDK, sprawdźmy, czy można jeszcze bardziej poprawić dokładność modelu. Możesz dostosować i zoptymalizować hiperparametry naszego modelu przy użyciu możliwości usługi Azure Machine Learning sweep .

Aby dostosować hiperparametry modelu, zdefiniuj przestrzeń parametrów, w której mają być wyszukiwane podczas trenowania. Zrobisz to, zastępując niektóre parametry (kernel i penalty) przekazane do zadania trenowania specjalnymi danymi wejściowymi z azure.ml.sweep pakietu.

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]),
)

Następnie skonfigurujesz zamiatanie zadania poleceń przy użyciu niektórych parametrów specyficznych dla zamiatania, takich jak podstawowa metryka do obserwowania i algorytm próbkowania do użycia.

W poniższym kodzie używamy losowego próbkowania do wypróbowania różnych zestawów konfiguracji hiperparametrów w celu zmaksymalizowania podstawowej metryki 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,
)

Teraz możesz przesłać to zadanie tak jak wcześniej. Tym razem będziesz uruchomić zadanie zamiatania, które zamiata się nad zadaniem pociągu.

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)

Zadanie można monitorować za pomocą linku interfejsu użytkownika programu Studio, który jest wyświetlany podczas uruchamiania zadania.

Znajdowanie i rejestrowanie najlepszego modelu

Po zakończeniu wszystkich przebiegów można znaleźć przebieg, który wyprodukował model z najwyższą dokładnością.

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
        )
    )

Następnie możesz zarejestrować ten model.

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

Wdrażanie modelu

Po zarejestrowaniu modelu można wdrożyć go w taki sam sposób, jak każdy inny zarejestrowany model w usłudze Azure ML. Aby uzyskać więcej informacji na temat wdrażania, zobacz Wdrażanie i ocenianie modelu uczenia maszynowego za pomocą zarządzanego punktu końcowego online przy użyciu zestawu SDK języka Python w wersji 2.

Następne kroki

W tym artykule wytrenujesz i zarejestrowano model scikit-learn oraz przedstawiono opcje wdrażania. Zobacz te inne artykuły, aby dowiedzieć się więcej o usłudze Azure Machine Learning.