Partilhar via


Processamento de imagem com implantações de modelo em lote

APLICA-SE A:Azure CLI ml extension v2 (current)Python SDK azure-ai-ml v2 (current)

As implantações de modelo em lote podem ser usadas para processar dados tabulares, mas também qualquer outro tipo de arquivo, como imagens. Essas implantações são suportadas em modelos MLflow e personalizados. Neste tutorial, aprenderemos a implantar um modelo que classifica imagens de acordo com a taxonomia do ImageNet.

Sobre este exemplo

O modelo com o qual vamos trabalhar foi construído usando o TensorFlow juntamente com a arquitetura RestNet (Identity Mappings in Deep Residual Networks). Uma amostra deste modelo pode ser descarregada aqui. O modelo tem as seguintes restrições que é importante ter em mente para a implantação:

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

As informações neste artigo são baseadas em exemplos de código contidos no repositório azureml-examples . Para executar os comandos localmente sem ter que copiar/colar YAML e outros arquivos, clone o repositório e, em seguida, altere os diretórios para o cli/endpoints/batch/deploy-models/imagenet-classifier se você estiver usando a CLI do Azure ou sdk/python/endpoints/batch/deploy-models/imagenet-classifier se estiver usando nosso SDK para Python.

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

Acompanhe em Jupyter Notebooks

Você pode acompanhar este exemplo em um Caderno Jupyter. No repositório clonado, abra o bloco de anotações: imagenet-classifier-batch.ipynb.

Pré-requisitos

Antes de seguir as etapas neste artigo, verifique se você tem os seguintes pré-requisitos:

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

  • Uma área de trabalho do Azure Machine Learning. Se você não tiver um, use as etapas no artigo Gerenciar espaços de trabalho do Azure Machine Learning para criar um.

  • Verifique se você tem as seguintes permissões no espaço de trabalho:

    • Criar ou gerenciar pontos de extremidade em lote e implantações: use uma função Proprietário, Colaborador ou Personalizada que permita Microsoft.MachineLearningServices/workspaces/batchEndpoints/*o .

    • Criar implantações ARM no grupo de recursos do espaço de trabalho: use uma função Proprietário, Colaborador ou Personalizada que permita Microsoft.Resources/deployments/write a entrada no grupo de recursos em que o espaço de trabalho está implantado.

  • Você precisa instalar o seguinte software para trabalhar com o Azure Machine Learning:

    A CLI do Azure e a mlextensão do Azure Machine Learning.

    az extension add -n ml
    

    Nota

    As implantações de componentes de pipeline para pontos de extremidade em lote foram introduzidas na versão 2.7 da extensão para CLI ml do Azure. Use az extension update --name ml para obter a última versão dele.

Ligar à sua área de trabalho

A área de trabalho é o recurso de nível superior do Azure Machine Learning que proporciona um local centralizado para trabalhar com todos os artefactos que cria quando utiliza o Azure Machine Learning. Nesta seção, nos conectaremos ao espaço de trabalho no qual você executará tarefas de implantação.

Passe os valores para sua ID de assinatura, espaço de trabalho, local e grupo de recursos no seguinte código:

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

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

Neste exemplo, vamos aprender como implantar um modelo de aprendizado profundo que pode classificar uma determinada imagem de acordo com a taxonomia da ImageNet.

Criar o ponto de extremidade

Primeiro, vamos criar o ponto de extremidade que hospedará o modelo:

Decida o nome do ponto de extremidade:

ENDPOINT_NAME="imagenet-classifier-batch"

O seguinte arquivo YAML define um ponto de extremidade em lote:

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

Execute o código a seguir para criar o ponto de extremidade.

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

Registo do modelo

As implantações de modelo só podem implantar modelos registrados, então precisamos registrá-lo. Você pode pular esta etapa se o modelo que você está tentando implantar já estiver registrado.

  1. Download de uma cópia do modelo:

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

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

Criando um script de pontuação

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

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

código/pontuação por ficheiro/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)

Gorjeta

Embora as imagens sejam fornecidas em minilotes pela implantação, esse script de pontuação processa uma imagem de cada vez. Este é um padrão comum, pois tentar carregar o lote inteiro e enviá-lo para o modelo de uma só vez pode resultar em alta pressão de memória no executor de lote (exepções OOM). No entanto, há certos casos em que isso permite um alto rendimento na tarefa de pontuação. Este é o caso, por exemplo, de implantações em lote sobre um hardware de GPU onde queremos alcançar alta utilização de GPU. Consulte Implantações de alta taxa de transferência para obter um exemplo de um script de pontuação que tira proveito dele.

Nota

Se você estiver tentando implantar um modelo generativo (que gera arquivos), leia como criar um script de pontuação, conforme explicado em Implantação de modelos que produzem vários arquivos.

Criando a implantação

Uma vez que o script de pontuação é criado, é hora de criar uma implantação em lote para ele. Siga as seguintes etapas para criá-lo:

  1. Certifique-se de ter um cluster de computação criado onde possamos criar a implantação. Neste exemplo, vamos usar um cluster de computação chamado gpu-cluster. Embora não seja necessário, usamos GPUs para acelerar o processamento.

  2. Precisamos indicar em qual ambiente vamos executar a implantação. No nosso caso, o nosso modelo funciona em TensorFlow. O Azure Machine Learning já tem um ambiente com o software necessário instalado, para que possamos reutilizar esse ambiente. Vamos apenas adicionar algumas dependências em um conda.yml arquivo.

    A definição de ambiente será 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. Agora, vamos criar a implantação.

    Para criar uma nova implantação sob o ponto de extremidade criado, crie uma YAML configuração como a seguinte. Você pode verificar o esquema YAML do ponto de extremidade de lote completo para obter propriedades extras.

    $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
    

    Em seguida, 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, geralmente desejará invocar o próprio ponto de extremidade e permitir que o ponto de extremidade decida qual implantação usar. Essa implantação é chamada de implantação "padrão". Isso lhe dá a possibilidade de alterar a implantação padrão - e, portanto, alterar o modelo que serve a implantação - sem alterar o contrato com o usuário invocando o ponto de extremidade. Use as seguintes instruções para atualizar a implantação padrão:

    az ml batch-endpoint update --name $ENDPOINT_NAME --set defaults.deployment_name=$DEPLOYMENT_NAME
    
  5. Neste ponto, nosso ponto de extremidade em lote está pronto para ser usado.

Testando a implantação

Para testar nosso endpoint, vamos usar uma amostra de 1000 imagens do conjunto de dados ImageNet original. Os pontos de extremidade em lote só podem processar dados localizados na nuvem e acessíveis a partir do espaço de trabalho do Azure Machine Learning. Neste exemplo, vamos carregá-lo em um repositório de dados do Azure Machine Learning. Particularmente, vamos criar um ativo de dados que pode ser usado para invocar o ponto de extremidade para pontuação. No entanto, observe que os pontos de extremidade em lote aceitam dados que podem ser colocados em vários tipos de locais.

  1. Vamos baixar os dados de exemplo associados:

    wget https://azuremlexampledata.blob.core.windows.net/data/imagenet/imagenet-1000.zip
    unzip imagenet-1000.zip -d data
    
  2. Agora, vamos criar o ativo de dados a partir dos dados recém-baixados

    Crie uma definição de ativo de dados em YAML:

    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
    

    Em seguida, crie o ativo de dados:

    az ml data create -f imagenet-sample-unlabeled.yml
    
  3. Agora que os dados estão carregados e prontos para serem usados, vamos invocar o ponto de extremidade:

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

    Nota

    O utilitário jq pode não ser instalado em todas as instalações. Você pode obter instruções neste link.

    Gorjeta

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

  4. Um trabalho em lote é iniciado assim que o comando retorna. Você pode monitorar o status do trabalho até que ele termine:

    az ml job show -n $JOB_NAME --web
    
  5. Quando a implantação estiver concluída, podemos baixar as previsões:

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

    az ml job download --name $JOB_NAME --output-name score --download-path ./
    
  6. As previsões de saída serão semelhantes às seguintes. Observe que as previsões foram combinadas com os rótulos para a conveniência do leitor. Para saber mais sobre como conseguir isso, 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
    
    ficheiro classe probabilidades etiqueta
    n02088094_Afghan_hound. JPEG 161 0.994745 Cão afegão
    n02088238_basset 162 0.999397 Basset
    n02088364_beagle. JPEG 165 0.366914 carrapato azul
    n02088466_bloodhound. JPEG 164 0.926464 Bloodhound
    ... ... ... ...

Implantações de alta taxa de transferência

Como mencionado anteriormente, a implantação que acabamos de criar processa uma imagem por vez, mesmo quando a implantação em lote está fornecendo um lote delas. Na maioria dos casos, esta é a melhor abordagem, pois simplifica a forma como os modelos são executados e evita possíveis problemas de falta de memória. No entanto, em alguns outros, podemos querer saturar tanto quanto possível a utilização do hardware subjacente. É o caso, por exemplo, das GPUs.

Nesses casos, podemos querer realizar inferência em todo o lote de dados. Isso 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 lotes de imagens e marcá-las todas de uma vez. Ele também usa TensorFlow operações para fazer qualquer pré-processamento de dados para que todo o pipeline aconteça 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. Lote novamente (como feito neste exemplo) ou diminua o tamanho dos lotes criados pela implantação em lote para evitar exceções de falta de memória.

  1. Criando o script de pontuação:

    código/pontuação por lote/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"]
        )
    

    Gorjeta

    • Observe que esse script está construindo um conjunto de dados tensor a partir do minilote enviado pela implantação em lote. Este conjunto de dados é pré-processado para obter os tensores esperados para o modelo usando a map operação com a função decode_img.
    • O conjunto de dados é agrupado novamente (16) enviar os dados para o modelo. Use esse parâmetro para controlar a quantidade de informações que você pode carregar na memória e enviar para o modelo de uma só vez. Se estiver sendo executado em uma GPU, você precisará ajustar cuidadosamente esse parâmetro para obter a utilização máxima da GPU antes de obter uma exceção OOM.
    • Uma vez que as previsões são calculadas, os tensores são convertidos em numpy.ndarray.
  2. Agora, vamos criar a implantação.

    Para criar uma nova implantação sob o ponto de extremidade criado, crie uma YAML configuração como a seguinte. Você pode verificar o esquema YAML do ponto de extremidade de lote completo para obter propriedades extras.

    $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
    

    Em seguida, 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 de exemplo mostrados anteriormente. Lembre-se de que, para invocar essa implantação, você deve indicar o nome da implantação no método de invocação ou defini-lo como padrão.

Considerações para modelos MLflow que processam imagens

Os modelos MLflow em Batch Endpoints suportam a leitura de imagens como dados de entrada. Como as implantações MLflow não exigem um script de pontuação, tenha as seguintes considerações ao usá-las:

  • Os ficheiros de imagem suportados incluem: .png, .jpg, .jpeg, .tiff.bmp e .gif.
  • Os modelos MLflow devem esperar receber uma np.ndarray entrada como que corresponderá às dimensões da imagem de entrada. Para suportar vários tamanhos de imagem em cada lote, o executor de lote invocará o modelo MLflow uma vez por arquivo de imagem.
  • Os modelos MLflow são altamente encorajados a incluir uma assinatura e, se o fizerem, devem 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 são inferidos.
  • Para modelos que incluem uma assinatura e devem lidar com o tamanho variável das imagens, inclua uma assinatura que possa garanti-la. Por exemplo, o exemplo de assinatura a seguir permitirá 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 trabalho no bloco de anotações Jupyter imagenet-classifier-mlflow.ipynb. Para obter mais informações sobre como usar modelos MLflow em implantações em lote, leia Usando modelos MLflow em implantações em lote.

Próximos passos