Treine os modelos scikit-learn em escala com o Azure Machine Learning

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

Neste artigo, saiba como executar seus scripts de treinamento do scikit-learn com o SDK do Python v2. do Azure Machine Learning.

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

Se você está treinando em um modelo scikit-learn de machine learning do zero ou está usando um modelo existente na nuvem, você pode usar o Azure Machine Learning para escalar horizontalmente execuções de treinamento de open-source usando recursos de computação em nuvem elásticos. Você pode criar, implantar, versionar e monitorar modelos de nível de produção com o Azure Machine Learning.

Pré-requisitos

Você pode executar o código desse artigo em uma instância de computação do Azure Machine Learning ou em seu próprio Jupyter Notebook.

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

    • Conclua Crie recursos para começar para criar uma instância de computação. Cada instância de computação inclui um servidor de notebook dedicado pré-carregado com o SDK e o repositório de exemplo de notebooks.
    • Selecione a guia Notebook no Estúdio do Azure Machine Learning. Na pasta de exemplos de treinamento, encontre um documento concluído e expandido. Para isso, navegue para este diretório: v2 > sdk > jobs > single-step > scikit-learn > train-hyperparameter-tune-deploy-with-sklearn.
    • Você pode usar o código pré-preenchido na pasta de treinamento de exemplo para concluir este tutorial.
  • Seu servidor do Jupyter Notebook.

Configurar o trabalho

Esta seção configura o trabalho para treinamento carregando os pacotes necessários do Python, conectando-se a um workspace, criando um recurso de computação para executar um trabalho de comando e criando um ambiente para executar o trabalho.

Conectar-se ao workspace

Primeiro, será necessário se conectar ao Workspace do Azure Machine Learning. O workspace do Azure Machine Learning é o recurso de nível superior para o serviço. Ele fornece um local centralizado para trabalhar com todos os artefatos que você criar ao usar o Azure Machine Learning.

Estamos usando DefaultAzureCredential para obter acesso ao workspace. Esta credencial deve poder lidar com a maioria dos cenários de autenticação do SDK do Azure.

Se DefaultAzureCredential não funcionar para você, 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 você preferir usar um navegador para entrar e se autenticar, remova os comentários no código a seguir e use-o.

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

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

Em seguida, obtenha um identificador para o workspace. Para isso, forneça sua ID de Assinatura, o nome do Grupo de Recursos e o nome do workspace. Para localizar esses parâmetros:

  1. Procure o nome do workspace no canto superior direito da barra de ferramentas do Estúdio do Azure Machine Learning.
  2. Selecione o nome do workspace para exibir o Grupo de Recursos e a ID da Assinatura.
  3. Copie os valores do Grupo de Recursos e da ID da Assinatura no 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 desse script é um identificador de workspace que você usa para gerenciar outros recursos e trabalhos.

Observação

A criação do MLClient não conectará o cliente ao workspace. A inicialização do cliente é lenta e aguardará pela primeira vez que precisar fazer uma chamada. Neste artigo, isso ocorrerá durante a criação da computação.

Criar um recurso de computação

O Azure Machine Learning precisa de um recurso de computação para executar um trabalho. Esse recurso pode ser computadores com um ou vários nós com o SO Linux ou Windows ou uma malha de computação específica como o Spark.

No script de exemplo a seguir, provisionamos um Linux compute cluster. Você pode ver na página Azure Machine Learning pricing a lista completa de tamanhos e preços de VM. Só precisamos de um cluster básico para este exemplo; Assim, escolhemos um modelo Standard_DS3_v2 com 2 núcleos de vCPU e 7 GB de RAM para criar uma computação do Azure Machine Learning.

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

Você precisa ter um ambiente para executar um trabalho do Azure Machine Learning. Um ambiente do Azure Machine Learning encapsula as dependências (como bibliotecas e runtime de software) necessárias para executar o script de treinamento de machine learning no recurso de computação. Esse ambiente é semelhante a um ambiente do Python no computador local.

O Azure Machine Learning permite que você use um ambiente coletado (ou pronto) ou crie um ambiente personalizado usando uma imagem do Docker ou uma configuração do Conda. Neste artigo, você criará um ambiente personalizado para seus trabalhos usando um arquivo YAML conda.

Criar um ambiente personalizado

Para criar seu ambiente personalizado, defina suas dependências conda em um arquivo YAML. Primeiro, crie um diretório para armazenar o arquivo. Neste exemplo, nomeamos o diretório de env.

import os

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

Em seguida, crie o arquivo no diretório de dependências. Neste exemplo, nomeamos o arquivo de conda.yml.

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

A especificação contém alguns pacotes usuais (como numpy e pip) que você usa em seu trabalho.

Em seguida, use o arquivo YAML para criar e registrar esse ambiente personalizado no seu workspace. O ambiente é empacotado em um contêiner do Docker em 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.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}"
)

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

[Opcional] Criar um ambiente personalizado com a Extensão Intel® para Scikit-Learn

Você gostaria de acelerar seus scripts scikit-learn no hardware da Intel? Tente adicionar a Extensão Intel® para Scikit-Learn ao arquivo yaml conda e siga as etapas posteriores detalhadas acima. Mostraremos como habilitar essas otimizações mais adiante neste exemplo:

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

Configurar e enviar trabalhos de treinamento

Nesta seção, abordaremos como executar um trabalho de treinamento usando um script de treinamento que fornecemos. Para começar, você cria o trabalho de treinamento configurando o comando para executar o script de treinamento. Em seguida, você envia o trabalho de treinamento para execução no Azure Machine Learning.

Preparar o script de treinamento

Neste artigo, fornecemos o script de treinamento train_iris.py. Na prática, você deve conseguir usar qualquer script de treinamento personalizado no estado em que se encontra e executá-lo com o Azure Machine Learning sem precisar modificar o código.

Observação

O script de treinamento fornecido faz o seguinte:

  • mostra como registrar algumas métricas na sua execução do Azure Machine Learning;
  • baixa e extrai os dados de treinamento usando iris = datasets.load_iris(); e
  • treina um modelo e, em seguida, o salva e registra.

Para usar e acessar seus dados, confira como ler e gravar dados em um trabalho para disponibilizar dados durante o treinamento.

Para usar o script de treinamento, primeiro crie um diretório no qual você armazenará o arquivo.

import os

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

Em seguida, crie o arquivo 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()

[Opcional] Habilitar otimizações da extensão Intel® para Scikit-Learn e obter mais desempenho no hardware da Intel

Se você instalou a extensão da Intel® para Scikit-Learn (conforme demonstrado na seção anterior), poderá habilitar as otimizações de desempenho adicionando as duas linhas de código à parte superior do arquivo de script, conforme mostrado abaixo.

Para saber mais sobre a extensão da Intel® para Scikit-Learn, confira a documentação do pacote.

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

Compilar o trabalho de treinamento

Agora que você tem todos os ativos necessários para executar o trabalho, é hora de compilá-lo usando o SDK v2 do Python para o Azure Machine Learning. Para executar o trabalho, criamos um command.

Um command do Azure Machine Learning é um recurso que especifica todos os detalhes necessários para executar o código de treinamento na nuvem. Esses detalhes incluem as entradas e saídas, o tipo de hardware a ser usado, o software a ser instalado e como executar o código. command contém informações para executar um único comando.

Configurar o comando

Você usa o uso geral command para executar o script de treinamento e executar as tarefas desejadas. Crie um objeto Command para especificar os detalhes de configuração do trabalho de treinamento.

  • As entradas desse comando incluem o número de épocas, a taxa de aprendizado, o momento e o diretório de saída.
  • Nos valores dos parâmetros:
    • forneça o cluster de computação cpu_compute_target = "cpu-cluster" que você criou para executar este comando;
    • forneça o ambiente personalizado sklearn-env que você criou para executar o trabalho do Azure Machine Learning;
    • configure a ação da linha de comando em si – nesse caso, o comando é python train_iris.py. É possível acessar as entradas e saídas no comando por meio da notação ${{ ... }}; e
    • configure os metadados como o nome de exibição e o nome do experimento; onde um experimento é um contêiner para todas as iterações feitas em um determinado projeto. Todos os trabalhos enviados com o mesmo nome de experimento serão listados um ao lado do outro no Estúdio do Azure Machine Learning.
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",
)

Enviar o trabalho

Agora é hora de enviar o trabalho a ser executado no Azure Machine Learning. Desta vez, você usa create_or_update em ml_client.jobs.

ml_client.jobs.create_or_update(job)

Depois de concluído, o trabalho registra um modelo em seu workspace (como resultado do treinamento) e gera um link para exibir o trabalho no Estúdio do Azure Machine Learning.

Aviso

O Azure Machine Learning executa scripts de treinamento copiando o diretório de origem inteiro. Se você tiver dados confidenciais que não quer carregar, use um arquivo .ignore ou não o inclua no diretório de origem.

O que acontece durante o trabalho

Conforme o trabalho é executado, ele passa pelos seguintes estágios:

  • Preparação: uma imagem Docker é criada de acordo com o ambiente definido. A imagem é carregada no registro de contêiner do workspace e armazenada em cache para execuções posteriores. Os logs também são transmitidos para o histórico de execuções e podem ser visualizados para monitorar o andamento. Mas se um ambiente coletado for especificado, a imagem armazenada em cache desse ambiente coletado é usada.

  • Dimensionamento: o cluster tentará escalar verticalmente se o cluster exigir mais nós para a execução, além do que está disponível no momento.

  • Execução: todos os scripts na pasta de scripts src são carregados para o destino de computação, os armazenamentos de dados são montados ou copiados e o script é executado. As saídas de stdout e a pasta ./logs são transmitidas para o histórico de execuções e podem ser usadas para o monitoramento.

Ajustar hiperparâmetros do modelo

Agora que você viu como fazer uma simples execução de treinamento do Scikit-learn usando o SDK, vamos tentar melhorar ainda mais a precisão do modelo. Você pode ajustar e otimizar os hiperparâmetros do modelo usando as funcionalidades de sweep do Azure Machine Learning.

Para ajustar os hiperparâmetros do modelo, defina o espaço de parâmetro a ser pesquisado durante o treinamento. Você faz isso substituindo alguns dos parâmetros (kernel e penalty) passados para o trabalho de treinamento por entradas especiais do pacote azure.ml.sweep.

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, você configura a varredura no trabalho de comando, usando alguns parâmetros específicos de varredura, como a métrica primária a ser observado e o algoritmo de amostragem a ser usado.

No código a seguir, usamos a amostragem aleatória para tentar diferentes conjuntos de configuração de hiperparâmetros na tentativa de maximizar 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, você pode enviar este trabalho como antes. Desta vez, você está executando um trabalho de varredura que varre seu trabalho de trem.

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)

Você pode monitorar o trabalho usando o link de interface do usuário do estúdio apresentado durante a execução do trabalho.

Localizar e registrar o melhor modelo

Depois que todas as execuções forem concluídas, você poderá 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, você pode registrar esse modelo.

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

Implantar o modelo

Depois de registrar seu modelo, você pode implantá-lo da mesma forma que qualquer outro modelo registrado no Azure Machine Learning. Para obter mais informações sobre a implantação, confira Implante e pontue um modelo de machine learning com um ponto de extremidade online gerenciado usando o SDK do Python v2.

Próximas etapas

Neste artigo, você treinou e registrou um modelo scikit-learn e aprendeu as opções de implantação. Consulte estes outros artigos para saber mais sobre Azure Machine Learning.