Processamento de imagens com implantações de modelos em lote

APLICA-SE A:Extensão de ML da CLI do Azure v2 (atual)SDK do Python azure-ai-ml v2 (atual)

Você pode usar implantações de modelos em lote para processar dados tabulares, mas também quaisquer outros tipos de arquivo, como imagens. Há suporte para essas implantações nos modelos personalizados e no MLflow. Nesse artigo, você aprenderá a implantar um modelo que classifica imagens de acordo com a taxonomia ImageNet.

Pré-requisitos

  • Uma assinatura do Azure. Caso não tenha uma assinatura do Azure, crie uma conta gratuita antes de começar. Experimente a versão gratuita ou paga do Azure Machine Learning.

  • Um workspace do Azure Machine Learning. Para criar um workspace, confira Gerenciar workspaces do Azure Machine Learning.

  • Certifique-se de que você tenha as seguintes permissões no espaço de trabalho do Machine Learning:

    • Criar ou gerenciar implantações e pontos de extremidade em lote: use uma função de Proprietário, Colaborador ou Personalizada que permita Microsoft.MachineLearningServices/workspaces/batchEndpoints/*.
    • Crie implantações do Azure Resource Manager no grupo de recursos do espaço de trabalho: use uma função de Proprietário, Colaborador ou Personalizada que permita Microsoft.Resources/deployments/write no grupo de recursos onde o espaço de trabalho está implantado.
  • Instale o seguinte software para trabalhar com o Machine Learning:

    Execute o seguinte comando para instalar a CLI do Azure e a extensão do Azure Machine Learning ml:

    az extension add -n ml
    

    As implantações de componente de pipeline para pontos de extremidade do Lote são introduzidas na versão 2.7 da extensão ml da CLI do Azure. Use o comando az extension update --name ml para obter a versão mais recente.


Conectar-se ao workspace

O workspace é o recurso de nível superior do Machine Learning. Ele fornece um local centralizado para trabalhar com todos os artefatos criados ao usar o Machine Learning. Nesta seção, você se conecta ao workspace em que executa as suas tarefas de implantação.

No comando a seguir, insira os valores para a sua ID de assinatura, workspace, local e grupo de recursos:

az account set --subscription <subscription>
az configure --defaults workspace=<workspace> group=<resource-group> location=<location>

Sobre este exemplo

Esse artigo usa um modelo que foi criado usando o TensorFlow junto com a arquitetura RestNet. Para obter mais informações, veja Mapeamentos de identidade em redes residuais profundas. Você pode baixar uma amostra deste modelo. O modelo tem as seguintes restrições:

  • Ele funciona com imagens do tamanho 244x244 (tensores de (224, 224, 3)).
  • Ele requer que as entradas sejam dimensionadas para o intervalo [0,1].

As informações deste artigo se baseiam em exemplos de código contidos no repositório azureml-examples. Para executar os comandos localmente sem precisar copiar/colar YAML e outros arquivos, clone o repositório. Altere os diretórios para cli/endpoints/batch/deploy-models/imagenet-classifier se estiver usando o CLI do Azure ou sdk/python/endpoints/batch/deploy-models/imagenet-classifier se estiver usando o SDK para Python.

git clone https://github.com/Azure/azureml-examples --depth 1
cd azureml-examples/cli/endpoints/batch/deploy-models/imagenet-classifier

Acompanhar em Jupyter Notebooks

Você pode acompanhar este exemplo em um Jupyter Notebook. No repositório clonado, abra o notebook: imagenet-classifier-batch.ipynb.

Classificação de imagem com implantações em lote

Nesse exemplo, você aprenderá como implantar um modelo de aprendizado profundo que pode classificar uma determinada imagem de acordo com a taxonomia do ImageNet.

Criar o ponto de extremidade

Crie o ponto de extremidade que hospeda o modelo:

  1. Especifique o nome do ponto de extremidade.

    ENDPOINT_NAME="imagenet-classifier-batch"
    
  2. Crie o seguinte arquivo YAML para definir o ponto de extremidade do lote, denominado endpoint.yml:

    $schema: https://azuremlschemas.azureedge.net/latest/batchEndpoint.schema.json
    name: imagenet-classifier-batch
    description: A batch endpoint for performing image classification using a TFHub model ImageNet model.
    auth_mode: aad_token
    

    Para criar o ponto de extremidade, execute o seguinte código:

    az ml batch-endpoint create --file endpoint.yml  --name $ENDPOINT_NAME
    

Registre o modelo

As implantações de modelos só podem implantar modelos registrados. Você precisa registrar o modelo. Você poderá pular essa etapa se o modelo que está tentando implantar já estiver registrado.

  1. Baixe uma cópia do modelo.

    wget https://azuremlexampledata.blob.core.windows.net/data/imagenet/model.zip
    unzip model.zip -d .
    
  2. Registre o modelo.

    MODEL_NAME='imagenet-classifier'
    az ml model create --name $MODEL_NAME --path "model"
    

Criar um script de pontuação

Crie um script de pontuação que possa ler as imagens fornecidas pela implantação em lote e retornar as pontuações do modelo.

  • O método init carrega o modelo usando o módulo keras emtensorflow.
  • O método run é executado para cada minilote fornecido pela implantação em lote.
  • O método run lê uma imagem do arquivo por vez.
  • O método run redimensiona as imagens para os tamanhos esperados para o modelo.
  • O método run redimensiona as imagens para o domínio [0,1] de intervalo, que é o que o modelo espera.
  • O script retorna as classes e as probabilidades associadas às previsões.

Esse código é o arquivo code/score-by-file/batch_driver.py:

import os
import numpy as np
import pandas as pd
import tensorflow as tf
from os.path import basename
from PIL import Image
from tensorflow.keras.models import load_model


def init():
    global model
    global input_width
    global input_height

    # AZUREML_MODEL_DIR is an environment variable created during deployment
    model_path = os.path.join(os.environ["AZUREML_MODEL_DIR"], "model")

    # load the model
    model = load_model(model_path)
    input_width = 244
    input_height = 244


def run(mini_batch):
    results = []

    for image in mini_batch:
        data = Image.open(image).resize(
            (input_width, input_height)
        )  # Read and resize the image
        data = np.array(data) / 255.0  # Normalize
        data_batch = tf.expand_dims(
            data, axis=0
        )  # create a batch of size (1, 244, 244, 3)

        # perform inference
        pred = model.predict(data_batch)

        # Compute probabilities, classes and labels
        pred_prob = tf.math.reduce_max(tf.math.softmax(pred, axis=-1)).numpy()
        pred_class = tf.math.argmax(pred, axis=-1).numpy()

        results.append([basename(image), pred_class[0], pred_prob])

    return pd.DataFrame(results)

Dica

Embora as imagens sejam fornecidos em minilotes pela implantação, esse script de pontuação processará uma imagem por vez. Esse é um padrão comum porque tentar carregar o lote inteiro e enviá-lo ao modelo de uma só vez pode resultar em alta pressão de memória no executor do lote (exceções OOM).

Há certos casos em que isso permite alto taxa de transferência na tarefa de pontuação. Esse é o caso de implantações em lote em hardware de GPU, onde você deseja obter alta utilização da GPU. Para um script de pontuação que aproveite essa abordagem, veja Implantações de alto taxa de transferência.

Observação

Se você deseja implantar um modelo generativo, que gera arquivos, aprenda a criar um script de pontuação: Personalize saídas em implantações em lote.

Criar a implantação

Depois de criar o script de pontuação, crie uma implantação em lote para ele. Use este procedimento:

  1. Certifique-se de ter criado um cluster de computação onde você pode criar a implantação. Nesse exemplo, use um cluster de computação denominado gpu-cluster. Embora não seja obrigatório, o uso de GPUs acelera o processamento.

  2. Indique em qual ambiente executar a implantação. Nesse exemplo, o modelo é executado em TensorFlow. O Azure Machine Learning já tem um ambiente com o software necessário instalado, então você pode reutilizá-lo. Você precisa adicionar algumas dependências em um arquivo conda.yml.

    A definição do ambiente está incluída no arquivo de implantação.

    compute: azureml:gpu-cluster
    environment:
      name: tensorflow212-cuda11-gpu
      image: mcr.microsoft.com/azureml/curated/tensorflow-2.12-cuda11:latest
    
  3. Crie a implantação.

    Para criar uma nova implantação no ponto de extremidade criado, crie uma configuração YAML como no exemplo a seguir. Para outras propriedades, veja o esquema YAML de ponto de extremidade de lote completo.

    $schema: https://azuremlschemas.azureedge.net/latest/modelBatchDeployment.schema.json
    endpoint_name: imagenet-classifier-batch
    name: imagenet-classifier-resnetv2
    description: A ResNetV2 model architecture for performing ImageNet classification in batch
    type: model
    model: azureml:imagenet-classifier@latest
    compute: azureml:gpu-cluster
    environment:
      name: tensorflow212-cuda11-gpu
      image: mcr.microsoft.com/azureml/curated/tensorflow-2.12-cuda11:latest
      conda_file: environment/conda.yaml
    code_configuration:
      code: code/score-by-file
      scoring_script: batch_driver.py
    resources:
      instance_count: 2
    settings:
      max_concurrency_per_instance: 1
      mini_batch_size: 5
      output_action: append_row
      output_file_name: predictions.csv
      retry_settings:
        max_retries: 3
        timeout: 300
      error_threshold: -1
      logging_level: info
    

    Crie a implantação com o seguinte comando:

    az ml batch-deployment create --file deployment-by-file.yml --endpoint-name $ENDPOINT_NAME --set-default
    
  4. Embora você possa invocar uma implantação específica dentro de um ponto de extremidade, normalmente você deseja invocar o próprio ponto de extremidade e deixar que ele decida qual implantação usar. Essa implantação é chamada de implantação padrão.

    Essa abordagem permite que você altere a implantação padrão e altere o modelo que atende à implantação sem alterar o contrato com o usuário que invoca o ponto de extremidade. Use o seguinte código para atualizar a implantação padrão:

    az ml batch-endpoint update --name $ENDPOINT_NAME --set defaults.deployment_name=$DEPLOYMENT_NAME
    

Seu ponto de extremidade em lote está pronto para ser usado.

Teste a implantação

Para testar o ponto final, use uma amostra de 1.000 imagens do conjunto de dados original do ImageNet. Os pontos de extremidade do lote só podem processar dados localizados na nuvem e que podem ser acessados no workspace do Azure Machine Learning. Carregue-o em um armazenamento de dados do Azure Machine Learning. Crie um ativo de dados que possa ser usado para invocar o ponto de extremidade para pontuação.

Observação

Os pontos de extremidade em lote aceitam dados que podem ser colocados em vários tipos de locais.

  1. Baixe os dados de amostra associados.

    wget https://azuremlexampledata.blob.core.windows.net/data/imagenet/imagenet-1000.zip
    unzip imagenet-1000.zip -d data
    

    Observação

    Se você não tiver o wget instalado localmente, instale-o ou use um navegador para obter o arquivo .zip.

  2. Crie o ativo de dados a partir dos dados baixados.

    1. Crie uma definição de ativo de dados em um arquivo YAML chamado imagenet-sample-unlabeled.yml:

      $schema: https://azuremlschemas.azureedge.net/latest/data.schema.json
      name: imagenet-sample-unlabeled
      description: A sample of 1000 images from the original ImageNet dataset. Download content from https://azuremlexampledata.blob.core.windows.net/data/imagenet-1000.zip.
      type: uri_folder
      path: data
      
    2. Crie o ativo de dados.

      az ml data create -f imagenet-sample-unlabeled.yml
      
  3. Quando os dados forem carregados e estiverem prontos para serem usados, invoque o ponto de extremidade.

    JOB_NAME=$(az ml batch-endpoint invoke --name $ENDPOINT_NAME --input azureml:imagenet-sample-unlabeled@latest --query name -o tsv)
    

    Observação

    Se o utilitário jq não estiver instalado, veja Baixar jq.


Dica

Você não indica o nome da implantação na operação de invocação. Isso ocorre porque o ponto de extremidade roteia automaticamente o trabalho para a implantação padrão. Como o ponto de extremidade tem apenas uma implantação, essa é a padrão. Você pode direcionar uma implantação específica indicando o argumento/parâmetro deployment_name.

  1. Um trabalho em lote começa assim que o comando retorna. Você pode monitorar o status do trabalho até que ele seja concluído.

    az ml job show -n $JOB_NAME --web
    
  2. Após a conclusão da implantação, baixe as previsões.

    Para baixar as previsões, use o seguinte comando:

    az ml job download --name $JOB_NAME --output-name score --download-path ./
    
  3. As previsões se parecem com a seguinte saída. As previsões são combinadas com os rótulos para conveniência do leitor. Para saber mais sobre como obter esse efeito, consulte o caderno associado.

    import pandas as pd
    score = pd.read_csv("named-outputs/score/predictions.csv", header=None,  names=['file', 'class', 'probabilities'], sep=' ')
    score['label'] = score['class'].apply(lambda pred: imagenet_labels[pred])
    score
    
    arquivo classe probabilities label
    n02088094_Afghan_hound.JPEG 161 0.994745 Afghan hound
    n02088238_basset 162 0.999397 basset
    n02088364_beagle.JPEG 165 0.366914 bluetick
    n02088466_bloodhound.JPEG 164 0.926464 bloodhound
    ... ... ... ...

Implantações de alta taxa de transferência

Como mencionado anteriormente, a implantação processa uma imagem por vez, mesmo quando a implantação em lote fornece um lote delas. Na maioria dos casos, essa abordagem é a melhor. Ele simplifica a execução dos modelos e evita possíveis problemas de falta de memória. Entretanto, em certos outros casos, você pode querer saturar o máximo possível o hardware subjacente. Essa situação é o caso das GPUs, por exemplo.

Nesses casos, talvez você queira fazer inferências sobre todo o lote de dados. Essa abordagem implica carregar todo o conjunto de imagens na memória e enviá-las diretamente para o modelo. O exemplo a seguir usa TensorFlow para ler o lote de imagens e pontuar todas elas de uma só vez. Ele também usa TensorFlow ops para fazer qualquer pré-processamento de dados. Todo o pipeline acontece no mesmo dispositivo que está sendo usado (CPU/GPU).

Aviso

Alguns modelos têm uma relação não linear com o tamanho das entradas em termos de consumo de memória. Para evitar exceções de falta de memória, faça o lote novamente (como feito nesse exemplo) ou diminua o tamanho dos lotes criados pela implantação em lote.

  1. Crie o script de pontuação code/score-by-batch/batch_driver.py:

    import os
    import numpy as np
    import pandas as pd
    import tensorflow as tf
    from tensorflow.keras.models import load_model
    
    
    def init():
        global model
        global input_width
        global input_height
    
        # AZUREML_MODEL_DIR is an environment variable created during deployment
        model_path = os.path.join(os.environ["AZUREML_MODEL_DIR"], "model")
    
        # load the model
        model = load_model(model_path)
        input_width = 244
        input_height = 244
    
    
    def decode_img(file_path):
        file = tf.io.read_file(file_path)
        img = tf.io.decode_jpeg(file, channels=3)
        img = tf.image.resize(img, [input_width, input_height])
        return img / 255.0
    
    
    def run(mini_batch):
        images_ds = tf.data.Dataset.from_tensor_slices(mini_batch)
        images_ds = images_ds.map(decode_img).batch(64)
    
        # perform inference
        pred = model.predict(images_ds)
    
        # Compute probabilities, classes and labels
        pred_prob = tf.math.reduce_max(tf.math.softmax(pred, axis=-1)).numpy()
        pred_class = tf.math.argmax(pred, axis=-1).numpy()
    
        return pd.DataFrame(
            [mini_batch, pred_prob, pred_class], columns=["file", "probability", "class"]
        )
    
    • Esse script constrói um conjunto de dados tensor a partir do minilote enviado pela implantação em lote. Esse conjunto de dados é pré-processado para obter os tensores esperados para o modelo usando a operação map com a função decode_img.
    • O conjunto de dados é agrupado novamente (16) para enviar os dados ao modelo. Use esse parâmetro para controlar quantas informações você pode carregar na memória e enviar para o modelo de uma só vez. Se estiver executando em uma GPU, você precisa ajustar cuidadosamente esse parâmetro para atingir o uso máximo da GPU antes de receber uma exceção OOM.
    • Após as previsões serem calculadas, os tensores são convertidos para numpy.ndarray.
  2. Crie a implantação.

    1. Para criar uma nova implantação no ponto de extremidade criado, crie uma configuração YAML como no exemplo a seguir. Para outras propriedades, veja o esquema YAML de ponto de extremidade de lote completo.
    $schema: https://azuremlschemas.azureedge.net/latest/modelBatchDeployment.schema.json
    endpoint_name: imagenet-classifier-batch
    name: imagenet-classifier-resnetv2
    description: A ResNetV2 model architecture for performing ImageNet classification in batch
    type: model
    model: azureml:imagenet-classifier@latest
    compute: azureml:gpu-cluster
    environment:
      name: tensorflow212-cuda11-gpu
      image: mcr.microsoft.com/azureml/curated/tensorflow-2.12-cuda11:latest
      conda_file: environment/conda.yaml
    code_configuration:
      code: code/score-by-batch
      scoring_script: batch_driver.py
    resources:
      instance_count: 2
    tags:
      device_acceleration: CUDA
      device_batching: 16
    settings:
      max_concurrency_per_instance: 1
      mini_batch_size: 5
      output_action: append_row
      output_file_name: predictions.csv
      retry_settings:
        max_retries: 3
        timeout: 300
      error_threshold: -1
      logging_level: info
    
    1. Crie a implantação com o seguinte comando:
    az ml batch-deployment create --file deployment-by-batch.yml --endpoint-name $ENDPOINT_NAME --set-default
    
  3. Você pode usar essa nova implantação com os dados da amostra que mostramos anteriormente. Lembre-se de que para invocar essa implantação, indique o nome da implantação no método de invocação ou defina-o como o padrão.

Considerações para modelos de MLflow que processam imagens

Os modelos de MLflow em Pontos de Extremidade do Lote dão suporte à leitura de imagens como dados de entrada. Já que as implantações do MLflow não exigem um script de pontuação, pense no seguinte ao usá-las:

  • Os arquivos de imagem suportados incluem: .png, .jpg, .jpeg, .tiff, .bmp, e .gif.
  • Os modelos MLflow devem esperar receber um np.ndarray como entrada que corresponda às dimensões da imagem de entrada. Para oferecer suporte a vários tamanhos de imagem em cada lote, o executor do lote invoca o modelo MLflow uma vez por arquivo de imagem.
  • É altamente recomendável que os modelos MLflow incluam uma assinatura. Se o fizerem, deve ser do tipo TensorSpec. As entradas são remodeladas para corresponder à forma do tensor, se disponível. Se nenhuma assinatura estiver disponível, tensores do tipo np.uint8 serão inferidos.
  • Para modelos que incluem uma assinatura e devem lidar com tamanhos variáveis ​​de imagens, inclua uma assinatura que possa garantir isso. Por exemplo, o exemplo de assinatura a seguir permite lotes de 3 imagens canalizadas.
import numpy as np
import mlflow
from mlflow.models.signature import ModelSignature
from mlflow.types.schema import Schema, TensorSpec

input_schema = Schema([
  TensorSpec(np.dtype(np.uint8), (-1, -1, -1, 3)),
])
signature = ModelSignature(inputs=input_schema)

(...)

mlflow.<flavor>.log_model(..., signature=signature)

Você pode encontrar um exemplo de funcionamento no Jupyter Notebook imagenet-classifier-mlflow.ipynb. Para obter mais informações sobre como usar modelos MLflow em implantações em lote, veja Usando modelos MLflow em implantações em lote.

Próximas etapas