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)
Implantações de modelos em lote podem ser usadas para processar dados tabulares, mas também qualquer outro tipo de arquivo, como imagens. Há suporte para essas implantações nos modelos personalizados e no MLflow. Neste tutorial, aprenderemos a implantar um modelo que classifica as imagens de acordo com a taxonomia ImageNet.
Sobre este exemplo
O modelo com o qual trabalharemos foi criado usando o TensorFlow junto com a arquitetura RestNet (Mapeamentos de Identidade em Redes Residuais Profundas). Um exemplo desse modelo pode ser baixado aqui. O modelo inclui as seguintes restrições de implantação importantes que você deve levar em consideração:
- 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 o YAML e outros arquivos, clone o repositório e altere os diretórios para o cli/endpoints/batch/deploy-models/imagenet-classifier
se você estiver usando a CLI do Azure ou para 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.
Pré-requisitos
Antes de seguir as etapas neste artigo, verifique se você tem os seguintes 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. Siga as etapas do artigo Gerenciar workspaces do Azure Machine Learning para criar um, caso ainda não tenha.
Certifique-se de ter as seguintes permissões no espaço de trabalho:
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/*
.Criar implantações do ARM no grupo de recursos do workspace: use uma função de Proprietário, Colaborador ou Personalizada que permita
Microsoft.Resources/deployments/write
no grupo de recursos em que o workspace está implantado.
Você precisa instalar o seguinte software para trabalhar com o Azure Machine Learning:
A CLI do Azure e a
ml
extensão do Azure Machine Learning.az extension add -n ml
Observação
Implantações de componente de pipeline para Pontos de Extremidade em Lote foram introduzidas na versão 2.7 da extensão
ml
para a CLI do Azure. Useaz extension update --name ml
para obter a última versão.
Conectar-se ao workspace
O workspace é o recurso de nível superior para o Azure Machine Learning. Ele fornece um local centralizado para trabalhar com todos os artefatos que você cria ao usar o Azure Machine Learning. Nesta seção, nos conectaremos ao workspace no qual você executará tarefas de implantação.
Passe os valores para sua ID de assinatura, espaço de trabalho, localização e grupo de recursos no código a seguir:
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, aprenderemos a 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 irá hospedar o modelo:
Decida qual será o nome do ponto de extremidade:
ENDPOINT_NAME="imagenet-classifier-batch"
O arquivo YAML a seguir 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
Registrar o modelo
As implantações de modelos só podem implantar modelos registrados, portanto, precisamos registrá-los. Você poderá pular essa etapa se o modelo que está tentando implantar já estiver registrado.
Baixando uma cópia do modelo:
wget https://azuremlexampledata.blob.core.windows.net/data/imagenet/model.zip unzip model.zip -d .
Registre o modelo:
MODEL_NAME='imagenet-classifier' az ml model create --name $MODEL_NAME --path "model"
Criar um script de pontuação
É necessário criar um script de pontuação que possa ler as imagens fornecidos pela implantação em lotes e retornar as pontuações do modelo. O seguinte script:
- Indica uma função
init
que carrega o modelo usando o módulokeras
emtensorflow
. - Indica uma função
run
que é executada para cada minilote fornecido pela implantação em lotes. - A função
run
lê uma imagem do arquivo de cada 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. - Ele retorna as classes e as probabilidades associadas às previsões.
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, pois tentar carregar o lote inteiro e enviá-lo ao modelo de uma só vez poderá resultar em alta pressão de memória no executor do lote (exceções OOM). No entanto, há certos casos em que isso permite alta taxa de transferência na tarefa de pontuação. Esse é o caso de implantações em lote por meio de um hardware de GPU em que queremos obter 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 se beneficia disso.
Observação
Se você estiver tentando implantar um modelo generativo (um que gera arquivos), leia como criar um script de pontuação, conforme explicado na Implantação de modelos que produzem vários arquivos.
Criar a implantação
Quando o script de pontuação for criado, será o momento de criar uma implantação em lotes para o script. Siga as seguintes etapas para criá-la:
Certifique-se de ter criado um cluster de computação onde podemos criar a implantação. Nesse exemplo vamos usar um cluster de computação chamado
gpu-cluster
. Embora não seja necessário, usamos GPUs para acelerar o processamento.É necessário indicar em qual ambiente executar a implantação. No nosso caso, o modelo executará em
TensorFlow
. O Azure Machine Learning já possui um ambiente com o software necessário instalado, de modo que será possível reutilizar esse ambiente. Vamos apenas adicionar algumas dependências em um arquivoconda.yml
.A definição do 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
Agora, criaremos a implantação.
Para criar uma nova implantação no ponto de extremidade criado, crie uma configuração
YAML
semelhante à seguinte. Você pode verificar o esquema YAML do ponto de extremidade do 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
Embora você possa invocar uma implantação específica dentro de um ponto de extremidade, geralmente desejará invocar o ponto de extremidade em si e permitir que o ponto de extremidade decida qual implantação usar. Essa implantação é chamada de implantação "padrão". Isso permite alterar a implantação padrão e, portanto, alterar o modelo que atende à implantação sem alterar o contrato com o usuário invocando o ponto de extremidade. Use a seguinte instrução para atualizar a implantação padrão:
az ml batch-endpoint update --name $ENDPOINT_NAME --set defaults.deployment_name=$DEPLOYMENT_NAME
Neste estágio, nosso ponto de extremidade em lotes está pronto para ser usado.
Testando a implantação
Para testar nosso ponto de extremidade, usaremos uma amostra de 1000 imagens do conjunto de dados ImageNet original. Os pontos de extremidade do lote só podem processar dados localizados na nuvem e que podem ser acessados no workspace do Azure Machine Learning. Neste exemplo, vamos carregá-lo em um armazenamento 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 do lote aceitam dados que podem ser colocados em vários tipos de locais.
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
Agora, vamos criar o ativo de dados dos dados que acabaram de ser 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
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)
Observação
O utilitário
jq
pode não ser instalado em todas as instalações. Você pode obter instruções neste link.Dica
Observe como não estamos indicando 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 nosso 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
.Um trabalho em lote é iniciado 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
Depois que a implantação for 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 ./
As previsões de saída terão a aparência a seguir. Observe que as previsões foram combinadas com os rótulos para a conveniência do leitor. Para saber mais sobre como fazer isso, consulte o notebook 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
file 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
Conforme 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 deles. Na maioria dos casos, essa é a melhor abordagem, pois simplifica a forma como os modelos são executados e evita possíveis problemas fora da memória. No entanto, em alguns outros, talvez queiramos saturar o máximo possível a utilização do hardware subjacente. Esse é o caso de GPUs, por exemplo.
Nesses casos, talvez queiramos executar 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 o lote de imagens e pontuar todas elas de uma só vez. Ele também usa operações TensorFlow
para fazer qualquer pré-processamento de dados para que todo o pipeline ocorra 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. Crie um lote novamente (conforme feito neste exemplo) ou diminua o tamanho dos lotes criados pela implantação em lote para evitar exceções fora da memória.
Criação do 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"] )
Dica
- Observe que esse script está construindo 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çãodecode_img
. - O conjunto de dados é enviado em lote novamente (16) para enviar os dados para o 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 em execução em uma GPU, você precisará ajustar cuidadosamente esse parâmetro para alcançar a utilização máxima da GPU pouco antes de obter uma exceção OOM.
- Depois que as previsões são computadas, os tensores são convertidos em
numpy.ndarray
.
- Observe que esse script está construindo 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
Agora, criaremos a implantação.
Para criar uma nova implantação no ponto de extremidade criado, crie uma configuração
YAML
semelhante à seguinte. Você pode verificar o esquema YAML do ponto de extremidade do 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
Você pode usar essa nova implantação com os dados da amostra que mostramos 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 conforme 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 com suporte incluem:
.png
,.jpg
,.jpeg
,.tiff
,.bmp
e.gif
. - Os modelos de MLflow devem esperar receber um
np.ndarray
como entrada que corresponda às dimensões da imagem de entrada. Para dar suporte a vários tamanhos de imagem em cada lote, o executor do lote invocará o modelo MLflow uma vez por arquivo de imagem. - Os modelos de MLflow são altamente incentivados 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 tiponp.uint8
serão inferidos. - Para modelos que incluem uma assinatura e que devem lidar com o tamanho variável das imagens, inclua uma assinatura que possa garantir isso. 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 funcionamento no Jupyter Notebook 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.