Compartir a través de


Procesamiento de imágenes con implementaciones de modelos por lotes

SE APLICA A:Extensión ML de la CLI de Azure v2 (actual)SDK de Python azure-ai-ml v2 (actual)

Puede usar implementaciones de modelos por lotes para procesar datos tabulares, pero también cualquier otro tipo de archivo, como imágenes. Esas implementaciones se admiten tanto en MLflow como en modelos personalizados. En este artículo, aprenderá a implementar un modelo que clasifica las imágenes según la taxonomía ImageNet.

Requisitos previos

  • Suscripción a Azure. Si no tiene una suscripción de Azure, cree una cuenta gratuita antes de empezar. Pruebe la versión gratuita o de pago de Azure Machine Learning.

  • Un área de trabajo de Azure Machine Learning. Para crear un área de trabajo, vea Administración de áreas de trabajo de Azure Machine Learning.

  • Asegúrese de que dispone de los siguientes permisos en el área de trabajo de Machine Learning:

    • Crear o administrar implementaciones y puntos de conexión por lotes: use los roles de propietario, colaborador o un rol personalizado que permita Microsoft.MachineLearningServices/workspaces/batchEndpoints/*.
    • Creación de implementaciones de Azure Resource Manager en el grupo de recursos del área de trabajo: use un rol de propietario, colaborador o personalizado que permita Microsoft.Resources/deployments/write en el grupo de recursos donde se implementa el área de trabajo.
  • Instale el siguiente software para trabajar con Machine Learning:

    Ejecute el siguiente comando para instalar la CLI de Azure y la extensión ml para Azure Machine Learning:

    az extension add -n ml
    

    Las implementaciones de componentes de canalización para puntos de conexión por lotes se introdujeron en la versión 2.7 de la extensión ml para la CLI de Azure. Use el comando az extension update --name ml para obtener la versión más reciente.


Conexión con su área de trabajo

El área de trabajo es el recurso de nivel superior de Machine Learning. Proporciona un lugar centralizado para trabajar con todos los artefactos que cree al usar Machine Learning. En esta sección, se conectará al área de trabajo donde realizará las tareas de implementación.

En el siguiente comando, escriba los valores de id. de suscripción, área de trabajo, ubicación y grupo de recursos:

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

Acerca de este ejemplo

En este artículo se usa un modelo que se creó con TensorFlow junto con la arquitectura RestNet. Para obtener más información, consulte Asignaciones de identidades en redes residuales profundas. Puede descargar un ejemplo de este modelo. El modelo tiene las restricciones siguientes:

  • Funciona con imágenes de tamaño de 244 x 244 (tensores de (224, 224, 3)).
  • Requiere que las entradas se escalen al intervalo [0,1].

La información de este artículo se basa en ejemplos de código que se encuentran en el repositorio azureml-examples. Para ejecutar los comandos localmente sin tener que copiar o pegar YAML y otros archivos, clone el repositorio. Cambie los directorios a cli/endpoints/batch/deploy-models/imagenet-classifier si usa la CLI de Azure o sdk/python/endpoints/batch/deploy-models/imagenet-classifier si usa el SDK para Python.

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

Siga estos pasos en Jupyter Notebooks

Puede seguir este ejemplo en un Jupyter Notebook. En el repositorio clonado, abra el cuaderno: imagenet-classifier-batch.ipynb.

Clasificación de imágenes con implementaciones por lotes

En este ejemplo, aprenderá a implementar un modelo de aprendizaje profundo que pueda clasificar una imagen determinada según la Taxonomía de ImageNet.

Creación del punto de conexión

Cree el punto de conexión que hospeda el modelo:

  1. Especifique el nombre del punto de conexión.

    ENDPOINT_NAME="imagenet-classifier-batch"
    
  2. Cree el siguiente archivo YAML para definir el punto de conexión por lotes, 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 crear el punto de conexión, ejecute el código siguiente:

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

Registro del modelo

Las implementaciones de modelos solo pueden implementar modelos registrados. Debe registrar el modelo. Puede omitir este paso si el modelo que está intentando implementar ya está registrado.

  1. Descargue una copia del modelo.

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

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

Crear un script de puntuación

Cree un script de puntuación que pueda leer las imágenes proporcionadas por la implementación por lotes y devolver las puntuaciones del modelo.

  • El método init carga el modelo mediante el módulo keras en tensorflow.
  • El método run se ejecuta para cada miniproceso que proporciona la implementación por lotes.
  • El método run lee una imagen del archivo a la vez.
  • El método run cambia el tamaño de las imágenes a los tamaños esperados del modelo.
  • El método run vuelve a escalar las imágenes al dominio de intervalo [0,1], que es lo que espera el modelo.
  • El script devuelve las clases y las probabilidades asociadas a las predicciones.

Este código es el archivocode/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)

Sugerencia

Aunque la implementación proporciona imágenes en mini lotes, este script de puntuación procesa una imagen cada vez. Este es un patrón común porque intentar cargar todo el lote y enviarlo al modelo a la vez podría dar lugar a una presión de memoria alta en el ejecutor de lotes (excepciones de OOM).

Hay ciertos casos en los que, al hacerlo, se habilita un alto rendimiento en la tarea de puntuación. Este es el caso de las implementaciones por lotes a través del hardware de GPU donde desea lograr un uso elevado de GPU. Para obtener un script de puntuación que aproveche este enfoque, consulte Implementaciones de alto rendimiento.

Nota:

Si desea implementar un modelo generativo, que genera archivos, aprenda a crear un script de puntuación: Personalizar salidas en implementaciones por lotes.

Creación de la implementación

Después de crear el script de puntuación, cree una implementación por lotes para él. Utilice el siguiente procedimiento:

  1. Asegúrese de que tiene un clúster de proceso creado donde puede crear la implementación. En este ejemplo, use un clúster de proceso denominado gpu-cluster. Aunque no es necesario, el uso de GPU acelera el procesamiento.

  2. Indique en qué entorno se va a ejecutar la implementación. En este ejemplo, el modelo se ejecuta en TensorFlow. Azure Machine Learning ya tiene un entorno con el software necesario instalado, por lo que puede reutilizar este entorno. Debe agregar un par de dependencias en un archivo conda.yml.

    La definición del entorno se incluye en el archivo de implementación.

    compute: azureml:gpu-cluster
    environment:
      name: tensorflow212-cuda11-gpu
      image: mcr.microsoft.com/azureml/curated/tensorflow-2.12-cuda11:latest
    
  3. Cree la implementación.

    Para crear una nueva implementación en el punto de conexión creado, cree una configuración de YAML como en el ejemplo siguiente. Para ver otras propiedades, consulte la esquema de YAML de punto de conexión por lotes 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
    

    Cree la implementación con el siguiente comando:

    az ml batch-deployment create --file deployment-by-file.yml --endpoint-name $ENDPOINT_NAME --set-default
    
  4. Aunque puede invocar una implementación específica dentro de un punto de conexión, normalmente querrá invocar el propio punto de conexión y dejar que este decida qué implementación se va a usar. Esta implementación se denomina implementación predeterminada.

    Este enfoque le permite cambiar la implementación predeterminada y cambiar el modelo que atiende la implementación sin cambiar el contrato con el usuario invocando el punto de conexión. Use el código siguiente para actualizar la implementación predeterminada:

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

El punto de conexión por lotes está listo para usarse.

Prueba de la implementación

Para probar el punto de conexión, use un ejemplo de 1000 imágenes del conjunto de datos ImageNet original. Los puntos de conexión de lote solo pueden procesar los datos que se encuentran en la nube y que son accesibles desde el área de trabajo de Azure Machine Learning. Cárguelo en un almacén de datos de Azure Machine Learning. Cree un recurso de datos que se pueda usar para invocar el punto de conexión para la puntuación.

Nota:

Los puntos de conexión de Batch aceptan datos que se pueden colocar en varios tipos de ubicaciones.

  1. Descargue los datos de ejemplo asociados.

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

    Nota:

    Si no tiene wget instalado localmente, instálelo o use un explorador para obtener el archivo .zip.

  2. Cree el recurso de datos a partir de los datos descargados.

    1. Cree una definición de recurso de datos en un archivo YAML denominado 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. Cree el recurso de datos.

      az ml data create -f imagenet-sample-unlabeled.yml
      
  3. Cuando los datos se carguen y estén listos para usarse, invoque el punto de conexión.

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

    Nota:

    Si la utilidad jq no está instalada, consulte Descargar jq.


Sugerencia

No se indica el nombre de implementación en la operación de invocación. Esto se debe a que el punto de conexión enruta automáticamente el trabajo a la implementación predeterminada. Puesto que el punto de conexión solo tiene una implementación, esa es la predeterminada. Puede tener como destino una implementación específica indicando el argumento o parámetro deployment_name.

  1. Un trabajo por lotes se inicia en cuanto se devuelve el comando. Puede supervisar el estado del trabajo hasta que finalice.

    az ml job show -n $JOB_NAME --web
    
  2. Una vez finalizada la implementación, descargue las predicciones.

    Use los siguientes comandos para descargar las predicciones:

    az ml job download --name $JOB_NAME --output-name score --download-path ./
    
  3. Las predicciones tienen un aspecto similar al siguiente resultado. Las predicciones se combinan con las etiquetas para la comodidad del lector. Para obtener más información acerca de cómo lograr este efecto, consulte el cuaderno asociado.

    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 class probabilities etiqueta
    n02088094_Lebrel_afgano.JPEG 161 0,994745 Lebrel afgano
    n02088238_basset 162 0,999397 basset
    n02088364_beagle.JPEG 165 0,366914 bluetick
    n02088466_Perro_de_San_Huberto.JPEG 164 0,926464 Perro de San Huberto
    ... ... ... ...

Implementaciones de alto rendimiento

Como se ha mencionado antes, la implementación procesa una imagen a la vez, incluso cuando la implementación por lotes está proporcionando un lote de ellos. En la mayoría de los casos, este enfoque es mejor. Simplifica la ejecución de los modelos y evita los posibles problemas de memoria insuficiente. Sin embargo, en algunos otros casos, es posible que quiera saturar tanto como sea posible el hardware subyacente. Esta situación es el caso de las GPU, por ejemplo.

En esos casos, es posible que desee realizar inferencias en todo el lote de datos. Este enfoque implica cargar todo el conjunto de imágenes en la memoria y enviarlos directamente al modelo. En el ejemplo siguiente se usa TensorFlow para leer el lote de imágenes y puntuarlas todas a la vez. También usa TensorFlow operaciones para realizar cualquier preprocesamiento de datos. Toda la canalización se produce en el mismo dispositivo que se usa (CPU/GPU).

Advertencia

Algunos modelos tienen una relación no lineal con el tamaño de las entradas en términos del consumo de memoria. Para evitar excepciones fuera de memoria, vuelva a procesar por lotes (como se hace en este ejemplo) o reduzca el tamaño de los lotes creados por la implementación de lotes.

  1. Cree el código de script de puntuación/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"]
        )
    
    • Este script crea un conjunto de datos de tensor a partir del minilote enviado por la implementación por lotes. Este conjunto de datos se preprocesa para obtener los tensores esperados para el modelo mediante la operación map con la función decode_img.
    • El conjunto de datos se vuelve a procesar por lotes (16) para enviar los datos al modelo. Use este parámetro para controlar la cantidad de información que puede cargar en la memoria y enviar al modelo a la vez. Si se ejecuta en una GPU, debe ajustar cuidadosamente este parámetro para lograr el uso máximo de la GPU justo antes de obtener una excepción de OOM.
    • Una vez calculadas las predicciones, los tensores se convierten en numpy.ndarray.
  2. Cree la implementación.

    1. Para crear una nueva implementación en el punto de conexión creado, cree una configuración de YAML como en el ejemplo siguiente. Para ver otras propiedades, consulte la esquema de YAML de punto de conexión por lotes 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. Cree la implementación con el siguiente comando:
    az ml batch-deployment create --file deployment-by-batch.yml --endpoint-name $ENDPOINT_NAME --set-default
    
  3. Puede usar esta nueva implementación con los datos de ejemplo mostrados anteriormente. Recuerde que para invocar esta implementación, indique el nombre de la implementación en el método de invocación o establézcalo como predeterminado.

Consideraciones sobre el procesamiento de imágenes de modelos de MLflow

Los modelos de MLflow en puntos de conexión de Batch admiten la lectura de imágenes como datos de entrada. Dado que las implementaciones de MLflow no requieren un script de puntuación, tenga en cuenta las siguientes consideraciones al usarlas:

  • Los archivos de imagen admitidos incluyen: .png, .jpg, .jpeg, .tiff, .bmp, y .gif.
  • Los modelos de MLflow deben esperar recibir un np.ndarray como entrada que coincida con las dimensiones de la imagen de entrada. Para admitir varios tamaños de imagen en cada lote, el ejecutor de lotes invoca el modelo de MLflow una vez por archivo de imagen.
  • Se recomienda encarecidamente que los modelos de MLflow incluyan una firma. Si lo hacen, debe ser de tipo TensorSpec. Las entradas se vuelven a configurar para que coincidan con la forma del tensor si está disponible. Si no hay ninguna firma disponible, se infieren tensores de tipo np.uint8.
  • Para los modelos que incluyen una firma y se espera que controle el tamaño variable de las imágenes, incluya una firma que pueda garantizarla. Por ejemplo, en el ejemplo de firma siguiente se permiten lotes de 3 imágenes canaladas.
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)

Puede encontrar un ejemplo de trabajo en el cuaderno de Jupyter imagenet-classifier-mlflow.ipynb. Para obtener más información acerca de cómo usar modelos de MLflow en implementaciones por lotes, consulte Uso de modelos de MLflow en implementaciones por lotes.

Pasos siguientes