Después de que los científicos de datos hayan desarrollado minuciosamente un modelo satisfactorio de aprendizaje automático (ML), el modelo debe implementarse de una manera que sea fácilmente accesible para otros miembros de la organización. Sin embargo, implementar modelos a gran escala con costos optimizados y eficiencia computacional puede ser una tarea abrumadora y engorrosa. Los puntos de enlace de Amazon SageMaker proporcionan una solución fácilmente escalable y rentable para la implementación de modelos. El modelo YOLOv5, distribuido bajo la licencia GPLv3, es un modelo popular de detección de objetos conocido por su eficiencia de tiempo de ejecución y precisión de detección. En esta publicación, mostramos cómo alojar un modelo YOLOv5 previamente entrenado en los puntos de enlace de SageMaker y cómo usar las funciones de AWS Lambda para invocar esos puntos de enlace.
descripción general de la solución
La siguiente imagen describe los servicios de AWS utilizados para alojar el modelo YOLOv5 con un punto de enlace de SageMaker e invocar el punto de enlace con Lambda. El portátil SageMaker accede a un modelo YOLOv5 PyTorch desde un depósito de Amazon Simple Storage Service (Amazon S3) y lo convierte en YOLOv5 TensorFlow SavedModel
formato y lo guarda de nuevo en el depósito S3. Luego, este modelo se usa cuando se aloja el punto final. Cuando se carga una imagen en Amazon S3, actúa como disparador para ejecutar la función Lambda. La función usa capas lambda de OpenCV para leer la imagen cargada y realizar la inferencia usando el punto final. Después de que se ejecute la inferencia, puede usar los resultados según sea necesario.
En esta publicación, recorremos el proceso de usar un modelo YOLOv5 estándar en PyTorch y convertirlo en un TensorFlow SavedModel
. Este modelo está alojado a través de un punto final de SageMaker. Luego, creamos y publicamos una función Lambda que llama al punto final para ejecutar la inferencia. Los modelos YOLOv5 preentrenados están disponibles en GitHub. Para esta publicación usamos el modelo yolov5l.
requisitos
Como requisito previo, debemos configurar los siguientes roles de AWS Identity and Access Management (IAM) con políticas de acceso adecuadas para SageMaker, Lambda y Amazon S3:
- Función de gestión de identidades y accesos de SageMaker – Esto requiere
AmazonS3FullAccess
Directrices adjuntas para almacenar y acceder al modelo en el depósito S3 - Rol de Lambda IAM – Este rol requiere varias políticas:
- Para acceder a las imágenes almacenadas en Amazon S3, necesitamos las siguientes políticas de IAM:
s3:GetObject
s3:ListBucket
- Para ejecutar el punto final de SageMaker, necesitamos acceso a las siguientes políticas de IAM:
sagemaker:ListEndpoints
sagemaker:DescribeEndpoint
sagemaker:InvokeEndpoint
sagemaker:InvokeEndpointAsync
- Para acceder a las imágenes almacenadas en Amazon S3, necesitamos las siguientes políticas de IAM:
También necesitará los siguientes recursos y servicios:
- La interfaz de línea de comandos de AWS (AWS CLI) que usamos para crear y configurar Lambda.
- Una instancia de cuaderno de SageMaker. Estos vienen con Docker preinstalado y lo usamos para crear las capas de Lambda. Complete los siguientes pasos para configurar la instancia del cuaderno:
- En la consola de SageMaker, cree una instancia de cuaderno y proporcione el nombre del cuaderno, el tipo de instancia (usaremos ml.c5.large para esta publicación), la función de IAM y otros parámetros.
- Clone el repositorio público y agregue el repositorio YOLOv5 proporcionado por Ultralytics.
Aloje YOLOv5 en un punto final de SageMaker
Antes de que podamos alojar el modelo YOLOv5 previamente entrenado en SageMaker, debemos exportarlo y empaquetarlo en la estructura de directorio correcta dentro model.tar.gz
. Para esta publicación, estamos demostrando cómo alojar YOLOv5 en el saved_model
Formato. El repositorio YOLOv5 proporciona una export.py
Archivo que el modelo puede exportar de muchas maneras diferentes. Después de clonar YOLOv5 e ingresar al directorio YOLOv5 desde la línea de comando, puede exportar el modelo con el siguiente comando:
$ cd yolov5
$ pip install -r requirements.txt tensorflow-cpu
$ python export.py --weights yolov5l.pt --include saved_model --nms
Este comando crea un nuevo directorio llamado yolov5l_saved_model
dentro de yolov5
Directorio. Dentro de yolov5l_saved_model
directorio, deberíamos ver los siguientes elementos:
para crear uno model.tar.gz
archivo, mueva el contenido de yolov5l_saved_model
a export/Servo/1
. Desde la línea de comandos podemos comprimir el export
directorio ejecutando el siguiente comando y cargando el modelo en el depósito S3:
$ mkdir export && mkdir export/Servo
$ mv yolov5l_saved_model export/Servo/1
$ tar -czvf model.tar.gz export/
$ aws s3 cp model.tar.gz "<s3://BUCKET/PATH/model.tar.gz>"
Luego, podemos implementar un punto final de SageMaker desde un cuaderno de SageMaker ejecutando el siguiente código:
import os
import tensorflow as tf
from tensorflow.keras import backend
from sagemaker.tensorflow import TensorFlowModel
model_data="<s3://BUCKET/PATH/model.tar.gz>"
role="<IAM ROLE>"
model = TensorFlowModel(model_data=model_data,
framework_version='2.8', role=role)
INSTANCE_TYPE = 'ml.m5.xlarge'
ENDPOINT_NAME = 'yolov5l-demo'
predictor = model.deploy(initial_instance_count=1,
instance_type=INSTANCE_TYPE,
endpoint_name=ENDPOINT_NAME)
La secuencia de comandos anterior tarda entre 2 y 3 minutos en implementar completamente el modelo en el extremo de SageMaker. Puede monitorear el estado de la implementación en SageMaker Console. Una vez que el modelo se ha alojado correctamente, el modelo está listo para la inferencia.
Probar el punto final de SageMaker
Después de que el modelo se haya alojado correctamente en un punto final de SageMaker, podemos probarlo, lo que hacemos con una imagen en blanco. El código de prueba es el siguiente:
import numpy as np
ENDPOINT_NAME = 'yolov5l-demo'
modelHeight, modelWidth = 640, 640
blank_image = np.zeros((modelHeight,modelWidth,3), np.uint8)
data = np.array(resized_image.astype(np.float32)/255.)
payload = json.dumps([data.tolist()])
response = runtime.invoke_endpoint(EndpointName=ENDPOINT_NAME,
ContentType="application/json",
Body=payload)
result = json.loads(response['Body'].read().decode())
print('Results: ', result)
Configurar Lambda con capas y disparadores
Usamos OpenCV para demostrar el modelo pasando una imagen y obteniendo los resultados de la inferencia. Lambda no viene con bibliotecas externas preconstruidas como OpenCV, por lo que debemos compilarlo antes de poder invocar el código de Lambda. Además, queremos asegurarnos de no crear bibliotecas externas como OpenCV cada vez que se llama a Lambda. Para este propósito, Lambda proporciona una funcionalidad para crear capas de Lambda. Podemos definir qué va en estas capas y se pueden usar en cada llamada desde el código Lambda. También mostramos cómo crear las capas Lambda para OpenCV. Para esta publicación, utilizaremos una instancia de Amazon Elastic Compute Cloud (Amazon EC2) para crear los niveles.
Ahora que tenemos las capas configuradas, vamos a crear el app.py
script, que es el código Lambda que usa las capas, realiza la inferencia y recupera los resultados. El siguiente diagrama ilustra este flujo de trabajo.
Crear capas Lambda para OpenCV con Docker
Para construir la imagen de Docker con Python 3.7, use Dockerfile de la siguiente manera:
FROM amazonlinux
RUN yum update -y
RUN yum install gcc openssl-devel bzip2-devel libffi-devel wget tar gzip zip make -y
# Install Python 3.7
WORKDIR /
RUN wget https://www.python.org/ftp/python/3.7.12/Python-3.7.12.tgz
RUN tar -xzvf Python-3.7.12.tgz
WORKDIR /Python-3.7.12
RUN ./configure --enable-optimizations
RUN make altinstall
# Install Python packages
RUN mkdir /packages
RUN echo "opencv-python" >> /packages/requirements.txt
RUN mkdir -p /packages/opencv-python-3.7/python/lib/python3.7/site-packages
RUN pip3.7 install -r /packages/requirements.txt -t /packages/opencv-python-3.7/python/lib/python3.7/site-packages
# Create zip files for Lambda Layer deployment
WORKDIR /packages/opencv-python-3.7/
RUN zip -r9 /packages/cv2-python37.zip .
WORKDIR /packages/
RUN rm -rf /packages/opencv-python-3.7/
Cree y ejecute Docker y guarde el archivo zip de salida en el directorio actual como layers
:
$ docker build --tag aws-lambda-layers:latest <PATH/TO/Dockerfile>
$ docker run -rm -it -v $(pwd):/layers aws-lambda-layers cp /packages/cv2-python37.zip /layers
Ahora podemos cargar los artefactos de la capa OpenCV en Amazon S3 y crear la capa Lambda:
$ aws s3 cp layers/cv2-python37.zip s3://<BUCKET>/<PATH/TO/STORE/ARTIFACTS>
$ aws lambda publish-layer-version --layer-name cv2 --description "Open CV" --content S3Bucket=<BUCKET>,S3Key=<PATH/TO/STORE/ARTIFACTS>/cv2-python37.zip --compatible-runtimes python3.7
Una vez que los comandos anteriores se hayan ejecutado correctamente, tendrá una capa de OpenCV en Lambda que podrá inspeccionar en la consola de Lambda.
Crear la función Lambda
Nosotros los usamos app.py
Script para crear la función Lambda y usar OpenCV. En el siguiente código, cambie los valores para BUCKET_NAME
y IMAGE_LOCATION
a la ubicación para acceder a la imagen:
import os, logging, json, time, urllib.parse
import boto3, botocore
import numpy as np, cv2
logger = logging.getLogger()
logger.setLevel(logging.INFO)
client = boto3.client('lambda')
# S3 BUCKETS DETAILS
s3 = boto3.resource('s3')
BUCKET_NAME = "<NAME OF S3 BUCKET FOR INPUT IMAGE>"
IMAGE_LOCATION = "<S3 PATH TO IMAGE>/image.png"
# INFERENCE ENDPOINT DETAILS
ENDPOINT_NAME = 'yolov5l-demo'
config = botocore.config.Config(read_timeout=80)
runtime = boto3.client('runtime.sagemaker', config=config)
modelHeight, modelWidth = 640, 640
# RUNNING LAMBDA
def lambda_handler(event, context):
key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
# INPUTS - Download Image file from S3 to Lambda /tmp/
input_imagename = key.split('/')[-1]
logger.info(f'Input Imagename: {input_imagename}')
s3.Bucket(BUCKET_NAME).download_file(IMAGE_LOCATION + '/' + input_imagename, '/tmp/' + input_imagename)
# INFERENCE - Invoke the SageMaker Inference Endpoint
logger.info(f'Starting Inference ... ')
orig_image = cv2.imread('/tmp/' + input_imagename)
if orig_image is not None:
start_time_iter = time.time()
# pre-processing input image
image = cv2.resize(orig_image.copy(), (modelWidth, modelHeight), interpolation = cv2.INTER_AREA)
data = np.array(image.astype(np.float32)/255.)
payload = json.dumps([data.tolist()])
# run inference
response = runtime.invoke_endpoint(EndpointName=ENDPOINT_NAME, ContentType="application/json", Body=payload)
# get the output results
result = json.loads(response['Body'].read().decode())
end_time_iter = time.time()
# get the total time taken for inference
inference_time = round((end_time_iter - start_time_iter)*100)/100
logger.info(f'Inference Completed ... ')
# OUTPUTS - Using the output to utilize in other services downstream
return {
"statusCode": 200,
"body": json.dumps({
"message": "Inference Time:// " + str(inference_time) + " seconds.",
"results": result
}),
}
Implemente la función Lambda con el siguiente código:
$ zip app.zip app.py
$ aws s3 cp app.zip s3://<BUCKET>/<PATH/TO/STORE/FUNCTION>
$ aws lambda create-function --function-name yolov5-lambda --handler app.lambda_handler --region us-east-1 --runtime python3.7 --environment "Variables={BUCKET_NAME=$BUCKET_NAME,S3_KEY=$S3_KEY}" --code S3Bucket=<BUCKET>,S3Key="<PATH/TO/STORE/FUNCTION/app.zip>"
Adjunte la capa OpenCV a la función Lambda
Ahora que tenemos la función Lambda y la capa configuradas, podemos conectar la capa a la función de la siguiente manera:
$ aws lambda update-function-configuration --function-name yolov5-lambda --layers cv2
Podemos verificar la configuración de la capa a través de la consola Lambda.
Activar Lambda cuando se carga una imagen en Amazon S3
Utilizamos una imagen cargada en Amazon S3 como disparador para ejecutar la función Lambda. Para obtener instrucciones, consulte Tutorial: Uso de un disparador de Amazon S3 para invocar una función de Lambda.
Debería ver los siguientes detalles de la función en la consola de Lambda.
realizar inferencia
Una vez que haya configurado Lambda y el extremo de SageMaker, puede probar el resultado invocando la función de Lambda. Utilizamos una carga de imagen en Amazon S3 como disparador para invocar a Lambda, que a su vez invoca el punto final de inferencia. Como ejemplo, subamos la siguiente imagen a la ubicación de Amazon S3 <S3 PATH TO IMAGE>/test_image.png
configurado en el apartado anterior.
Después de cargar la imagen, se activa la función Lambda para descargar y leer los datos de la imagen y enviarlos al extremo de SageMaker para la inferencia. El resultado de salida del punto final de SageMaker es obtenido y devuelto por la función en formato JSON, que podemos usar de diferentes maneras. La siguiente imagen muestra una salida de muestra superpuesta a la imagen.
Limpiar
Según el tipo de instancia, las notebooks de SageMaker pueden requerir una potencia de procesamiento y un costo significativos. Para evitar cargos innecesarios, recomendamos detener la instancia del portátil cuando no esté en uso. Además, las funciones de Lambda y los extremos de SageMaker solo se cobran cuando se invocan. Por lo tanto, no se requiere limpieza para estos servicios. Sin embargo, si ya no se usa un punto final, es una buena idea eliminar el punto final y el modelo.
Conclusión
En esta publicación, mostramos cómo alojar un modelo YOLOv5 previamente entrenado en un punto final de SageMaker y usar Lambda para invocar la inferencia y procesar la salida. El código detallado está disponible en GitHub.
Para obtener más información sobre los puntos de enlace de SageMaker, consulte Creación de su punto de enlace e implementación de su modelo y Creación, prueba e implementación de sus modelos de inferencia de Amazon SageMaker en AWS Lambda, que destaca cómo puede automatizar el proceso de implementación de modelos YOLOv5.
Sobre los autores
canción de kevin es un científico de datos de IoT Edge en AWS Professional Services. Kevin tiene un doctorado en Biofísica de la Universidad de Chicago. Tiene más de 4 años de experiencia en la industria de visión artificial y aprendizaje automático. Está involucrado en ayudar a los clientes en las industrias de deportes y ciencias de la vida a implementar modelos de aprendizaje automático.
Romil Shah es un científico de datos de IoT Edge en AWS Professional Services. Romil tiene más de 6 años de experiencia en la industria de visión por computadora, aprendizaje automático y dispositivos IoT edge. Está involucrado en ayudar a los clientes a optimizar e implementar sus modelos de aprendizaje automático en dispositivos de borde para la configuración industrial.