Preparar modelos scikit-learn em escala com o Azure Machine Learning

APLICA-SE A: SDK python azure-ai-ml v2 (atual)

Neste artigo, saiba como executar os scripts de formação scikit-learn com o SDK Python v2 do Azure Machine Learning.

Os scripts de exemplo neste artigo são utilizados para classificar imagens de flores de íris para criar um modelo de machine learning com base no conjunto de dados de íris do scikit-learn.

Quer esteja a preparar um modelo de aprendizagem automática scikit-learn a partir da base ou a trazer um modelo existente para a cloud, pode utilizar o Azure Machine Learning para aumentar horizontalmente as tarefas de preparação open source com recursos de computação na cloud elástica. Pode criar, implementar, versão e monitorizar modelos de nível de produção com o Azure Machine Learning.

Pré-requisitos

Pode executar o código para este artigo numa instância de computação do Azure Machine Learning ou na sua própria Jupyter Notebook.

  • Instância de computação do Azure Machine Learning

    • Conclua o Início Rápido: Introdução ao Azure Machine Learning para criar uma instância de computação. Todas as instâncias de computação incluem um servidor de blocos de notas dedicado pré-carregado com o SDK e o repositório de exemplo de blocos de notas.
    • Selecione o separador bloco de notas no estúdio do Azure Machine Learning. Na pasta de preparação de exemplos, localize um bloco de notas concluído e expandido ao navegar para este diretório: tarefas de sdk >> v2 > de passo > único scikit-learn > train-hyperparameter-tune-deploy-with-sklearn.
    • Pode utilizar o código pré-preenchido na pasta de preparação de exemplo para concluir este tutorial.
  • O seu servidor de blocos de notas do Jupyter.

Configurar a tarefa

Esta secção configura a tarefa de preparação ao carregar os pacotes Python necessários, ligar a uma área de trabalho, criar um recurso de computação para executar uma tarefa de comando e criar um ambiente para executar a tarefa.

Ligar à área de trabalho

Primeiro, terá de se ligar à área de trabalho do AzureML. A área de trabalho do AzureML é o recurso de nível superior do serviço. Fornece-lhe um local centralizado para trabalhar com todos os artefactos que cria quando utiliza o Azure Machine Learning.

Estamos a utilizar DefaultAzureCredential para obter acesso à área de trabalho. Esta credencial deve ser capaz de processar a maioria dos cenários de autenticação do SDK do Azure.

Se DefaultAzureCredential não funcionar para si, consulte azure-identity reference documentation ou Set up authentication para obter mais credenciais disponíveis.

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

# Authentication package
from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()

Se preferir utilizar um browser para iniciar sessão e autenticar, deve remover os comentários no código seguinte e utilizá-lo.

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

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

Em seguida, obtenha uma alça para a área de trabalho ao fornecer o ID da Subscrição, o nome do Grupo de Recursos e o nome da área de trabalho. Para localizar estes parâmetros:

  1. Procure o nome da área de trabalho no canto superior direito da barra de ferramentas estúdio do Azure Machine Learning.
  2. Selecione o nome da área de trabalho para mostrar o Grupo de Recursos e o ID da Subscrição.
  3. Copie os valores do Grupo de Recursos e do ID da Subscrição para o código.
# 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>",
)

O resultado da execução deste script é uma alça de área de trabalho que irá utilizar para gerir outros recursos e tarefas.

Nota

A criação MLClient não ligará o cliente à área de trabalho. A inicialização do cliente é preguiçosa e aguardará pela primeira vez que precisar de fazer uma chamada. Neste artigo, isto acontecerá durante a criação da computação.

Criar um recurso de computação para executar a tarefa

O AzureML precisa de um recurso de computação para executar uma tarefa. Este recurso pode ser uma máquina única ou com vários nós com Linux ou SO Windows, ou um recurso de computação específico, como o Spark.

No script de exemplo seguinte, aprovisionamos um Linux compute cluster. Pode ver a Azure Machine Learning pricing página para obter a lista completa dos tamanhos e preços das VMs. Só precisamos de um cluster básico para este exemplo; Assim, vamos escolher um modelo de Standard_DS3_v2 com 2 núcleos vCPU e 7 GB de RAM para criar uma computação 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}"
)

Criar um ambiente de trabalho

Para executar uma tarefa do AzureML, precisará de um ambiente. Um ambiente do AzureML encapsula as dependências (como o runtime de software e bibliotecas) necessárias para executar o script de preparação de machine learning no recurso de computação. Este ambiente é semelhante a um ambiente Python no seu computador local.

O AzureML permite-lhe utilizar um ambiente organizado (ou pronto) ou criar um ambiente personalizado com uma imagem do Docker ou uma configuração conda. Neste artigo, irá criar um ambiente personalizado para as suas tarefas através de um ficheiro YAML conda.

Criar um ambiente personalizado

Para criar o seu ambiente personalizado, irá definir as dependências do Conda num ficheiro YAML. Primeiro, crie um diretório para armazenar o ficheiro. Neste exemplo, nomeámos o diretório env.

import os

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

Em seguida, crie o ficheiro no diretório de dependências. Neste exemplo, nomeámos o ficheiro 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

A especificação contém alguns pacotes habituais (como numpy e pip) que irá utilizar na sua tarefa.

Em seguida, utilize o ficheiro YAML para criar e registar este ambiente personalizado na sua área de trabalho. O ambiente será empacotado num contentor do Docker no runtime.

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

Para obter mais informações sobre como criar e utilizar ambientes, veja Criar e utilizar ambientes de software no Azure Machine Learning.

Configurar e submeter a tarefa de preparação

Nesta secção, vamos abordar como executar um trabalho de preparação com um script de preparação que fornecemos. Para começar, irá criar a tarefa de preparação ao configurar o comando para executar o script de preparação. Em seguida, irá submeter a tarefa de formação a executar no AzureML.

Preparar o script de preparação

Neste artigo, fornecemos o script de preparação train_iris.py. Na prática, deve ser capaz de utilizar qualquer script de preparação personalizado como está e executá-lo com o AzureML sem ter de modificar o código.

Nota

O script de preparação fornecido faz o seguinte:

  • mostra como registar algumas métricas na execução do AzureML;
  • transfere e extrai os dados de preparação com iris = datasets.load_iris(); e
  • prepara um modelo e, em seguida, guarda-o e regista-o.

Para utilizar e aceder aos seus próprios dados, veja como ler e escrever dados numa tarefa para disponibilizar dados durante a preparação.

Para utilizar o script de preparação, crie primeiro um diretório onde irá armazenar o ficheiro.

import os

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

Em seguida, crie o ficheiro de script no diretório de origem.

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

Criar a tarefa de preparação

Agora que tem todos os recursos necessários para executar a sua tarefa, está na altura de o criar com o SDK Python v2 do AzureML. Para tal, vamos criar um command.

Um AzureML command é um recurso que especifica todos os detalhes necessários para executar o código de preparação na cloud. Estes detalhes incluem as entradas e saídas, o tipo de hardware a utilizar, o software a instalar e como executar o código. Contém command informações para executar um único comando.

Configurar o comando

Irá utilizar o objetivo command geral para executar o script de preparação e realizar as tarefas pretendidas. Crie um Command objeto para especificar os detalhes de configuração da sua tarefa de preparação.

  • As entradas para este comando incluem o número de épocas, taxa de aprendizagem, dinâmica e diretório de saída.
  • Para os valores dos parâmetros:
    • forneça o cluster cpu_compute_target = "cpu-cluster" de computação que criou para executar este comando;
    • forneça o ambiente sklearn-env personalizado que criou para executar a tarefa do AzureML;
    • configure a ação da linha de comandos em si— neste caso, o comando é python train_iris.py. Pode aceder às entradas e saídas no comando através da ${{ ... }} notação; e
    • configurar os metadados, como o nome a apresentar e o nome da experimentação; em que uma experimentação é um contentor para todas as iterações que se faz num determinado projeto. Tenha em atenção que todas as tarefas submetidas com o mesmo nome de experimentação seriam listadas ao lado umas das outras no 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",
)

Submeter o trabalho

Chegou a altura de submeter a tarefa a ser executada no AzureML. Desta vez, irá utilizar create_or_update em ml_client.jobs.

ml_client.jobs.create_or_update(job)

Depois de concluída, a tarefa registará um modelo na área de trabalho (como resultado da preparação) e produzirá uma ligação para ver a tarefa no AzureML Studio.

Aviso

O Azure Machine Learning executa scripts de preparação ao copiar todo o diretório de origem. Se tiver dados confidenciais que não pretende carregar, utilize um ficheiro .ignore ou não os inclua no diretório de origem.

O que acontece durante a execução da tarefa

À medida que a tarefa é executada, passa pelas seguintes fases:

  • A preparar: é criada uma imagem do Docker de acordo com o ambiente definido. A imagem é carregada para o registo de contentor da área de trabalho e colocada em cache para execuções posteriores. Os registos também são transmitidos para o histórico de execuções e podem ser visualizados para monitorizar o progresso. Se for especificado um ambiente organizado, será utilizado o suporte de imagem em cache que o ambiente organizado.

  • Dimensionamento: o cluster tenta aumentar verticalmente se o cluster precisar de mais nós para executar a execução do que está atualmente disponível.

  • Em execução: todos os scripts na pasta de scripts src são carregados para o destino de computação, os arquivos de dados são montados ou copiados e o script é executado. As saídas do stdout e da pasta ./logs são transmitidas em fluxo para o histórico de execuções e podem ser utilizadas para monitorizar a execução.

Otimizar hiperparâmetros de modelo

Agora que já viu como fazer uma execução de preparação simples do Scikit-learn com o SDK, vamos ver se consegue melhorar ainda mais a precisão do seu modelo. Pode otimizar e otimizar os hiperparâmetros do nosso modelo com as capacidades do sweep Azure Machine Learning.

Para ajustar os hiperparâmetros do modelo, defina o espaço de parâmetros no qual pretende procurar durante a preparação. Irá fazê-lo ao substituir alguns dos parâmetros (kernel e penalty) transmitidos para a tarefa de preparação por entradas especiais do azure.ml.sweep pacote.

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

Em seguida, irá configurar a operação de varrimento na tarefa de comando, utilizando alguns parâmetros específicos de varrimento, como a métrica primária a observar e o algoritmo de amostragem a utilizar.

No código seguinte, utilizamos a amostragem aleatória para experimentar diferentes conjuntos de configuração de hiperparâmetros numa tentativa de maximizar a nossa métrica primária, 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,
)

Agora, pode submeter esta tarefa como anteriormente. Desta vez, vais fazer um trabalho de varrer o teu trabalho de comboio.

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)

Pode monitorizar a tarefa com a ligação de interface de utilizador do studio que é apresentada durante a execução da tarefa.

Localizar e registar o melhor modelo

Depois de todas as execuções serem concluídas, pode encontrar a execução que produziu o modelo com a maior precisão.

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

Em seguida, pode registar este modelo.

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

Implementar o modelo

Depois de registar o modelo, pode implementá-lo da mesma forma que qualquer outro modelo registado no Azure ML. Para obter mais informações sobre a implementação, veja Implementar e classificar um modelo de machine learning com o ponto final online gerido com o SDK Python v2.

Passos seguintes

Neste artigo, preparou e registou um modelo scikit-learn e aprendeu sobre as opções de implementação. Veja estes outros artigos para saber mais sobre o Azure Machine Learning.