Dela via


Träna scikit-learn-modeller i stor skala med Azure Machine Learning

GÄLLER FÖR: Python SDK azure-ai-ml v2 (aktuell)

I den här artikeln får du lära dig hur du kör dina scikit-learn-träningsskript med Azure Machine Learning Python SDK v2.

Exempelskripten i den här artikeln används för att klassificera irisblomsbilder för att skapa en maskininlärningsmodell baserat på scikit-learns iris-datauppsättning.

Oavsett om du tränar en scikit-learn-modell för maskininlärning från grunden eller om du tar in en befintlig modell i molnet kan du använda Azure Machine Learning för att skala ut träningsjobb med öppen källkod med hjälp av elastiska beräkningsresurser för molnet. Du kan skapa, distribuera, version och övervaka modeller i produktionsklass med Azure Machine Learning.

Förutsättningar

Du kan köra koden för den här artikeln i antingen en Azure Machine Learning-beräkningsinstans eller i din egen Jupyter Notebook.

  • Azure Machine Learning-beräkningsinstans

    • Slutför Skapa resurser för att komma igång med att skapa en beräkningsinstans. Varje beräkningsinstans innehåller en dedikerad notebook-server som är förinstallerad med SDK och notebook-exempellagringsplatsen.
    • Välj anteckningsboksfliken i Azure Machine Learning-studio. I exempelträningsmappen hittar du en slutförd och expanderad notebook-fil genom att gå till den här katalogen: v2 > sdk-jobb > > i ett steg > scikit-learn > train-hyperparameter-tune-deploy-with-sklearn.
    • Du kan använda den förifyllda koden i exempelträningsmappen för att slutföra den här självstudien.
  • Jupyter Notebook-servern.

Konfigurera jobbet

Det här avsnittet konfigurerar jobbet för träning genom att läsa in nödvändiga Python-paket, ansluta till en arbetsyta, skapa en beräkningsresurs för att köra ett kommandojobb och skapa en miljö för att köra jobbet.

Ansluta till arbetsytan

Först måste du ansluta till din Azure Machine Learning-arbetsyta. Azure Machine Learning-arbetsytan är den översta resursen för tjänsten. Det ger dig en central plats där du kan arbeta med alla artefakter som du skapar när du använder Azure Machine Learning.

Vi använder DefaultAzureCredential för att få åtkomst till arbetsytan. Den här autentiseringsuppgiften bör kunna hantera de flesta Azure SDK-autentiseringsscenarier.

Om DefaultAzureCredential inte fungerar för dig kan du se azure-identity reference documentation eller Set up authentication för mer tillgängliga autentiseringsuppgifter.

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

# Authentication package
from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()

Om du föredrar att använda en webbläsare för att logga in och autentisera bör du ta bort kommentarerna i följande kod och använda den i stället.

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

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

Hämta sedan en referens till arbetsytan genom att ange ditt prenumerations-ID, resursgruppsnamn och arbetsytenamn. Så här hittar du följande parametrar:

  1. Leta efter arbetsytans namn i det övre högra hörnet i Azure Machine Learning-studio verktygsfält.
  2. Välj namnet på arbetsytan för att visa resursgruppen och prenumerations-ID:t.
  3. Kopiera värdena för Resursgrupp och Prenumerations-ID till koden.
# 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>",
)

Resultatet av att köra det här skriptet är en arbetsytereferens som du använder för att hantera andra resurser och jobb.

Kommentar

När du skapar MLClient ansluts inte klienten till arbetsytan. Klientinitieringen är lat och väntar första gången den behöver göra ett anrop. I den här artikeln sker detta när beräkning skapas.

Skapa en beräkningsresurs

Azure Machine Learning behöver en beräkningsresurs för att köra ett jobb. Den här resursen kan vara datorer med en eller flera noder med Linux eller Windows OS, eller en specifik beräkningsinfrastruktur som Spark.

I följande exempelskript etablerar vi en Linux compute cluster. Du kan se sidan Azure Machine Learning pricing för den fullständiga listan över VM-storlekar och priser. Vi behöver bara ett grundläggande kluster för det här exemplet. Därför väljer vi en Standard_DS3_v2 modell med 2 vCPU-kärnor och 7 GB RAM-minne för att skapa en Azure Machine Learning-beräkning.

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

Skapa en jobbmiljö

Om du vill köra ett Azure Machine Learning-jobb behöver du en miljö. En Azure Machine Learning-miljö kapslar in de beroenden (till exempel programkörning och bibliotek) som behövs för att köra maskininlärningsträningsskriptet på beräkningsresursen. Den här miljön liknar en Python-miljö på den lokala datorn.

Med Azure Machine Learning kan du antingen använda en kuraterad (eller färdig) miljö eller skapa en anpassad miljö med hjälp av en Docker-avbildning eller en Conda-konfiguration. I den här artikeln skapar du en anpassad miljö för dina jobb med hjälp av en Conda YAML-fil.

Skapa en anpassad miljö

För att skapa din anpassade miljö definierar du dina Conda-beroenden i en YAML-fil. Skapa först en katalog för lagring av filen. I det här exemplet har vi namngett katalogen env.

import os

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

Skapa sedan filen i katalogen beroenden. I det här exemplet har vi döpt filen conda.ymltill .

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

Specifikationen innehåller några vanliga paket (till exempel numpy och pip) som du använder i ditt jobb.

Använd sedan YAML-filen för att skapa och registrera den här anpassade miljön på din arbetsyta. Miljön paketeras i en Docker-container vid körning.

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.yaml"),
    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}"
)

Mer information om hur du skapar och använder miljöer finns i Skapa och använda programvarumiljöer i Azure Machine Learning.

[Valfritt] Skapa en anpassad miljö med Intel-tillägget® för Scikit-Learn

Vill du påskynda dina scikit-learn-skript på Intel-maskinvara? Prova att lägga till Intel-tillägget® för Scikit-Learn i din conda yaml-fil och följ de efterföljande stegen som beskrivs ovan. Vi visar hur du aktiverar dessa optimeringar senare i det här exemplet:

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

Konfigurera och skicka ditt träningsjobb

I det här avsnittet går vi igenom hur du kör ett träningsjobb med hjälp av ett träningsskript som vi har angett. Börja med att skapa träningsjobbet genom att konfigurera kommandot för att köra träningsskriptet. Sedan skickar du träningsjobbet som ska köras i Azure Machine Learning.

Förbereda träningsskriptet

I den här artikeln har vi angett träningsskriptet train_iris.py. I praktiken bör du kunna använda ett anpassat träningsskript som det är och köra det med Azure Machine Learning utan att behöva ändra koden.

Kommentar

Det angivna träningsskriptet gör följande:

  • visar hur du loggar vissa mått till din Azure Machine Learning-körning.
  • laddar ned och extraherar träningsdata med hjälp av iris = datasets.load_iris(); och
  • tränar en modell och sparar och registrerar den.

Om du vill använda och komma åt dina egna data kan du läsa och skriva data i ett jobb för att göra data tillgängliga under träningen.

Om du vill använda träningsskriptet skapar du först en katalog där du lagrar filen.

import os

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

Skapa sedan skriptfilen i källkatalogen.

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

[Valfritt] Aktivera Intel-tillägg® för Scikit-Learn-optimeringar för mer prestanda på Intel-maskinvara

Om du har installerat Intel-tillägget® för Scikit-Learn (vilket visas i föregående avsnitt) kan du aktivera prestandaoptimeringarna genom att lägga till de två kodraderna överst i skriptfilen, enligt nedan.

Mer information om Intel-tillägget® för Scikit-Learn finns i paketets dokumentation.

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

import argparse
import os

# Import and enable Intel Extension for Scikit-learn optimizations
# where possible

from sklearnex import patch_sklearn
patch_sklearn()

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

Skapa träningsjobbet

Nu när du har alla tillgångar som krävs för att köra jobbet är det dags att skapa det med Hjälp av Azure Machine Learning Python SDK v2. För att köra jobbet skapar vi en command.

En Azure Machine Learning command är en resurs som anger all information som behövs för att köra träningskoden i molnet. Den här informationen omfattar indata och utdata, typ av maskinvara som ska användas, programvara som ska installeras och hur du kör koden. Innehåller command information för att köra ett enda kommando.

Konfigurera kommandot

Du använder det allmänna syftet command för att köra träningsskriptet och utföra önskade uppgifter. Skapa ett Command objekt för att ange konfigurationsinformationen för ditt träningsjobb.

  • Indata för det här kommandot omfattar antalet epoker, inlärningshastighet, momentum och utdatakatalog.
  • För parametervärdena:
    • ange det beräkningskluster cpu_compute_target = "cpu-cluster" som du skapade för att köra det här kommandot.
    • ange den anpassade miljö sklearn-env som du skapade för att köra Azure Machine Learning-jobbet.
    • konfigurera själva kommandoradsåtgärden – i det här fallet är python train_iris.pykommandot . Du kan komma åt indata och utdata i kommandot via notationen ${{ ... }} och
    • konfigurera metadata, till exempel visningsnamn och experimentnamn. där ett experiment är en container för alla iterationer man gör i ett visst projekt. Alla jobb som skickas under samma experimentnamn visas bredvid varandra i Azure Machine Learning-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",
)

Skicka jobbet

Nu är det dags att skicka jobbet som ska köras i Azure Machine Learning. Den här gången använder create_or_update du på ml_client.jobs.

ml_client.jobs.create_or_update(job)

När jobbet har slutförts registrerar det en modell på din arbetsyta (som ett resultat av träningen) och matar ut en länk för att visa jobbet i Azure Machine Learning-studio.

Varning

Azure Machine Learning kör träningsskript genom att kopiera hela källkatalogen. Om du har känsliga data som du inte vill ladda upp använder du en .ignore-fil eller tar inte med den i källkatalogen.

Vad händer under jobbkörningen?

När jobbet körs går det igenom följande steg:

  • Förbereder: En docker-avbildning skapas enligt den definierade miljön. Avbildningen laddas upp till arbetsytans containerregister och cachelagras för senare körningar. Loggar strömmas också till körningshistoriken och kan visas för att övervaka förloppet. Om en kuraterad miljö anges används den cachelagrade avbildningsstöd som den kurerade miljön.

  • Skalning: Klustret försöker skala upp om klustret kräver fler noder för att köra körningen än vad som för närvarande är tillgängligt.

  • Körs: Alla skript i skriptmappens src laddas upp till beräkningsmålet, datalager monteras eller kopieras och skriptet körs. Utdata från stdout och mappen ./logs strömmas till körningshistoriken och kan användas för att övervaka körningen.

Finjustera modellhyperparametrar

Nu när du har sett hur du gör en enkel Scikit-learn-träningskörning med hjälp av SDK:et ska vi se om du kan förbättra modellens noggrannhet ytterligare. Du kan finjustera och optimera modellens hyperparametrar med hjälp av Funktionerna i Azure Machine Learning sweep .

Om du vill justera modellens hyperparametrar definierar du det parameterutrymme som du vill söka i under träningen. Det gör du genom att ersätta några av parametrarna (kernel och penalty) som skickas till träningsjobbet med särskilda indata från azure.ml.sweep paketet.

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

Sedan konfigurerar du svepning på kommandojobbet med hjälp av några svepspecifika parametrar, till exempel det primära måttet att titta på och samplingsalgoritmen som ska användas.

I följande kod använder vi slumpmässig sampling för att prova olika konfigurationsuppsättningar med hyperparametrar i ett försök att maximera vårt primära mått, 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,
)

Nu kan du skicka det här jobbet som tidigare. Den här gången kör du ett svepjobb som sveper över ditt tågjobb.

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)

Du kan övervaka jobbet med hjälp av länken för studioanvändargränssnittet som visas under jobbkörningen.

Hitta och registrera den bästa modellen

När alla körningar har slutförts kan du hitta den körning som skapade modellen med högsta noggrannhet.

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

Du kan sedan registrera den här modellen.

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

Distribuera modellen

När du har registrerat din modell kan du distribuera den på samma sätt som andra registrerade modeller i Azure Machine Learning. Mer information om distribution finns i Distribuera och poängsätta en maskininlärningsmodell med hanterad onlineslutpunkt med Python SDK v2.

Nästa steg

I den här artikeln har du tränat och registrerat en scikit-learn-modell och lärt dig om distributionsalternativ. Mer information om Azure Machine Learning finns i de här andra artiklarna.