Capítulo 4: Aprendizaje profundo con PyTorch
4.5 Implementación de modelos PyTorch con TorchServe
Después de entrenar un modelo en PyTorch, el siguiente paso crucial es implementarlo en un entorno de producción donde pueda procesar nuevos datos y generar predicciones. TorchServe, una colaboración entre AWS y Facebook, ofrece una solución robusta y adaptable para servir modelos de PyTorch. Esta poderosa herramienta permite la implementación fluida de modelos entrenados como API REST, facilita la gestión simultánea de varios modelos y proporciona capacidades de escalado horizontal para manejar escenarios de alto tráfico.
TorchServe cuenta con una gama de características diseñadas para satisfacer las demandas de implementaciones a nivel de producción:
- Servicio multi-modelo: Gestiona y sirve eficientemente múltiples modelos dentro de una única instancia, optimizando el uso de recursos.
- Registro y monitoreo exhaustivos: Aprovecha las funcionalidades integradas de métricas y registro para un seguimiento detallado del rendimiento y análisis.
- Inferencia avanzada por lotes: Mejora el rendimiento agrupando inteligentemente las solicitudes entrantes en lotes, maximizando el rendimiento y la eficiencia.
- Integración fluida con GPU: Aprovecha la potencia de las GPUs para acelerar drásticamente los procesos de inferencia, permitiendo tiempos de respuesta más rápidos.
- Gestión dinámica de modelos: Actualiza, versiona y retrocede fácilmente los modelos sin interrupción del servicio, asegurando una mejora continua y flexibilidad.
Esta sección proporcionará una guía completa para implementar un modelo utilizando TorchServe. Cubriremos todo el proceso, desde preparar el modelo en un formato compatible con TorchServe hasta configurar y lanzar el servidor de modelos. Además, exploraremos las mejores prácticas para optimizar la implementación y aprovechar las características avanzadas de TorchServe para garantizar un servicio robusto y escalable en entornos de producción.
4.5.1 Preparación del modelo para TorchServe
Antes de implementar un modelo PyTorch con TorchServe, es crucial preparar el modelo en un formato que TorchServe pueda interpretar y utilizar de manera efectiva. Este proceso de preparación implica varios pasos clave:
1. Serialización del modelo
El primer paso para preparar un modelo PyTorch para su implementación con TorchServe es serializar el modelo entrenado. La serialización es el proceso de convertir una estructura de datos compleja o el estado de un objeto en un formato que se pueda almacenar o transmitir y reconstruir más tarde. En el contexto de los modelos de PyTorch, esto implica principalmente guardar el diccionario de estado del modelo.
El diccionario de estado, al que se accede a través de model.state_dict()
, es un diccionario de Python que asigna cada capa a sus tensores de parámetros. Contiene todos los parámetros entrenables (pesos y sesgos) del modelo. PyTorch proporciona una función conveniente, torch.save()
, para serializar este diccionario de estado.
Aquí tienes un proceso típico para la serialización de modelos:
- Entrena tu modelo PyTorch al nivel de rendimiento deseado.
- Accede al diccionario de estado del modelo utilizando
model.state_dict()
. - Usa
torch.save(model.state_dict(), 'model.pth')
para guardar el diccionario de estado en un archivo. La extensión '.pth' se usa comúnmente para archivos de modelos PyTorch, aunque no es obligatoria.
Este paso de serialización es crucial porque te permite:
- Conservar los parámetros del modelo entrenado para uso futuro.
- Compartir el modelo con otros sin necesidad de compartir todo el proceso de entrenamiento.
- Implementar el modelo en entornos de producción, como con TorchServe.
- Reanudar el entrenamiento desde un estado previamente guardado.
Es importante tener en cuenta que torch.save()
utiliza el módulo pickle de Python para serializar el objeto, por lo que debes tener precaución al cargar modelos desde fuentes no confiables. Además, aunque puedes guardar todo el objeto del modelo, generalmente se recomienda guardar solo el diccionario de estado para una mejor portabilidad y flexibilidad.
2. Creación de un archivo de modelo
TorchServe requiere que los modelos se empaqueten en un archivo de Model Archive (.mar
). Este archivo es un paquete integral que encapsula todos los componentes necesarios para implementar y servir un modelo de aprendizaje automático. El formato .mar
está específicamente diseñado para trabajar perfectamente con TorchServe, asegurando que todos los elementos requeridos estén empaquetados juntos para un servicio eficiente del modelo. Este archivo incluye:
- Los pesos y la arquitectura del modelo: Este es el núcleo del archivo, que contiene los parámetros entrenados (pesos) y la estructura (arquitectura) de la red neuronal. Estos normalmente se guardan como un diccionario de estado de PyTorch (
.pth
) o un archivo de modelo serializado. - Cualquier archivo de configuración necesario: Estos pueden incluir archivos JSON o YAML que especifiquen configuraciones específicas del modelo, hiperparámetros u otros detalles de configuración necesarios para la inicialización y ejecución del modelo.
- Código personalizado para preprocesamiento, posprocesamiento o manejo de requisitos específicos del modelo: Esto a menudo incluye un script de controlador personalizado (generalmente un archivo Python) que define cómo deben preprocesarse los datos de entrada antes de ser enviados al modelo, cómo debe posprocesarse la salida del modelo y cualquier otra lógica específica del modelo requerida para la inferencia.
- Recursos adicionales como mapeos de etiquetas o tokenizadores: Estos son archivos complementarios que ayudan a interpretar la entrada o salida del modelo. Por ejemplo, un archivo de mapeo de etiquetas podría asociar predicciones numéricas de clases con etiquetas legibles por humanos, mientras que un tokenizador podría ser necesario para procesar entradas de texto en modelos de procesamiento de lenguaje natural.
El archivo de modelo sirve como una unidad autónoma que incluye todo lo que TorchServe necesita para implementar y ejecutar el modelo. Este enfoque de empaquetado garantiza portabilidad, lo que facilita la transferencia de modelos entre diferentes entornos o su implementación en varios sistemas sin preocuparse por dependencias faltantes o problemas de configuración.
3. Controlador del modelo
Crear una clase de controlador personalizado es un paso crucial para definir cómo TorchServe interactúa con tu modelo. Este controlador actúa como una interfaz entre TorchServe y tu modelo PyTorch, proporcionando métodos para:
- Preprocesar datos de entrada: Este método transforma los datos de entrada en bruto en un formato adecuado para tu modelo. Por ejemplo, podría redimensionar imágenes, tokenizar textos o normalizar valores numéricos.
- Ejecutar la inferencia: Este método pasa los datos preprocesados a través de tu modelo para generar predicciones.
- Posprocesar los resultados: Este método toma la salida en bruto del modelo y la formatea en una respuesta fácil de usar. Podría implicar decodificar predicciones, aplicar umbrales o formatear la salida como JSON.
El controlador también suele incluir métodos para la inicialización y carga del modelo. Al personalizar estos métodos, puedes asegurarte de que tu modelo se integre perfectamente con TorchServe, maneje correctamente varios tipos de entrada y proporcione salidas significativas a los usuarios o aplicaciones que consumen las predicciones de tu modelo.
4. Versionado
El archivo .mar
admite el control de versiones, una característica crucial para gestionar diferentes iteraciones de tu modelo. Esta capacidad te permite:
- Mantener varias versiones del mismo modelo de manera simultánea, cada una optimizada potencialmente para diferentes casos de uso o métricas de rendimiento.
- Implementar pruebas A/B al desplegar diferentes versiones de un modelo y comparar su rendimiento en escenarios del mundo real.
- Facilitar despliegues graduales de actualizaciones del modelo, permitiendo reemplazar incrementalmente una versión anterior con una más reciente mientras monitoreas posibles comportamientos inesperados o caídas de rendimiento.
- Revertir fácilmente a una versión anterior si surgen problemas con una nueva implementación, asegurando una mínima interrupción del servicio.
- Rastrear la evolución de tu modelo a lo largo del tiempo, proporcionando valiosos conocimientos sobre el proceso de desarrollo y ayudando con la gobernanza y los requisitos de cumplimiento del modelo.
Al aprovechar esta función de versionado, puedes asegurar una estrategia de implementación más robusta y flexible, permitiendo una mejora continua de tus modelos mientras mantienes la estabilidad y confiabilidad de tus servicios de aprendizaje automático.
Al preparar meticulosamente tu modelo en este formato compatible con TorchServe, aseguras una implementación fluida y un rendimiento óptimo en entornos de producción. Esta etapa de preparación es fundamental para aprovechar las capacidades de TorchServe al servir modelos PyTorch de manera eficiente y a gran escala.
Paso 1: Exportar el modelo
Para utilizar TorchServe de manera efectiva, hay dos pasos cruciales que debes seguir al preparar tu modelo:
- Guarda los pesos del modelo: Esto se hace utilizando la función
torch.save()
de PyTorch. Esta función serializa los parámetros del modelo (pesos y sesgos) en un archivo, normalmente con una extensión .pth. Este paso es esencial ya que captura el conocimiento aprendido de tu modelo entrenado. - Asegura una serialización adecuada: No basta con solo guardar los pesos; necesitas asegurarte de que el modelo esté serializado de una manera que TorchServe pueda entender y cargar. Esto a menudo implica guardar no solo el diccionario de estado del modelo, sino también cualquier capa personalizada, pasos de preprocesamiento u otra información específica del modelo que TorchServe necesitará para instanciar y usar correctamente tu modelo.
Siguiendo cuidadosamente estos pasos, aseguras que tu modelo pueda ser cargado y servido de manera eficiente por TorchServe, lo que permite una implementación fluida y una inferencia en entornos de producción.
Ejemplo: Exportando un modelo preentrenado
import torch
import torchvision.models as models
from torchvision import transforms
from PIL import Image
# Load a pretrained ResNet-18 model
model = models.resnet18(pretrained=True)
# Set the model to evaluation mode
model.eval()
# Save the model's state_dict (required by TorchServe)
torch.save(model.state_dict(), 'resnet18.pth')
# Define a function to preprocess the input image
def preprocess_image(image_path):
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
image = Image.open(image_path)
return transform(image).unsqueeze(0)
# Load and preprocess a sample image
sample_image = preprocess_image('sample_image.jpg')
# Perform inference
with torch.no_grad():
output = model(sample_image)
# Get the predicted class index
_, predicted_idx = torch.max(output, 1)
predicted_label = predicted_idx.item()
print(f"Predicted class index: {predicted_label}")
# Load ImageNet class labels from a file
imagenet_classes = []
with open("imagenet_classes.txt") as f:
imagenet_classes = [line.strip() for line in f.readlines()]
# Ensure the class index is within range
if predicted_label < len(imagenet_classes):
print(f"Predicted class: {imagenet_classes[predicted_label]}")
else:
print("Predicted class index is out of range.")
Este ejemplo de código demuestra un flujo de trabajo completo para usar un modelo ResNet-18 preentrenado, guardarlo y realizar inferencias con las etiquetas de clase correctas de ImageNet.
Desglose del código:
- Importación de bibliotecas necesarias:
torch
: La biblioteca principal de PyTorch.torchvision.models
: Proporciona modelos preentrenados.torchvision.transforms
: Para preprocesamiento de imágenes.PIL
: Para cargar y manipular imágenes.
- Carga del modelo preentrenado:
- Usamos
models.resnet18(pretrained=True)
para cargar un modelo ResNet-18 con pesos preentrenados entrenado en ImageNet.
- Usamos
- Configuración del modelo en modo evaluación:
model.eval()
asegura que el modelo esté en modo de inferencia, desactivando dropout y actualizaciones de normalización por lotes para predicciones más estables.
- Guardado del diccionario de estado del modelo:
torch.save(model.state_dict(), 'resnet18.pth')
guarda solo los parámetros del modelo, que es la forma recomendada de guardar un modelo PyTorch para implementación.
- Definición de una función de preprocesamiento:
preprocess_image(image_path)
aplica el preprocesamiento estándar de ImageNet:- Redimensionar a
256x256
- Recorte central a
224x224
- Conversión a tensor
- Normalización usando los valores de media y desviación estándar de ImageNet
- Redimensionar a
- Carga y preprocesamiento de una imagen de ejemplo:
- Llamamos a
preprocess_image('sample_image.jpg')
para transformar una imagen en un formato compatible con el modelo.
- Llamamos a
- Realización de inferencia:
- El bloque
with torch.no_grad():
asegura que no se calculen gradientes, reduciendo el uso de memoria y acelerando la inferencia.
- El bloque
- Interpretación de la salida:
- Usamos
torch.max(output, 1)
para obtener el índice de clase con la probabilidad más alta.
- Usamos
- Carga y mapeo de etiquetas de clase:
- El modelo predice un índice de clase de ImageNet (0-999), por lo que cargamos las etiquetas correctas de ImageNet desde
imagenet_classes.txt
. - Nos aseguramos de que el índice predicho esté dentro del rango antes de imprimir la etiqueta.
- El modelo predice un índice de clase de ImageNet (0-999), por lo que cargamos las etiquetas correctas de ImageNet desde
- Impresión de resultados:
- Se imprimen el índice de clase y el nombre de clase legible para una mejor interpretación.
Este ejemplo asegura un flujo de trabajo robusto para usar un modelo preentrenado, guardarlo para implementación y realizar inferencias con etiquetas correctas, que son elementos esenciales para aplicaciones de aprendizaje profundo en el mundo real.
4.5.2 Escribir un controlador de modelo personalizado (Opcional)
TorchServe utiliza controladores de modelo como un componente crucial en su arquitectura. Estos controladores sirven como un puente entre el marco de TorchServe y tu modelo específico de PyTorch, definiendo dos aspectos clave de la implementación del modelo:
- Carga del modelo: Los controladores especifican cómo debe inicializarse y cargarse tu modelo en memoria. Esto incluye tareas como:
- Cargar la arquitectura del modelo y los pesos desde archivos guardados.
- Configurar el modelo en modo de evaluación para la inferencia.
- Mover el modelo al dispositivo adecuado (CPU o GPU).
- Manejo de solicitudes de inferencia: Los controladores dictan cómo TorchServe debe procesar las solicitudes de inferencia entrantes, lo que generalmente implica:
- Preprocesar los datos de entrada para que coincidan con el formato esperado del modelo.
- Pasar los datos preprocesados a través del modelo.
- Posprocesar la salida del modelo para generar la respuesta final.
Si bien TorchServe proporciona controladores predeterminados para escenarios comunes, es posible que necesites crear un controlador personalizado si tu modelo requiere pasos específicos de preprocesamiento o posprocesamiento. Por ejemplo:
- Preprocesamiento de imágenes personalizado para modelos de visión por computadora.
- Tokenización de texto para modelos de procesamiento de lenguaje natural.
- Formateo especializado de la salida para las necesidades de tu aplicación.
Al implementar un controlador personalizado, aseguras que tu modelo se integre sin problemas con TorchServe, permitiendo una inferencia eficiente y precisa en entornos de producción.
Ejemplo: Escribir un controlador personalizado (Opcional)
import torch
import torchvision.models as models
from torchvision import transforms
from PIL import Image
import json
import logging
class ResNetHandler:
def __init__(self):
self.model = None
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
self.class_to_idx = None
self.logger = logging.getLogger(__name__)
def initialize(self, context):
"""
Initialize the handler at startup.
:param context: Initial context containing model server system properties.
"""
self.manifest = context.manifest
properties = context.system_properties
model_dir = properties.get("model_dir")
self.logger.info(f"Model directory: {model_dir}")
# Load the model architecture
self.model = models.resnet18(pretrained=False)
self.model.fc = torch.nn.Linear(self.model.fc.in_features, 1000) # Adjust if needed
# Load the model's state_dict
state_dict_path = f"{model_dir}/resnet18.pth"
self.logger.info(f"Loading model from {state_dict_path}")
self.model.load_state_dict(torch.load(state_dict_path, map_location=self.device))
self.model.eval()
self.model.to(self.device)
# Load class mapping
class_mapping_path = f"{model_dir}/class_mapping.json"
try:
with open(class_mapping_path, 'r') as f:
self.class_to_idx = json.load(f)
self.logger.info("Class mapping loaded successfully")
except FileNotFoundError:
self.logger.warning(f"Class mapping file not found at {class_mapping_path}")
self.logger.info("Model initialized successfully")
def preprocess(self, data):
"""
Preprocess the input data before inference.
:param data: Input data to be preprocessed.
:return: Preprocessed data for model input.
"""
self.logger.info("Preprocessing input data")
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
images = []
for row in data:
image = row.get("data") or row.get("body")
if isinstance(image, (bytes, bytearray)):
image = Image.open(io.BytesIO(image))
elif isinstance(image, str):
image = Image.open(image)
else:
raise ValueError(f"Unsupported image format: {type(image)}")
images.append(transform(image))
return torch.stack(images).to(self.device)
def inference(self, data):
"""
Perform inference on the preprocessed data.
:param data: Preprocessed data for model input.
:return: Raw model output.
"""
self.logger.info("Performing inference")
with torch.no_grad():
output = self.model(data)
return output
def postprocess(self, inference_output):
"""
Postprocess the model output.
:param inference_output: Raw model output.
:return: Processed output.
"""
self.logger.info("Postprocessing inference output")
probabilities = torch.nn.functional.softmax(inference_output, dim=1)
top_prob, top_class = torch.topk(probabilities, 5)
result = []
for i in range(top_prob.shape[0]):
item_result = []
for j in range(5):
class_idx = top_class[i][j].item()
if self.class_to_idx:
class_name = self.class_to_idx.get(str(class_idx), f"Unknown class {class_idx}")
else:
class_name = f"Class {class_idx}"
item_result.append({
"class": class_name,
"probability": top_prob[i][j].item()
})
result.append(item_result)
return json.dumps(result)
def handle(self, data, context):
"""
Handle a request to the model.
:param data: Input data for inference.
:param context: Context object containing request details.
:return: Processed output.
"""
self.logger.info("Handling inference request")
preprocessed_data = self.preprocess(data)
inference_output = self.inference(preprocessed_data)
return self.postprocess(inference_output)
Este ejemplo de código proporciona una implementación completa de un controlador personalizado para TorchServe.
Aquí tienes un desglose detallado de los cambios y adiciones:
- Importaciones:
Se añadieron las importaciones necesarias, incluyendo
logging
para mejorar la depuración y el seguimiento de errores. - Inicialización:
- Se agregó la configuración de registro (
logging
). - Se incluyó el manejo de errores para la carga del modelo y el mapeo de clases.
- Se hizo la inicialización más robusta utilizando el objeto de contexto proporcionado por TorchServe.
- Se agregó la configuración de registro (
- Preprocesamiento:
- Mejorado para manejar múltiples formatos de entrada (bytes, rutas de archivo).
- Se añadió soporte para el procesamiento por lotes.
- Inferencia:
- Se mantuvo simple y enfocado en ejecutar el modelo.
- Posprocesamiento:
- Mejorado para devolver las 5 mejores predicciones con probabilidades.
- Se agregó soporte para el mapeo de nombres de clases, si está disponible.
- Método Handle:
- Se añadió un método principal
handle
que TorchServe llama, el cual orquesta los pasos de preprocesamiento, inferencia y posprocesamiento.
- Se añadió un método principal
- Manejo de errores y registro:
- Incorporado en todo el código para facilitar la depuración y mejorar la robustez.
- Flexibilidad:
- Ahora el controlador es más flexible, capaz de trabajar con o sin un archivo de mapeo de clases.
Esta implementación proporciona un controlador más preparado para la producción que puede manejar varios escenarios y casos límite, haciéndolo más adecuado para la implementación en el mundo real con TorchServe.
4.5.3 Creación del archivo de modelo (.mar)
El archivo de modelo, denotado por la extensión .mar
, es un componente crucial en el proceso de implementación de TorchServe. Este archivo actúa como un paquete integral que encapsula todos los elementos esenciales necesarios para servir un modelo, incluyendo:
- Pesos del modelo: Los parámetros entrenados de tu red neuronal.
- Controlador del modelo: Un script en Python que define cómo cargar el modelo y procesar las solicitudes.
- Configuración del modelo: Cualquier archivo o metadato adicional necesario para la operación del modelo.
TorchServe utiliza este archivo como un punto de referencia único al cargar y ejecutar el modelo, lo que simplifica el proceso de implementación y asegura que todos los componentes necesarios estén empaquetados juntos.
Paso 2: Crear el archivo de modelo utilizando torch-model-archiver
Para facilitar la creación de estos archivos de modelo, TorchServe proporciona una herramienta de línea de comandos llamada torch-model-archiver
. Esta utilidad simplifica el proceso de empaquetar tus modelos PyTorch y los archivos asociados en el formato requerido .mar
.
La herramienta torch-model-archiver
requiere dos entradas principales:
- state_dict del modelo: Esta es la forma serializada de los parámetros de tu modelo, normalmente guardada como un archivo
.pth
o.pt
. - Archivo de controlador: Un script en Python que define cómo TorchServe debe interactuar con tu modelo, incluyendo métodos para preprocesar entradas, ejecutar inferencia y posprocesar salidas.
Además, puedes incluir otros archivos necesarios como etiquetas de clase, archivos de configuración o cualquier otro recurso requerido para la operación de tu modelo.
Al usar torch-model-archiver
, te aseguras de que todos los componentes estén empaquetados correctamente y listos para la implementación con TorchServe, promoviendo consistencia y facilidad de uso en diferentes entornos.
Comando para crear el archivo .mar
:
# Archive the ResNet18 model for TorchServe
torch-model-archiver \
--model-name resnet18 \ # Model name
--version 1.0 \ # Version number
--model-file model.py \ # Path to model definition (if needed)
--serialized-file resnet18.pth \ # Path to saved weights
--handler handler.py \ # Path to custom handler (if any)
--export-path model_store \ # Output directory
--extra-files index_to_name.json # Additional files like class labels
4.5.4 Iniciar el servidor de modelos TorchServe
Una vez que el archivo de modelo se ha creado, puedes iniciar TorchServe para desplegar el modelo. Este proceso implica inicializar el servidor de TorchServe, que actúa como un entorno de ejecución para tus modelos PyTorch. TorchServe carga el archivo de modelo (.mar) que has creado, configura los puntos de acceso necesarios para la inferencia y gestiona el ciclo de vida del modelo.
Cuando inicias TorchServe, realiza varias acciones clave:
- Carga el modelo desde el archivo .mar en la memoria.
- Inicializa cualquier controlador personalizado que hayas definido.
- Configura puntos de acceso API REST para la gestión del modelo y la inferencia.
- Prepara el modelo para su servicio, asegurándose de que esté listo para manejar solicitudes entrantes.
Este paso de implementación es crucial, ya que convierte tu modelo de un archivo estático a un servicio activo y accesible, capaz de procesar solicitudes de inferencia en tiempo real. Una vez que TorchServe está en funcionamiento con tu modelo, está listo para aceptar y responder a solicitudes de predicciones, llevando efectivamente tu modelo de machine learning a un estado listo para producción.
Paso 3: Iniciar TorchServe
torchserve --start --model-store model_store --models resnet18=resnet18.mar
Aquí tienes un desglose del comando:
torchserve
: Este es el comando principal para ejecutar TorchServe.-start
: Esta bandera indica a TorchServe que inicie el servidor.-model-store model_store
: Esto especifica el directorio donde se almacenan tus archivos de modelo (.mar). En este caso, es un directorio llamado "model_store".-models resnet18=resnet18.mar
: Esto le indica a TorchServe qué modelos cargar. Aquí, está cargando un modelo ResNet-18 desde un archivo llamado "resnet18.mar".
Cuando ejecutas este comando, TorchServe se iniciará, cargará el modelo ResNet-18 especificado desde el archivo .mar en el almacén de modelos y lo pondrá disponible para servir predicciones a través de una API.
4.5.5 Realizar predicciones a través de la API
Una vez que el modelo se ha desplegado, puedes enviar solicitudes de inferencia a la API para obtener predicciones en tiempo real. Este paso es crucial, ya que te permite utilizar tu modelo entrenado en aplicaciones prácticas. A continuación se explica este proceso en más detalle:
- Punto de acceso API: TorchServe crea un punto de acceso API REST para tu modelo. Este punto de acceso generalmente está disponible en una URL como http://localhost:8080/predictions/[model_name].
- Formato de solicitud: Puedes enviar solicitudes HTTP POST a este punto de acceso. El cuerpo de la solicitud generalmente contiene los datos de entrada (por ejemplo, un archivo de imagen para tareas de clasificación de imágenes) sobre los que deseas realizar predicciones.
- Procesamiento en tiempo real: Cuando envías una solicitud, TorchServe la procesa en tiempo real. Utiliza el modelo desplegado para generar predicciones basadas en los datos de entrada.
- Respuesta: La API devuelve una respuesta que contiene las predicciones del modelo. Esto podría ser probabilidades de clases para una tarea de clasificación, cuadros delimitadores para una tarea de detección de objetos, o cualquier otra salida relevante para el propósito de tu modelo.
- Integración: Este enfoque basado en API permite una fácil integración de tu modelo en varias aplicaciones, sitios web o servicios, lo que te permite aprovechar tu modelo de IA en escenarios del mundo real.
Al utilizar esta API, puedes incorporar sin problemas las capacidades de tu modelo PyTorch en tu ecosistema de software más amplio, convirtiéndolo en una herramienta poderosa para implementar funciones y características impulsadas por IA.
Paso 4: Enviar una solicitud de predicción a la API de TorchServe
import requests
import json
from PIL import Image
import io
def predict_image(image_path, model_name, server_url):
"""
Send an image to TorchServe for prediction.
Args:
image_path (str): Path to the image file
model_name (str): Name of the model to use for prediction
server_url (str): Base URL of the TorchServe server
Returns:
dict: Prediction results
"""
# Prepare the image file for prediction
with open(image_path, 'rb') as file:
image_data = file.read()
# Prepare the request
url = f"{server_url}/predictions/{model_name}"
files = {'data': ('image.jpg', image_data)}
try:
# Send a POST request to the model's endpoint
response = requests.post(url, files=files)
response.raise_for_status() # Raise an exception for bad status codes
# Parse and return the prediction result
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error occurred: {e}")
return None
# Example usage
if __name__ == "__main__":
image_path = 'test_image.jpg'
model_name = 'resnet18'
server_url = 'http://localhost:8080'
result = predict_image(image_path, model_name, server_url)
if result:
print("Prediction Result:")
print(json.dumps(result, indent=2))
else:
print("Failed to get prediction.")
Este ejemplo de código proporciona un enfoque integral para realizar predicciones utilizando TorchServe. A continuación, se detalla cada uno de los componentes clave:
- Definición de la función:
- Definimos una función
predict_image
que encapsula el proceso de predicción. - Esta función toma tres parámetros: la ruta al archivo de imagen, el nombre del modelo y la URL del servidor TorchServe.
- Definimos una función
- Preparación de la imagen:
- El archivo de imagen se lee como datos binarios, lo que es más eficiente que abrirlo como un objeto PIL Image.
- Preparación de la solicitud:
- Construimos la URL completa para el punto de acceso de predicción utilizando la URL del servidor y el nombre del modelo.
- Los datos de la imagen se preparan como un archivo para ser enviados en la solicitud POST.
- Manejo de errores:
- El código utiliza un bloque try-except para manejar posibles errores durante la solicitud.
- Se usa
raise_for_status()
para capturar cualquier error HTTP.
- Procesamiento de la respuesta:
- La respuesta en formato JSON del servidor se devuelve si la solicitud es exitosa.
- Ejecución principal:
- El script incluye un bloque de ejecución condicional principal.
- Demuestra cómo utilizar la función
predict_image
con parámetros de ejemplo.
- Visualización de resultados:
- Si se obtiene una predicción correctamente, se imprime en una estructura JSON formateada para mejorar la legibilidad.
- Si la predicción falla, se muestra un mensaje de error.
Este ejemplo ofrece un manejo de errores robusto, mayor flexibilidad mediante la parametrización y una estructura más clara que aísla la funcionalidad central en una función reutilizable. Está mejor adaptado para la integración en proyectos más grandes y proporciona una base sólida para el desarrollo futuro o la personalización.
4.5.6 Monitorización y gestión de modelos con TorchServe
TorchServe ofrece una suite completa de características para monitorear y gestionar tus modelos desplegados, mejorando tu capacidad para mantener y optimizar tu infraestructura de machine learning:
- Métricas: TorchServe proporciona métricas detalladas de rendimiento accesibles a través del punto de acceso
/metrics
. Estas métricas incluyen:- Latencia: Mide el tiempo que tarda tu modelo en procesar solicitudes, ayudándote a identificar y solucionar cuellos de botella en el rendimiento.
- Rendimiento: Rastrea el número de solicitudes que tu modelo puede manejar por unidad de tiempo, lo que es crucial para la planificación de la capacidad y las decisiones de escalado.
- Utilización de la GPU: Para modelos que se ejecutan en GPUs, monitorea el uso de recursos para asegurar un rendimiento óptimo.
- Tasas de solicitud: Analiza la frecuencia de las solicitudes entrantes para entender los patrones de uso y los momentos de mayor actividad.
Estas métricas permiten tomar decisiones basadas en datos para la optimización del modelo y la planificación de la infraestructura.
- Escalado: Las capacidades de escalado de TorchServe están diseñadas para manejar cargas variables en entornos de producción:
- Escalado horizontal: Despliega múltiples instancias del mismo modelo en diferentes servidores para distribuir la carga de trabajo.
- Escalado vertical: Ajusta los recursos (CPU, GPU, memoria) asignados a cada instancia del modelo según la demanda.
- Autoescalado: Implementa reglas de autoescalado predictivo o basado en reglas para ajustar dinámicamente el número de instancias del modelo en función de los patrones de tráfico.
- Balanceo de carga: Distribuye eficientemente las solicitudes entrantes entre múltiples instancias del modelo para asegurar una utilización óptima de los recursos.
Estas características de escalado permiten que tu despliegue maneje sin problemas escenarios de alto tráfico y mantenga un rendimiento consistente bajo cargas variables.
- Registros: El sistema de registro de TorchServe es una herramienta poderosa para monitorear y solucionar problemas en tus modelos desplegados:
- Registros de errores: Captura y clasifica errores que ocurren durante la inferencia del modelo, ayudando a identificar y resolver problemas rápidamente.
- Registros de solicitudes: Rastrea solicitudes individuales, incluyendo los datos de entrada y las respuestas del modelo, útiles para depuración y auditoría.
- Registros del sistema: Monitorea eventos a nivel del servidor, como la carga o descarga de modelos y cambios de configuración.
- Registro personalizado: Implementa registros personalizados dentro de tus controladores de modelo para capturar información específica de la aplicación.
- Agregación de registros: Integra con herramientas de gestión de registros para la recolección y análisis centralizados de registros en múltiples instancias.
Estos registros exhaustivos proporcionan información invaluable para mantener la salud y el rendimiento de tus modelos desplegados.
Al aprovechar estas funciones avanzadas, puedes garantizar que tu implementación de TorchServe sea robusta, escalable y fácil de gestionar en entornos de producción.
4.5 Implementación de modelos PyTorch con TorchServe
Después de entrenar un modelo en PyTorch, el siguiente paso crucial es implementarlo en un entorno de producción donde pueda procesar nuevos datos y generar predicciones. TorchServe, una colaboración entre AWS y Facebook, ofrece una solución robusta y adaptable para servir modelos de PyTorch. Esta poderosa herramienta permite la implementación fluida de modelos entrenados como API REST, facilita la gestión simultánea de varios modelos y proporciona capacidades de escalado horizontal para manejar escenarios de alto tráfico.
TorchServe cuenta con una gama de características diseñadas para satisfacer las demandas de implementaciones a nivel de producción:
- Servicio multi-modelo: Gestiona y sirve eficientemente múltiples modelos dentro de una única instancia, optimizando el uso de recursos.
- Registro y monitoreo exhaustivos: Aprovecha las funcionalidades integradas de métricas y registro para un seguimiento detallado del rendimiento y análisis.
- Inferencia avanzada por lotes: Mejora el rendimiento agrupando inteligentemente las solicitudes entrantes en lotes, maximizando el rendimiento y la eficiencia.
- Integración fluida con GPU: Aprovecha la potencia de las GPUs para acelerar drásticamente los procesos de inferencia, permitiendo tiempos de respuesta más rápidos.
- Gestión dinámica de modelos: Actualiza, versiona y retrocede fácilmente los modelos sin interrupción del servicio, asegurando una mejora continua y flexibilidad.
Esta sección proporcionará una guía completa para implementar un modelo utilizando TorchServe. Cubriremos todo el proceso, desde preparar el modelo en un formato compatible con TorchServe hasta configurar y lanzar el servidor de modelos. Además, exploraremos las mejores prácticas para optimizar la implementación y aprovechar las características avanzadas de TorchServe para garantizar un servicio robusto y escalable en entornos de producción.
4.5.1 Preparación del modelo para TorchServe
Antes de implementar un modelo PyTorch con TorchServe, es crucial preparar el modelo en un formato que TorchServe pueda interpretar y utilizar de manera efectiva. Este proceso de preparación implica varios pasos clave:
1. Serialización del modelo
El primer paso para preparar un modelo PyTorch para su implementación con TorchServe es serializar el modelo entrenado. La serialización es el proceso de convertir una estructura de datos compleja o el estado de un objeto en un formato que se pueda almacenar o transmitir y reconstruir más tarde. En el contexto de los modelos de PyTorch, esto implica principalmente guardar el diccionario de estado del modelo.
El diccionario de estado, al que se accede a través de model.state_dict()
, es un diccionario de Python que asigna cada capa a sus tensores de parámetros. Contiene todos los parámetros entrenables (pesos y sesgos) del modelo. PyTorch proporciona una función conveniente, torch.save()
, para serializar este diccionario de estado.
Aquí tienes un proceso típico para la serialización de modelos:
- Entrena tu modelo PyTorch al nivel de rendimiento deseado.
- Accede al diccionario de estado del modelo utilizando
model.state_dict()
. - Usa
torch.save(model.state_dict(), 'model.pth')
para guardar el diccionario de estado en un archivo. La extensión '.pth' se usa comúnmente para archivos de modelos PyTorch, aunque no es obligatoria.
Este paso de serialización es crucial porque te permite:
- Conservar los parámetros del modelo entrenado para uso futuro.
- Compartir el modelo con otros sin necesidad de compartir todo el proceso de entrenamiento.
- Implementar el modelo en entornos de producción, como con TorchServe.
- Reanudar el entrenamiento desde un estado previamente guardado.
Es importante tener en cuenta que torch.save()
utiliza el módulo pickle de Python para serializar el objeto, por lo que debes tener precaución al cargar modelos desde fuentes no confiables. Además, aunque puedes guardar todo el objeto del modelo, generalmente se recomienda guardar solo el diccionario de estado para una mejor portabilidad y flexibilidad.
2. Creación de un archivo de modelo
TorchServe requiere que los modelos se empaqueten en un archivo de Model Archive (.mar
). Este archivo es un paquete integral que encapsula todos los componentes necesarios para implementar y servir un modelo de aprendizaje automático. El formato .mar
está específicamente diseñado para trabajar perfectamente con TorchServe, asegurando que todos los elementos requeridos estén empaquetados juntos para un servicio eficiente del modelo. Este archivo incluye:
- Los pesos y la arquitectura del modelo: Este es el núcleo del archivo, que contiene los parámetros entrenados (pesos) y la estructura (arquitectura) de la red neuronal. Estos normalmente se guardan como un diccionario de estado de PyTorch (
.pth
) o un archivo de modelo serializado. - Cualquier archivo de configuración necesario: Estos pueden incluir archivos JSON o YAML que especifiquen configuraciones específicas del modelo, hiperparámetros u otros detalles de configuración necesarios para la inicialización y ejecución del modelo.
- Código personalizado para preprocesamiento, posprocesamiento o manejo de requisitos específicos del modelo: Esto a menudo incluye un script de controlador personalizado (generalmente un archivo Python) que define cómo deben preprocesarse los datos de entrada antes de ser enviados al modelo, cómo debe posprocesarse la salida del modelo y cualquier otra lógica específica del modelo requerida para la inferencia.
- Recursos adicionales como mapeos de etiquetas o tokenizadores: Estos son archivos complementarios que ayudan a interpretar la entrada o salida del modelo. Por ejemplo, un archivo de mapeo de etiquetas podría asociar predicciones numéricas de clases con etiquetas legibles por humanos, mientras que un tokenizador podría ser necesario para procesar entradas de texto en modelos de procesamiento de lenguaje natural.
El archivo de modelo sirve como una unidad autónoma que incluye todo lo que TorchServe necesita para implementar y ejecutar el modelo. Este enfoque de empaquetado garantiza portabilidad, lo que facilita la transferencia de modelos entre diferentes entornos o su implementación en varios sistemas sin preocuparse por dependencias faltantes o problemas de configuración.
3. Controlador del modelo
Crear una clase de controlador personalizado es un paso crucial para definir cómo TorchServe interactúa con tu modelo. Este controlador actúa como una interfaz entre TorchServe y tu modelo PyTorch, proporcionando métodos para:
- Preprocesar datos de entrada: Este método transforma los datos de entrada en bruto en un formato adecuado para tu modelo. Por ejemplo, podría redimensionar imágenes, tokenizar textos o normalizar valores numéricos.
- Ejecutar la inferencia: Este método pasa los datos preprocesados a través de tu modelo para generar predicciones.
- Posprocesar los resultados: Este método toma la salida en bruto del modelo y la formatea en una respuesta fácil de usar. Podría implicar decodificar predicciones, aplicar umbrales o formatear la salida como JSON.
El controlador también suele incluir métodos para la inicialización y carga del modelo. Al personalizar estos métodos, puedes asegurarte de que tu modelo se integre perfectamente con TorchServe, maneje correctamente varios tipos de entrada y proporcione salidas significativas a los usuarios o aplicaciones que consumen las predicciones de tu modelo.
4. Versionado
El archivo .mar
admite el control de versiones, una característica crucial para gestionar diferentes iteraciones de tu modelo. Esta capacidad te permite:
- Mantener varias versiones del mismo modelo de manera simultánea, cada una optimizada potencialmente para diferentes casos de uso o métricas de rendimiento.
- Implementar pruebas A/B al desplegar diferentes versiones de un modelo y comparar su rendimiento en escenarios del mundo real.
- Facilitar despliegues graduales de actualizaciones del modelo, permitiendo reemplazar incrementalmente una versión anterior con una más reciente mientras monitoreas posibles comportamientos inesperados o caídas de rendimiento.
- Revertir fácilmente a una versión anterior si surgen problemas con una nueva implementación, asegurando una mínima interrupción del servicio.
- Rastrear la evolución de tu modelo a lo largo del tiempo, proporcionando valiosos conocimientos sobre el proceso de desarrollo y ayudando con la gobernanza y los requisitos de cumplimiento del modelo.
Al aprovechar esta función de versionado, puedes asegurar una estrategia de implementación más robusta y flexible, permitiendo una mejora continua de tus modelos mientras mantienes la estabilidad y confiabilidad de tus servicios de aprendizaje automático.
Al preparar meticulosamente tu modelo en este formato compatible con TorchServe, aseguras una implementación fluida y un rendimiento óptimo en entornos de producción. Esta etapa de preparación es fundamental para aprovechar las capacidades de TorchServe al servir modelos PyTorch de manera eficiente y a gran escala.
Paso 1: Exportar el modelo
Para utilizar TorchServe de manera efectiva, hay dos pasos cruciales que debes seguir al preparar tu modelo:
- Guarda los pesos del modelo: Esto se hace utilizando la función
torch.save()
de PyTorch. Esta función serializa los parámetros del modelo (pesos y sesgos) en un archivo, normalmente con una extensión .pth. Este paso es esencial ya que captura el conocimiento aprendido de tu modelo entrenado. - Asegura una serialización adecuada: No basta con solo guardar los pesos; necesitas asegurarte de que el modelo esté serializado de una manera que TorchServe pueda entender y cargar. Esto a menudo implica guardar no solo el diccionario de estado del modelo, sino también cualquier capa personalizada, pasos de preprocesamiento u otra información específica del modelo que TorchServe necesitará para instanciar y usar correctamente tu modelo.
Siguiendo cuidadosamente estos pasos, aseguras que tu modelo pueda ser cargado y servido de manera eficiente por TorchServe, lo que permite una implementación fluida y una inferencia en entornos de producción.
Ejemplo: Exportando un modelo preentrenado
import torch
import torchvision.models as models
from torchvision import transforms
from PIL import Image
# Load a pretrained ResNet-18 model
model = models.resnet18(pretrained=True)
# Set the model to evaluation mode
model.eval()
# Save the model's state_dict (required by TorchServe)
torch.save(model.state_dict(), 'resnet18.pth')
# Define a function to preprocess the input image
def preprocess_image(image_path):
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
image = Image.open(image_path)
return transform(image).unsqueeze(0)
# Load and preprocess a sample image
sample_image = preprocess_image('sample_image.jpg')
# Perform inference
with torch.no_grad():
output = model(sample_image)
# Get the predicted class index
_, predicted_idx = torch.max(output, 1)
predicted_label = predicted_idx.item()
print(f"Predicted class index: {predicted_label}")
# Load ImageNet class labels from a file
imagenet_classes = []
with open("imagenet_classes.txt") as f:
imagenet_classes = [line.strip() for line in f.readlines()]
# Ensure the class index is within range
if predicted_label < len(imagenet_classes):
print(f"Predicted class: {imagenet_classes[predicted_label]}")
else:
print("Predicted class index is out of range.")
Este ejemplo de código demuestra un flujo de trabajo completo para usar un modelo ResNet-18 preentrenado, guardarlo y realizar inferencias con las etiquetas de clase correctas de ImageNet.
Desglose del código:
- Importación de bibliotecas necesarias:
torch
: La biblioteca principal de PyTorch.torchvision.models
: Proporciona modelos preentrenados.torchvision.transforms
: Para preprocesamiento de imágenes.PIL
: Para cargar y manipular imágenes.
- Carga del modelo preentrenado:
- Usamos
models.resnet18(pretrained=True)
para cargar un modelo ResNet-18 con pesos preentrenados entrenado en ImageNet.
- Usamos
- Configuración del modelo en modo evaluación:
model.eval()
asegura que el modelo esté en modo de inferencia, desactivando dropout y actualizaciones de normalización por lotes para predicciones más estables.
- Guardado del diccionario de estado del modelo:
torch.save(model.state_dict(), 'resnet18.pth')
guarda solo los parámetros del modelo, que es la forma recomendada de guardar un modelo PyTorch para implementación.
- Definición de una función de preprocesamiento:
preprocess_image(image_path)
aplica el preprocesamiento estándar de ImageNet:- Redimensionar a
256x256
- Recorte central a
224x224
- Conversión a tensor
- Normalización usando los valores de media y desviación estándar de ImageNet
- Redimensionar a
- Carga y preprocesamiento de una imagen de ejemplo:
- Llamamos a
preprocess_image('sample_image.jpg')
para transformar una imagen en un formato compatible con el modelo.
- Llamamos a
- Realización de inferencia:
- El bloque
with torch.no_grad():
asegura que no se calculen gradientes, reduciendo el uso de memoria y acelerando la inferencia.
- El bloque
- Interpretación de la salida:
- Usamos
torch.max(output, 1)
para obtener el índice de clase con la probabilidad más alta.
- Usamos
- Carga y mapeo de etiquetas de clase:
- El modelo predice un índice de clase de ImageNet (0-999), por lo que cargamos las etiquetas correctas de ImageNet desde
imagenet_classes.txt
. - Nos aseguramos de que el índice predicho esté dentro del rango antes de imprimir la etiqueta.
- El modelo predice un índice de clase de ImageNet (0-999), por lo que cargamos las etiquetas correctas de ImageNet desde
- Impresión de resultados:
- Se imprimen el índice de clase y el nombre de clase legible para una mejor interpretación.
Este ejemplo asegura un flujo de trabajo robusto para usar un modelo preentrenado, guardarlo para implementación y realizar inferencias con etiquetas correctas, que son elementos esenciales para aplicaciones de aprendizaje profundo en el mundo real.
4.5.2 Escribir un controlador de modelo personalizado (Opcional)
TorchServe utiliza controladores de modelo como un componente crucial en su arquitectura. Estos controladores sirven como un puente entre el marco de TorchServe y tu modelo específico de PyTorch, definiendo dos aspectos clave de la implementación del modelo:
- Carga del modelo: Los controladores especifican cómo debe inicializarse y cargarse tu modelo en memoria. Esto incluye tareas como:
- Cargar la arquitectura del modelo y los pesos desde archivos guardados.
- Configurar el modelo en modo de evaluación para la inferencia.
- Mover el modelo al dispositivo adecuado (CPU o GPU).
- Manejo de solicitudes de inferencia: Los controladores dictan cómo TorchServe debe procesar las solicitudes de inferencia entrantes, lo que generalmente implica:
- Preprocesar los datos de entrada para que coincidan con el formato esperado del modelo.
- Pasar los datos preprocesados a través del modelo.
- Posprocesar la salida del modelo para generar la respuesta final.
Si bien TorchServe proporciona controladores predeterminados para escenarios comunes, es posible que necesites crear un controlador personalizado si tu modelo requiere pasos específicos de preprocesamiento o posprocesamiento. Por ejemplo:
- Preprocesamiento de imágenes personalizado para modelos de visión por computadora.
- Tokenización de texto para modelos de procesamiento de lenguaje natural.
- Formateo especializado de la salida para las necesidades de tu aplicación.
Al implementar un controlador personalizado, aseguras que tu modelo se integre sin problemas con TorchServe, permitiendo una inferencia eficiente y precisa en entornos de producción.
Ejemplo: Escribir un controlador personalizado (Opcional)
import torch
import torchvision.models as models
from torchvision import transforms
from PIL import Image
import json
import logging
class ResNetHandler:
def __init__(self):
self.model = None
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
self.class_to_idx = None
self.logger = logging.getLogger(__name__)
def initialize(self, context):
"""
Initialize the handler at startup.
:param context: Initial context containing model server system properties.
"""
self.manifest = context.manifest
properties = context.system_properties
model_dir = properties.get("model_dir")
self.logger.info(f"Model directory: {model_dir}")
# Load the model architecture
self.model = models.resnet18(pretrained=False)
self.model.fc = torch.nn.Linear(self.model.fc.in_features, 1000) # Adjust if needed
# Load the model's state_dict
state_dict_path = f"{model_dir}/resnet18.pth"
self.logger.info(f"Loading model from {state_dict_path}")
self.model.load_state_dict(torch.load(state_dict_path, map_location=self.device))
self.model.eval()
self.model.to(self.device)
# Load class mapping
class_mapping_path = f"{model_dir}/class_mapping.json"
try:
with open(class_mapping_path, 'r') as f:
self.class_to_idx = json.load(f)
self.logger.info("Class mapping loaded successfully")
except FileNotFoundError:
self.logger.warning(f"Class mapping file not found at {class_mapping_path}")
self.logger.info("Model initialized successfully")
def preprocess(self, data):
"""
Preprocess the input data before inference.
:param data: Input data to be preprocessed.
:return: Preprocessed data for model input.
"""
self.logger.info("Preprocessing input data")
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
images = []
for row in data:
image = row.get("data") or row.get("body")
if isinstance(image, (bytes, bytearray)):
image = Image.open(io.BytesIO(image))
elif isinstance(image, str):
image = Image.open(image)
else:
raise ValueError(f"Unsupported image format: {type(image)}")
images.append(transform(image))
return torch.stack(images).to(self.device)
def inference(self, data):
"""
Perform inference on the preprocessed data.
:param data: Preprocessed data for model input.
:return: Raw model output.
"""
self.logger.info("Performing inference")
with torch.no_grad():
output = self.model(data)
return output
def postprocess(self, inference_output):
"""
Postprocess the model output.
:param inference_output: Raw model output.
:return: Processed output.
"""
self.logger.info("Postprocessing inference output")
probabilities = torch.nn.functional.softmax(inference_output, dim=1)
top_prob, top_class = torch.topk(probabilities, 5)
result = []
for i in range(top_prob.shape[0]):
item_result = []
for j in range(5):
class_idx = top_class[i][j].item()
if self.class_to_idx:
class_name = self.class_to_idx.get(str(class_idx), f"Unknown class {class_idx}")
else:
class_name = f"Class {class_idx}"
item_result.append({
"class": class_name,
"probability": top_prob[i][j].item()
})
result.append(item_result)
return json.dumps(result)
def handle(self, data, context):
"""
Handle a request to the model.
:param data: Input data for inference.
:param context: Context object containing request details.
:return: Processed output.
"""
self.logger.info("Handling inference request")
preprocessed_data = self.preprocess(data)
inference_output = self.inference(preprocessed_data)
return self.postprocess(inference_output)
Este ejemplo de código proporciona una implementación completa de un controlador personalizado para TorchServe.
Aquí tienes un desglose detallado de los cambios y adiciones:
- Importaciones:
Se añadieron las importaciones necesarias, incluyendo
logging
para mejorar la depuración y el seguimiento de errores. - Inicialización:
- Se agregó la configuración de registro (
logging
). - Se incluyó el manejo de errores para la carga del modelo y el mapeo de clases.
- Se hizo la inicialización más robusta utilizando el objeto de contexto proporcionado por TorchServe.
- Se agregó la configuración de registro (
- Preprocesamiento:
- Mejorado para manejar múltiples formatos de entrada (bytes, rutas de archivo).
- Se añadió soporte para el procesamiento por lotes.
- Inferencia:
- Se mantuvo simple y enfocado en ejecutar el modelo.
- Posprocesamiento:
- Mejorado para devolver las 5 mejores predicciones con probabilidades.
- Se agregó soporte para el mapeo de nombres de clases, si está disponible.
- Método Handle:
- Se añadió un método principal
handle
que TorchServe llama, el cual orquesta los pasos de preprocesamiento, inferencia y posprocesamiento.
- Se añadió un método principal
- Manejo de errores y registro:
- Incorporado en todo el código para facilitar la depuración y mejorar la robustez.
- Flexibilidad:
- Ahora el controlador es más flexible, capaz de trabajar con o sin un archivo de mapeo de clases.
Esta implementación proporciona un controlador más preparado para la producción que puede manejar varios escenarios y casos límite, haciéndolo más adecuado para la implementación en el mundo real con TorchServe.
4.5.3 Creación del archivo de modelo (.mar)
El archivo de modelo, denotado por la extensión .mar
, es un componente crucial en el proceso de implementación de TorchServe. Este archivo actúa como un paquete integral que encapsula todos los elementos esenciales necesarios para servir un modelo, incluyendo:
- Pesos del modelo: Los parámetros entrenados de tu red neuronal.
- Controlador del modelo: Un script en Python que define cómo cargar el modelo y procesar las solicitudes.
- Configuración del modelo: Cualquier archivo o metadato adicional necesario para la operación del modelo.
TorchServe utiliza este archivo como un punto de referencia único al cargar y ejecutar el modelo, lo que simplifica el proceso de implementación y asegura que todos los componentes necesarios estén empaquetados juntos.
Paso 2: Crear el archivo de modelo utilizando torch-model-archiver
Para facilitar la creación de estos archivos de modelo, TorchServe proporciona una herramienta de línea de comandos llamada torch-model-archiver
. Esta utilidad simplifica el proceso de empaquetar tus modelos PyTorch y los archivos asociados en el formato requerido .mar
.
La herramienta torch-model-archiver
requiere dos entradas principales:
- state_dict del modelo: Esta es la forma serializada de los parámetros de tu modelo, normalmente guardada como un archivo
.pth
o.pt
. - Archivo de controlador: Un script en Python que define cómo TorchServe debe interactuar con tu modelo, incluyendo métodos para preprocesar entradas, ejecutar inferencia y posprocesar salidas.
Además, puedes incluir otros archivos necesarios como etiquetas de clase, archivos de configuración o cualquier otro recurso requerido para la operación de tu modelo.
Al usar torch-model-archiver
, te aseguras de que todos los componentes estén empaquetados correctamente y listos para la implementación con TorchServe, promoviendo consistencia y facilidad de uso en diferentes entornos.
Comando para crear el archivo .mar
:
# Archive the ResNet18 model for TorchServe
torch-model-archiver \
--model-name resnet18 \ # Model name
--version 1.0 \ # Version number
--model-file model.py \ # Path to model definition (if needed)
--serialized-file resnet18.pth \ # Path to saved weights
--handler handler.py \ # Path to custom handler (if any)
--export-path model_store \ # Output directory
--extra-files index_to_name.json # Additional files like class labels
4.5.4 Iniciar el servidor de modelos TorchServe
Una vez que el archivo de modelo se ha creado, puedes iniciar TorchServe para desplegar el modelo. Este proceso implica inicializar el servidor de TorchServe, que actúa como un entorno de ejecución para tus modelos PyTorch. TorchServe carga el archivo de modelo (.mar) que has creado, configura los puntos de acceso necesarios para la inferencia y gestiona el ciclo de vida del modelo.
Cuando inicias TorchServe, realiza varias acciones clave:
- Carga el modelo desde el archivo .mar en la memoria.
- Inicializa cualquier controlador personalizado que hayas definido.
- Configura puntos de acceso API REST para la gestión del modelo y la inferencia.
- Prepara el modelo para su servicio, asegurándose de que esté listo para manejar solicitudes entrantes.
Este paso de implementación es crucial, ya que convierte tu modelo de un archivo estático a un servicio activo y accesible, capaz de procesar solicitudes de inferencia en tiempo real. Una vez que TorchServe está en funcionamiento con tu modelo, está listo para aceptar y responder a solicitudes de predicciones, llevando efectivamente tu modelo de machine learning a un estado listo para producción.
Paso 3: Iniciar TorchServe
torchserve --start --model-store model_store --models resnet18=resnet18.mar
Aquí tienes un desglose del comando:
torchserve
: Este es el comando principal para ejecutar TorchServe.-start
: Esta bandera indica a TorchServe que inicie el servidor.-model-store model_store
: Esto especifica el directorio donde se almacenan tus archivos de modelo (.mar). En este caso, es un directorio llamado "model_store".-models resnet18=resnet18.mar
: Esto le indica a TorchServe qué modelos cargar. Aquí, está cargando un modelo ResNet-18 desde un archivo llamado "resnet18.mar".
Cuando ejecutas este comando, TorchServe se iniciará, cargará el modelo ResNet-18 especificado desde el archivo .mar en el almacén de modelos y lo pondrá disponible para servir predicciones a través de una API.
4.5.5 Realizar predicciones a través de la API
Una vez que el modelo se ha desplegado, puedes enviar solicitudes de inferencia a la API para obtener predicciones en tiempo real. Este paso es crucial, ya que te permite utilizar tu modelo entrenado en aplicaciones prácticas. A continuación se explica este proceso en más detalle:
- Punto de acceso API: TorchServe crea un punto de acceso API REST para tu modelo. Este punto de acceso generalmente está disponible en una URL como http://localhost:8080/predictions/[model_name].
- Formato de solicitud: Puedes enviar solicitudes HTTP POST a este punto de acceso. El cuerpo de la solicitud generalmente contiene los datos de entrada (por ejemplo, un archivo de imagen para tareas de clasificación de imágenes) sobre los que deseas realizar predicciones.
- Procesamiento en tiempo real: Cuando envías una solicitud, TorchServe la procesa en tiempo real. Utiliza el modelo desplegado para generar predicciones basadas en los datos de entrada.
- Respuesta: La API devuelve una respuesta que contiene las predicciones del modelo. Esto podría ser probabilidades de clases para una tarea de clasificación, cuadros delimitadores para una tarea de detección de objetos, o cualquier otra salida relevante para el propósito de tu modelo.
- Integración: Este enfoque basado en API permite una fácil integración de tu modelo en varias aplicaciones, sitios web o servicios, lo que te permite aprovechar tu modelo de IA en escenarios del mundo real.
Al utilizar esta API, puedes incorporar sin problemas las capacidades de tu modelo PyTorch en tu ecosistema de software más amplio, convirtiéndolo en una herramienta poderosa para implementar funciones y características impulsadas por IA.
Paso 4: Enviar una solicitud de predicción a la API de TorchServe
import requests
import json
from PIL import Image
import io
def predict_image(image_path, model_name, server_url):
"""
Send an image to TorchServe for prediction.
Args:
image_path (str): Path to the image file
model_name (str): Name of the model to use for prediction
server_url (str): Base URL of the TorchServe server
Returns:
dict: Prediction results
"""
# Prepare the image file for prediction
with open(image_path, 'rb') as file:
image_data = file.read()
# Prepare the request
url = f"{server_url}/predictions/{model_name}"
files = {'data': ('image.jpg', image_data)}
try:
# Send a POST request to the model's endpoint
response = requests.post(url, files=files)
response.raise_for_status() # Raise an exception for bad status codes
# Parse and return the prediction result
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error occurred: {e}")
return None
# Example usage
if __name__ == "__main__":
image_path = 'test_image.jpg'
model_name = 'resnet18'
server_url = 'http://localhost:8080'
result = predict_image(image_path, model_name, server_url)
if result:
print("Prediction Result:")
print(json.dumps(result, indent=2))
else:
print("Failed to get prediction.")
Este ejemplo de código proporciona un enfoque integral para realizar predicciones utilizando TorchServe. A continuación, se detalla cada uno de los componentes clave:
- Definición de la función:
- Definimos una función
predict_image
que encapsula el proceso de predicción. - Esta función toma tres parámetros: la ruta al archivo de imagen, el nombre del modelo y la URL del servidor TorchServe.
- Definimos una función
- Preparación de la imagen:
- El archivo de imagen se lee como datos binarios, lo que es más eficiente que abrirlo como un objeto PIL Image.
- Preparación de la solicitud:
- Construimos la URL completa para el punto de acceso de predicción utilizando la URL del servidor y el nombre del modelo.
- Los datos de la imagen se preparan como un archivo para ser enviados en la solicitud POST.
- Manejo de errores:
- El código utiliza un bloque try-except para manejar posibles errores durante la solicitud.
- Se usa
raise_for_status()
para capturar cualquier error HTTP.
- Procesamiento de la respuesta:
- La respuesta en formato JSON del servidor se devuelve si la solicitud es exitosa.
- Ejecución principal:
- El script incluye un bloque de ejecución condicional principal.
- Demuestra cómo utilizar la función
predict_image
con parámetros de ejemplo.
- Visualización de resultados:
- Si se obtiene una predicción correctamente, se imprime en una estructura JSON formateada para mejorar la legibilidad.
- Si la predicción falla, se muestra un mensaje de error.
Este ejemplo ofrece un manejo de errores robusto, mayor flexibilidad mediante la parametrización y una estructura más clara que aísla la funcionalidad central en una función reutilizable. Está mejor adaptado para la integración en proyectos más grandes y proporciona una base sólida para el desarrollo futuro o la personalización.
4.5.6 Monitorización y gestión de modelos con TorchServe
TorchServe ofrece una suite completa de características para monitorear y gestionar tus modelos desplegados, mejorando tu capacidad para mantener y optimizar tu infraestructura de machine learning:
- Métricas: TorchServe proporciona métricas detalladas de rendimiento accesibles a través del punto de acceso
/metrics
. Estas métricas incluyen:- Latencia: Mide el tiempo que tarda tu modelo en procesar solicitudes, ayudándote a identificar y solucionar cuellos de botella en el rendimiento.
- Rendimiento: Rastrea el número de solicitudes que tu modelo puede manejar por unidad de tiempo, lo que es crucial para la planificación de la capacidad y las decisiones de escalado.
- Utilización de la GPU: Para modelos que se ejecutan en GPUs, monitorea el uso de recursos para asegurar un rendimiento óptimo.
- Tasas de solicitud: Analiza la frecuencia de las solicitudes entrantes para entender los patrones de uso y los momentos de mayor actividad.
Estas métricas permiten tomar decisiones basadas en datos para la optimización del modelo y la planificación de la infraestructura.
- Escalado: Las capacidades de escalado de TorchServe están diseñadas para manejar cargas variables en entornos de producción:
- Escalado horizontal: Despliega múltiples instancias del mismo modelo en diferentes servidores para distribuir la carga de trabajo.
- Escalado vertical: Ajusta los recursos (CPU, GPU, memoria) asignados a cada instancia del modelo según la demanda.
- Autoescalado: Implementa reglas de autoescalado predictivo o basado en reglas para ajustar dinámicamente el número de instancias del modelo en función de los patrones de tráfico.
- Balanceo de carga: Distribuye eficientemente las solicitudes entrantes entre múltiples instancias del modelo para asegurar una utilización óptima de los recursos.
Estas características de escalado permiten que tu despliegue maneje sin problemas escenarios de alto tráfico y mantenga un rendimiento consistente bajo cargas variables.
- Registros: El sistema de registro de TorchServe es una herramienta poderosa para monitorear y solucionar problemas en tus modelos desplegados:
- Registros de errores: Captura y clasifica errores que ocurren durante la inferencia del modelo, ayudando a identificar y resolver problemas rápidamente.
- Registros de solicitudes: Rastrea solicitudes individuales, incluyendo los datos de entrada y las respuestas del modelo, útiles para depuración y auditoría.
- Registros del sistema: Monitorea eventos a nivel del servidor, como la carga o descarga de modelos y cambios de configuración.
- Registro personalizado: Implementa registros personalizados dentro de tus controladores de modelo para capturar información específica de la aplicación.
- Agregación de registros: Integra con herramientas de gestión de registros para la recolección y análisis centralizados de registros en múltiples instancias.
Estos registros exhaustivos proporcionan información invaluable para mantener la salud y el rendimiento de tus modelos desplegados.
Al aprovechar estas funciones avanzadas, puedes garantizar que tu implementación de TorchServe sea robusta, escalable y fácil de gestionar en entornos de producción.
4.5 Implementación de modelos PyTorch con TorchServe
Después de entrenar un modelo en PyTorch, el siguiente paso crucial es implementarlo en un entorno de producción donde pueda procesar nuevos datos y generar predicciones. TorchServe, una colaboración entre AWS y Facebook, ofrece una solución robusta y adaptable para servir modelos de PyTorch. Esta poderosa herramienta permite la implementación fluida de modelos entrenados como API REST, facilita la gestión simultánea de varios modelos y proporciona capacidades de escalado horizontal para manejar escenarios de alto tráfico.
TorchServe cuenta con una gama de características diseñadas para satisfacer las demandas de implementaciones a nivel de producción:
- Servicio multi-modelo: Gestiona y sirve eficientemente múltiples modelos dentro de una única instancia, optimizando el uso de recursos.
- Registro y monitoreo exhaustivos: Aprovecha las funcionalidades integradas de métricas y registro para un seguimiento detallado del rendimiento y análisis.
- Inferencia avanzada por lotes: Mejora el rendimiento agrupando inteligentemente las solicitudes entrantes en lotes, maximizando el rendimiento y la eficiencia.
- Integración fluida con GPU: Aprovecha la potencia de las GPUs para acelerar drásticamente los procesos de inferencia, permitiendo tiempos de respuesta más rápidos.
- Gestión dinámica de modelos: Actualiza, versiona y retrocede fácilmente los modelos sin interrupción del servicio, asegurando una mejora continua y flexibilidad.
Esta sección proporcionará una guía completa para implementar un modelo utilizando TorchServe. Cubriremos todo el proceso, desde preparar el modelo en un formato compatible con TorchServe hasta configurar y lanzar el servidor de modelos. Además, exploraremos las mejores prácticas para optimizar la implementación y aprovechar las características avanzadas de TorchServe para garantizar un servicio robusto y escalable en entornos de producción.
4.5.1 Preparación del modelo para TorchServe
Antes de implementar un modelo PyTorch con TorchServe, es crucial preparar el modelo en un formato que TorchServe pueda interpretar y utilizar de manera efectiva. Este proceso de preparación implica varios pasos clave:
1. Serialización del modelo
El primer paso para preparar un modelo PyTorch para su implementación con TorchServe es serializar el modelo entrenado. La serialización es el proceso de convertir una estructura de datos compleja o el estado de un objeto en un formato que se pueda almacenar o transmitir y reconstruir más tarde. En el contexto de los modelos de PyTorch, esto implica principalmente guardar el diccionario de estado del modelo.
El diccionario de estado, al que se accede a través de model.state_dict()
, es un diccionario de Python que asigna cada capa a sus tensores de parámetros. Contiene todos los parámetros entrenables (pesos y sesgos) del modelo. PyTorch proporciona una función conveniente, torch.save()
, para serializar este diccionario de estado.
Aquí tienes un proceso típico para la serialización de modelos:
- Entrena tu modelo PyTorch al nivel de rendimiento deseado.
- Accede al diccionario de estado del modelo utilizando
model.state_dict()
. - Usa
torch.save(model.state_dict(), 'model.pth')
para guardar el diccionario de estado en un archivo. La extensión '.pth' se usa comúnmente para archivos de modelos PyTorch, aunque no es obligatoria.
Este paso de serialización es crucial porque te permite:
- Conservar los parámetros del modelo entrenado para uso futuro.
- Compartir el modelo con otros sin necesidad de compartir todo el proceso de entrenamiento.
- Implementar el modelo en entornos de producción, como con TorchServe.
- Reanudar el entrenamiento desde un estado previamente guardado.
Es importante tener en cuenta que torch.save()
utiliza el módulo pickle de Python para serializar el objeto, por lo que debes tener precaución al cargar modelos desde fuentes no confiables. Además, aunque puedes guardar todo el objeto del modelo, generalmente se recomienda guardar solo el diccionario de estado para una mejor portabilidad y flexibilidad.
2. Creación de un archivo de modelo
TorchServe requiere que los modelos se empaqueten en un archivo de Model Archive (.mar
). Este archivo es un paquete integral que encapsula todos los componentes necesarios para implementar y servir un modelo de aprendizaje automático. El formato .mar
está específicamente diseñado para trabajar perfectamente con TorchServe, asegurando que todos los elementos requeridos estén empaquetados juntos para un servicio eficiente del modelo. Este archivo incluye:
- Los pesos y la arquitectura del modelo: Este es el núcleo del archivo, que contiene los parámetros entrenados (pesos) y la estructura (arquitectura) de la red neuronal. Estos normalmente se guardan como un diccionario de estado de PyTorch (
.pth
) o un archivo de modelo serializado. - Cualquier archivo de configuración necesario: Estos pueden incluir archivos JSON o YAML que especifiquen configuraciones específicas del modelo, hiperparámetros u otros detalles de configuración necesarios para la inicialización y ejecución del modelo.
- Código personalizado para preprocesamiento, posprocesamiento o manejo de requisitos específicos del modelo: Esto a menudo incluye un script de controlador personalizado (generalmente un archivo Python) que define cómo deben preprocesarse los datos de entrada antes de ser enviados al modelo, cómo debe posprocesarse la salida del modelo y cualquier otra lógica específica del modelo requerida para la inferencia.
- Recursos adicionales como mapeos de etiquetas o tokenizadores: Estos son archivos complementarios que ayudan a interpretar la entrada o salida del modelo. Por ejemplo, un archivo de mapeo de etiquetas podría asociar predicciones numéricas de clases con etiquetas legibles por humanos, mientras que un tokenizador podría ser necesario para procesar entradas de texto en modelos de procesamiento de lenguaje natural.
El archivo de modelo sirve como una unidad autónoma que incluye todo lo que TorchServe necesita para implementar y ejecutar el modelo. Este enfoque de empaquetado garantiza portabilidad, lo que facilita la transferencia de modelos entre diferentes entornos o su implementación en varios sistemas sin preocuparse por dependencias faltantes o problemas de configuración.
3. Controlador del modelo
Crear una clase de controlador personalizado es un paso crucial para definir cómo TorchServe interactúa con tu modelo. Este controlador actúa como una interfaz entre TorchServe y tu modelo PyTorch, proporcionando métodos para:
- Preprocesar datos de entrada: Este método transforma los datos de entrada en bruto en un formato adecuado para tu modelo. Por ejemplo, podría redimensionar imágenes, tokenizar textos o normalizar valores numéricos.
- Ejecutar la inferencia: Este método pasa los datos preprocesados a través de tu modelo para generar predicciones.
- Posprocesar los resultados: Este método toma la salida en bruto del modelo y la formatea en una respuesta fácil de usar. Podría implicar decodificar predicciones, aplicar umbrales o formatear la salida como JSON.
El controlador también suele incluir métodos para la inicialización y carga del modelo. Al personalizar estos métodos, puedes asegurarte de que tu modelo se integre perfectamente con TorchServe, maneje correctamente varios tipos de entrada y proporcione salidas significativas a los usuarios o aplicaciones que consumen las predicciones de tu modelo.
4. Versionado
El archivo .mar
admite el control de versiones, una característica crucial para gestionar diferentes iteraciones de tu modelo. Esta capacidad te permite:
- Mantener varias versiones del mismo modelo de manera simultánea, cada una optimizada potencialmente para diferentes casos de uso o métricas de rendimiento.
- Implementar pruebas A/B al desplegar diferentes versiones de un modelo y comparar su rendimiento en escenarios del mundo real.
- Facilitar despliegues graduales de actualizaciones del modelo, permitiendo reemplazar incrementalmente una versión anterior con una más reciente mientras monitoreas posibles comportamientos inesperados o caídas de rendimiento.
- Revertir fácilmente a una versión anterior si surgen problemas con una nueva implementación, asegurando una mínima interrupción del servicio.
- Rastrear la evolución de tu modelo a lo largo del tiempo, proporcionando valiosos conocimientos sobre el proceso de desarrollo y ayudando con la gobernanza y los requisitos de cumplimiento del modelo.
Al aprovechar esta función de versionado, puedes asegurar una estrategia de implementación más robusta y flexible, permitiendo una mejora continua de tus modelos mientras mantienes la estabilidad y confiabilidad de tus servicios de aprendizaje automático.
Al preparar meticulosamente tu modelo en este formato compatible con TorchServe, aseguras una implementación fluida y un rendimiento óptimo en entornos de producción. Esta etapa de preparación es fundamental para aprovechar las capacidades de TorchServe al servir modelos PyTorch de manera eficiente y a gran escala.
Paso 1: Exportar el modelo
Para utilizar TorchServe de manera efectiva, hay dos pasos cruciales que debes seguir al preparar tu modelo:
- Guarda los pesos del modelo: Esto se hace utilizando la función
torch.save()
de PyTorch. Esta función serializa los parámetros del modelo (pesos y sesgos) en un archivo, normalmente con una extensión .pth. Este paso es esencial ya que captura el conocimiento aprendido de tu modelo entrenado. - Asegura una serialización adecuada: No basta con solo guardar los pesos; necesitas asegurarte de que el modelo esté serializado de una manera que TorchServe pueda entender y cargar. Esto a menudo implica guardar no solo el diccionario de estado del modelo, sino también cualquier capa personalizada, pasos de preprocesamiento u otra información específica del modelo que TorchServe necesitará para instanciar y usar correctamente tu modelo.
Siguiendo cuidadosamente estos pasos, aseguras que tu modelo pueda ser cargado y servido de manera eficiente por TorchServe, lo que permite una implementación fluida y una inferencia en entornos de producción.
Ejemplo: Exportando un modelo preentrenado
import torch
import torchvision.models as models
from torchvision import transforms
from PIL import Image
# Load a pretrained ResNet-18 model
model = models.resnet18(pretrained=True)
# Set the model to evaluation mode
model.eval()
# Save the model's state_dict (required by TorchServe)
torch.save(model.state_dict(), 'resnet18.pth')
# Define a function to preprocess the input image
def preprocess_image(image_path):
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
image = Image.open(image_path)
return transform(image).unsqueeze(0)
# Load and preprocess a sample image
sample_image = preprocess_image('sample_image.jpg')
# Perform inference
with torch.no_grad():
output = model(sample_image)
# Get the predicted class index
_, predicted_idx = torch.max(output, 1)
predicted_label = predicted_idx.item()
print(f"Predicted class index: {predicted_label}")
# Load ImageNet class labels from a file
imagenet_classes = []
with open("imagenet_classes.txt") as f:
imagenet_classes = [line.strip() for line in f.readlines()]
# Ensure the class index is within range
if predicted_label < len(imagenet_classes):
print(f"Predicted class: {imagenet_classes[predicted_label]}")
else:
print("Predicted class index is out of range.")
Este ejemplo de código demuestra un flujo de trabajo completo para usar un modelo ResNet-18 preentrenado, guardarlo y realizar inferencias con las etiquetas de clase correctas de ImageNet.
Desglose del código:
- Importación de bibliotecas necesarias:
torch
: La biblioteca principal de PyTorch.torchvision.models
: Proporciona modelos preentrenados.torchvision.transforms
: Para preprocesamiento de imágenes.PIL
: Para cargar y manipular imágenes.
- Carga del modelo preentrenado:
- Usamos
models.resnet18(pretrained=True)
para cargar un modelo ResNet-18 con pesos preentrenados entrenado en ImageNet.
- Usamos
- Configuración del modelo en modo evaluación:
model.eval()
asegura que el modelo esté en modo de inferencia, desactivando dropout y actualizaciones de normalización por lotes para predicciones más estables.
- Guardado del diccionario de estado del modelo:
torch.save(model.state_dict(), 'resnet18.pth')
guarda solo los parámetros del modelo, que es la forma recomendada de guardar un modelo PyTorch para implementación.
- Definición de una función de preprocesamiento:
preprocess_image(image_path)
aplica el preprocesamiento estándar de ImageNet:- Redimensionar a
256x256
- Recorte central a
224x224
- Conversión a tensor
- Normalización usando los valores de media y desviación estándar de ImageNet
- Redimensionar a
- Carga y preprocesamiento de una imagen de ejemplo:
- Llamamos a
preprocess_image('sample_image.jpg')
para transformar una imagen en un formato compatible con el modelo.
- Llamamos a
- Realización de inferencia:
- El bloque
with torch.no_grad():
asegura que no se calculen gradientes, reduciendo el uso de memoria y acelerando la inferencia.
- El bloque
- Interpretación de la salida:
- Usamos
torch.max(output, 1)
para obtener el índice de clase con la probabilidad más alta.
- Usamos
- Carga y mapeo de etiquetas de clase:
- El modelo predice un índice de clase de ImageNet (0-999), por lo que cargamos las etiquetas correctas de ImageNet desde
imagenet_classes.txt
. - Nos aseguramos de que el índice predicho esté dentro del rango antes de imprimir la etiqueta.
- El modelo predice un índice de clase de ImageNet (0-999), por lo que cargamos las etiquetas correctas de ImageNet desde
- Impresión de resultados:
- Se imprimen el índice de clase y el nombre de clase legible para una mejor interpretación.
Este ejemplo asegura un flujo de trabajo robusto para usar un modelo preentrenado, guardarlo para implementación y realizar inferencias con etiquetas correctas, que son elementos esenciales para aplicaciones de aprendizaje profundo en el mundo real.
4.5.2 Escribir un controlador de modelo personalizado (Opcional)
TorchServe utiliza controladores de modelo como un componente crucial en su arquitectura. Estos controladores sirven como un puente entre el marco de TorchServe y tu modelo específico de PyTorch, definiendo dos aspectos clave de la implementación del modelo:
- Carga del modelo: Los controladores especifican cómo debe inicializarse y cargarse tu modelo en memoria. Esto incluye tareas como:
- Cargar la arquitectura del modelo y los pesos desde archivos guardados.
- Configurar el modelo en modo de evaluación para la inferencia.
- Mover el modelo al dispositivo adecuado (CPU o GPU).
- Manejo de solicitudes de inferencia: Los controladores dictan cómo TorchServe debe procesar las solicitudes de inferencia entrantes, lo que generalmente implica:
- Preprocesar los datos de entrada para que coincidan con el formato esperado del modelo.
- Pasar los datos preprocesados a través del modelo.
- Posprocesar la salida del modelo para generar la respuesta final.
Si bien TorchServe proporciona controladores predeterminados para escenarios comunes, es posible que necesites crear un controlador personalizado si tu modelo requiere pasos específicos de preprocesamiento o posprocesamiento. Por ejemplo:
- Preprocesamiento de imágenes personalizado para modelos de visión por computadora.
- Tokenización de texto para modelos de procesamiento de lenguaje natural.
- Formateo especializado de la salida para las necesidades de tu aplicación.
Al implementar un controlador personalizado, aseguras que tu modelo se integre sin problemas con TorchServe, permitiendo una inferencia eficiente y precisa en entornos de producción.
Ejemplo: Escribir un controlador personalizado (Opcional)
import torch
import torchvision.models as models
from torchvision import transforms
from PIL import Image
import json
import logging
class ResNetHandler:
def __init__(self):
self.model = None
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
self.class_to_idx = None
self.logger = logging.getLogger(__name__)
def initialize(self, context):
"""
Initialize the handler at startup.
:param context: Initial context containing model server system properties.
"""
self.manifest = context.manifest
properties = context.system_properties
model_dir = properties.get("model_dir")
self.logger.info(f"Model directory: {model_dir}")
# Load the model architecture
self.model = models.resnet18(pretrained=False)
self.model.fc = torch.nn.Linear(self.model.fc.in_features, 1000) # Adjust if needed
# Load the model's state_dict
state_dict_path = f"{model_dir}/resnet18.pth"
self.logger.info(f"Loading model from {state_dict_path}")
self.model.load_state_dict(torch.load(state_dict_path, map_location=self.device))
self.model.eval()
self.model.to(self.device)
# Load class mapping
class_mapping_path = f"{model_dir}/class_mapping.json"
try:
with open(class_mapping_path, 'r') as f:
self.class_to_idx = json.load(f)
self.logger.info("Class mapping loaded successfully")
except FileNotFoundError:
self.logger.warning(f"Class mapping file not found at {class_mapping_path}")
self.logger.info("Model initialized successfully")
def preprocess(self, data):
"""
Preprocess the input data before inference.
:param data: Input data to be preprocessed.
:return: Preprocessed data for model input.
"""
self.logger.info("Preprocessing input data")
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
images = []
for row in data:
image = row.get("data") or row.get("body")
if isinstance(image, (bytes, bytearray)):
image = Image.open(io.BytesIO(image))
elif isinstance(image, str):
image = Image.open(image)
else:
raise ValueError(f"Unsupported image format: {type(image)}")
images.append(transform(image))
return torch.stack(images).to(self.device)
def inference(self, data):
"""
Perform inference on the preprocessed data.
:param data: Preprocessed data for model input.
:return: Raw model output.
"""
self.logger.info("Performing inference")
with torch.no_grad():
output = self.model(data)
return output
def postprocess(self, inference_output):
"""
Postprocess the model output.
:param inference_output: Raw model output.
:return: Processed output.
"""
self.logger.info("Postprocessing inference output")
probabilities = torch.nn.functional.softmax(inference_output, dim=1)
top_prob, top_class = torch.topk(probabilities, 5)
result = []
for i in range(top_prob.shape[0]):
item_result = []
for j in range(5):
class_idx = top_class[i][j].item()
if self.class_to_idx:
class_name = self.class_to_idx.get(str(class_idx), f"Unknown class {class_idx}")
else:
class_name = f"Class {class_idx}"
item_result.append({
"class": class_name,
"probability": top_prob[i][j].item()
})
result.append(item_result)
return json.dumps(result)
def handle(self, data, context):
"""
Handle a request to the model.
:param data: Input data for inference.
:param context: Context object containing request details.
:return: Processed output.
"""
self.logger.info("Handling inference request")
preprocessed_data = self.preprocess(data)
inference_output = self.inference(preprocessed_data)
return self.postprocess(inference_output)
Este ejemplo de código proporciona una implementación completa de un controlador personalizado para TorchServe.
Aquí tienes un desglose detallado de los cambios y adiciones:
- Importaciones:
Se añadieron las importaciones necesarias, incluyendo
logging
para mejorar la depuración y el seguimiento de errores. - Inicialización:
- Se agregó la configuración de registro (
logging
). - Se incluyó el manejo de errores para la carga del modelo y el mapeo de clases.
- Se hizo la inicialización más robusta utilizando el objeto de contexto proporcionado por TorchServe.
- Se agregó la configuración de registro (
- Preprocesamiento:
- Mejorado para manejar múltiples formatos de entrada (bytes, rutas de archivo).
- Se añadió soporte para el procesamiento por lotes.
- Inferencia:
- Se mantuvo simple y enfocado en ejecutar el modelo.
- Posprocesamiento:
- Mejorado para devolver las 5 mejores predicciones con probabilidades.
- Se agregó soporte para el mapeo de nombres de clases, si está disponible.
- Método Handle:
- Se añadió un método principal
handle
que TorchServe llama, el cual orquesta los pasos de preprocesamiento, inferencia y posprocesamiento.
- Se añadió un método principal
- Manejo de errores y registro:
- Incorporado en todo el código para facilitar la depuración y mejorar la robustez.
- Flexibilidad:
- Ahora el controlador es más flexible, capaz de trabajar con o sin un archivo de mapeo de clases.
Esta implementación proporciona un controlador más preparado para la producción que puede manejar varios escenarios y casos límite, haciéndolo más adecuado para la implementación en el mundo real con TorchServe.
4.5.3 Creación del archivo de modelo (.mar)
El archivo de modelo, denotado por la extensión .mar
, es un componente crucial en el proceso de implementación de TorchServe. Este archivo actúa como un paquete integral que encapsula todos los elementos esenciales necesarios para servir un modelo, incluyendo:
- Pesos del modelo: Los parámetros entrenados de tu red neuronal.
- Controlador del modelo: Un script en Python que define cómo cargar el modelo y procesar las solicitudes.
- Configuración del modelo: Cualquier archivo o metadato adicional necesario para la operación del modelo.
TorchServe utiliza este archivo como un punto de referencia único al cargar y ejecutar el modelo, lo que simplifica el proceso de implementación y asegura que todos los componentes necesarios estén empaquetados juntos.
Paso 2: Crear el archivo de modelo utilizando torch-model-archiver
Para facilitar la creación de estos archivos de modelo, TorchServe proporciona una herramienta de línea de comandos llamada torch-model-archiver
. Esta utilidad simplifica el proceso de empaquetar tus modelos PyTorch y los archivos asociados en el formato requerido .mar
.
La herramienta torch-model-archiver
requiere dos entradas principales:
- state_dict del modelo: Esta es la forma serializada de los parámetros de tu modelo, normalmente guardada como un archivo
.pth
o.pt
. - Archivo de controlador: Un script en Python que define cómo TorchServe debe interactuar con tu modelo, incluyendo métodos para preprocesar entradas, ejecutar inferencia y posprocesar salidas.
Además, puedes incluir otros archivos necesarios como etiquetas de clase, archivos de configuración o cualquier otro recurso requerido para la operación de tu modelo.
Al usar torch-model-archiver
, te aseguras de que todos los componentes estén empaquetados correctamente y listos para la implementación con TorchServe, promoviendo consistencia y facilidad de uso en diferentes entornos.
Comando para crear el archivo .mar
:
# Archive the ResNet18 model for TorchServe
torch-model-archiver \
--model-name resnet18 \ # Model name
--version 1.0 \ # Version number
--model-file model.py \ # Path to model definition (if needed)
--serialized-file resnet18.pth \ # Path to saved weights
--handler handler.py \ # Path to custom handler (if any)
--export-path model_store \ # Output directory
--extra-files index_to_name.json # Additional files like class labels
4.5.4 Iniciar el servidor de modelos TorchServe
Una vez que el archivo de modelo se ha creado, puedes iniciar TorchServe para desplegar el modelo. Este proceso implica inicializar el servidor de TorchServe, que actúa como un entorno de ejecución para tus modelos PyTorch. TorchServe carga el archivo de modelo (.mar) que has creado, configura los puntos de acceso necesarios para la inferencia y gestiona el ciclo de vida del modelo.
Cuando inicias TorchServe, realiza varias acciones clave:
- Carga el modelo desde el archivo .mar en la memoria.
- Inicializa cualquier controlador personalizado que hayas definido.
- Configura puntos de acceso API REST para la gestión del modelo y la inferencia.
- Prepara el modelo para su servicio, asegurándose de que esté listo para manejar solicitudes entrantes.
Este paso de implementación es crucial, ya que convierte tu modelo de un archivo estático a un servicio activo y accesible, capaz de procesar solicitudes de inferencia en tiempo real. Una vez que TorchServe está en funcionamiento con tu modelo, está listo para aceptar y responder a solicitudes de predicciones, llevando efectivamente tu modelo de machine learning a un estado listo para producción.
Paso 3: Iniciar TorchServe
torchserve --start --model-store model_store --models resnet18=resnet18.mar
Aquí tienes un desglose del comando:
torchserve
: Este es el comando principal para ejecutar TorchServe.-start
: Esta bandera indica a TorchServe que inicie el servidor.-model-store model_store
: Esto especifica el directorio donde se almacenan tus archivos de modelo (.mar). En este caso, es un directorio llamado "model_store".-models resnet18=resnet18.mar
: Esto le indica a TorchServe qué modelos cargar. Aquí, está cargando un modelo ResNet-18 desde un archivo llamado "resnet18.mar".
Cuando ejecutas este comando, TorchServe se iniciará, cargará el modelo ResNet-18 especificado desde el archivo .mar en el almacén de modelos y lo pondrá disponible para servir predicciones a través de una API.
4.5.5 Realizar predicciones a través de la API
Una vez que el modelo se ha desplegado, puedes enviar solicitudes de inferencia a la API para obtener predicciones en tiempo real. Este paso es crucial, ya que te permite utilizar tu modelo entrenado en aplicaciones prácticas. A continuación se explica este proceso en más detalle:
- Punto de acceso API: TorchServe crea un punto de acceso API REST para tu modelo. Este punto de acceso generalmente está disponible en una URL como http://localhost:8080/predictions/[model_name].
- Formato de solicitud: Puedes enviar solicitudes HTTP POST a este punto de acceso. El cuerpo de la solicitud generalmente contiene los datos de entrada (por ejemplo, un archivo de imagen para tareas de clasificación de imágenes) sobre los que deseas realizar predicciones.
- Procesamiento en tiempo real: Cuando envías una solicitud, TorchServe la procesa en tiempo real. Utiliza el modelo desplegado para generar predicciones basadas en los datos de entrada.
- Respuesta: La API devuelve una respuesta que contiene las predicciones del modelo. Esto podría ser probabilidades de clases para una tarea de clasificación, cuadros delimitadores para una tarea de detección de objetos, o cualquier otra salida relevante para el propósito de tu modelo.
- Integración: Este enfoque basado en API permite una fácil integración de tu modelo en varias aplicaciones, sitios web o servicios, lo que te permite aprovechar tu modelo de IA en escenarios del mundo real.
Al utilizar esta API, puedes incorporar sin problemas las capacidades de tu modelo PyTorch en tu ecosistema de software más amplio, convirtiéndolo en una herramienta poderosa para implementar funciones y características impulsadas por IA.
Paso 4: Enviar una solicitud de predicción a la API de TorchServe
import requests
import json
from PIL import Image
import io
def predict_image(image_path, model_name, server_url):
"""
Send an image to TorchServe for prediction.
Args:
image_path (str): Path to the image file
model_name (str): Name of the model to use for prediction
server_url (str): Base URL of the TorchServe server
Returns:
dict: Prediction results
"""
# Prepare the image file for prediction
with open(image_path, 'rb') as file:
image_data = file.read()
# Prepare the request
url = f"{server_url}/predictions/{model_name}"
files = {'data': ('image.jpg', image_data)}
try:
# Send a POST request to the model's endpoint
response = requests.post(url, files=files)
response.raise_for_status() # Raise an exception for bad status codes
# Parse and return the prediction result
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error occurred: {e}")
return None
# Example usage
if __name__ == "__main__":
image_path = 'test_image.jpg'
model_name = 'resnet18'
server_url = 'http://localhost:8080'
result = predict_image(image_path, model_name, server_url)
if result:
print("Prediction Result:")
print(json.dumps(result, indent=2))
else:
print("Failed to get prediction.")
Este ejemplo de código proporciona un enfoque integral para realizar predicciones utilizando TorchServe. A continuación, se detalla cada uno de los componentes clave:
- Definición de la función:
- Definimos una función
predict_image
que encapsula el proceso de predicción. - Esta función toma tres parámetros: la ruta al archivo de imagen, el nombre del modelo y la URL del servidor TorchServe.
- Definimos una función
- Preparación de la imagen:
- El archivo de imagen se lee como datos binarios, lo que es más eficiente que abrirlo como un objeto PIL Image.
- Preparación de la solicitud:
- Construimos la URL completa para el punto de acceso de predicción utilizando la URL del servidor y el nombre del modelo.
- Los datos de la imagen se preparan como un archivo para ser enviados en la solicitud POST.
- Manejo de errores:
- El código utiliza un bloque try-except para manejar posibles errores durante la solicitud.
- Se usa
raise_for_status()
para capturar cualquier error HTTP.
- Procesamiento de la respuesta:
- La respuesta en formato JSON del servidor se devuelve si la solicitud es exitosa.
- Ejecución principal:
- El script incluye un bloque de ejecución condicional principal.
- Demuestra cómo utilizar la función
predict_image
con parámetros de ejemplo.
- Visualización de resultados:
- Si se obtiene una predicción correctamente, se imprime en una estructura JSON formateada para mejorar la legibilidad.
- Si la predicción falla, se muestra un mensaje de error.
Este ejemplo ofrece un manejo de errores robusto, mayor flexibilidad mediante la parametrización y una estructura más clara que aísla la funcionalidad central en una función reutilizable. Está mejor adaptado para la integración en proyectos más grandes y proporciona una base sólida para el desarrollo futuro o la personalización.
4.5.6 Monitorización y gestión de modelos con TorchServe
TorchServe ofrece una suite completa de características para monitorear y gestionar tus modelos desplegados, mejorando tu capacidad para mantener y optimizar tu infraestructura de machine learning:
- Métricas: TorchServe proporciona métricas detalladas de rendimiento accesibles a través del punto de acceso
/metrics
. Estas métricas incluyen:- Latencia: Mide el tiempo que tarda tu modelo en procesar solicitudes, ayudándote a identificar y solucionar cuellos de botella en el rendimiento.
- Rendimiento: Rastrea el número de solicitudes que tu modelo puede manejar por unidad de tiempo, lo que es crucial para la planificación de la capacidad y las decisiones de escalado.
- Utilización de la GPU: Para modelos que se ejecutan en GPUs, monitorea el uso de recursos para asegurar un rendimiento óptimo.
- Tasas de solicitud: Analiza la frecuencia de las solicitudes entrantes para entender los patrones de uso y los momentos de mayor actividad.
Estas métricas permiten tomar decisiones basadas en datos para la optimización del modelo y la planificación de la infraestructura.
- Escalado: Las capacidades de escalado de TorchServe están diseñadas para manejar cargas variables en entornos de producción:
- Escalado horizontal: Despliega múltiples instancias del mismo modelo en diferentes servidores para distribuir la carga de trabajo.
- Escalado vertical: Ajusta los recursos (CPU, GPU, memoria) asignados a cada instancia del modelo según la demanda.
- Autoescalado: Implementa reglas de autoescalado predictivo o basado en reglas para ajustar dinámicamente el número de instancias del modelo en función de los patrones de tráfico.
- Balanceo de carga: Distribuye eficientemente las solicitudes entrantes entre múltiples instancias del modelo para asegurar una utilización óptima de los recursos.
Estas características de escalado permiten que tu despliegue maneje sin problemas escenarios de alto tráfico y mantenga un rendimiento consistente bajo cargas variables.
- Registros: El sistema de registro de TorchServe es una herramienta poderosa para monitorear y solucionar problemas en tus modelos desplegados:
- Registros de errores: Captura y clasifica errores que ocurren durante la inferencia del modelo, ayudando a identificar y resolver problemas rápidamente.
- Registros de solicitudes: Rastrea solicitudes individuales, incluyendo los datos de entrada y las respuestas del modelo, útiles para depuración y auditoría.
- Registros del sistema: Monitorea eventos a nivel del servidor, como la carga o descarga de modelos y cambios de configuración.
- Registro personalizado: Implementa registros personalizados dentro de tus controladores de modelo para capturar información específica de la aplicación.
- Agregación de registros: Integra con herramientas de gestión de registros para la recolección y análisis centralizados de registros en múltiples instancias.
Estos registros exhaustivos proporcionan información invaluable para mantener la salud y el rendimiento de tus modelos desplegados.
Al aprovechar estas funciones avanzadas, puedes garantizar que tu implementación de TorchServe sea robusta, escalable y fácil de gestionar en entornos de producción.
4.5 Implementación de modelos PyTorch con TorchServe
Después de entrenar un modelo en PyTorch, el siguiente paso crucial es implementarlo en un entorno de producción donde pueda procesar nuevos datos y generar predicciones. TorchServe, una colaboración entre AWS y Facebook, ofrece una solución robusta y adaptable para servir modelos de PyTorch. Esta poderosa herramienta permite la implementación fluida de modelos entrenados como API REST, facilita la gestión simultánea de varios modelos y proporciona capacidades de escalado horizontal para manejar escenarios de alto tráfico.
TorchServe cuenta con una gama de características diseñadas para satisfacer las demandas de implementaciones a nivel de producción:
- Servicio multi-modelo: Gestiona y sirve eficientemente múltiples modelos dentro de una única instancia, optimizando el uso de recursos.
- Registro y monitoreo exhaustivos: Aprovecha las funcionalidades integradas de métricas y registro para un seguimiento detallado del rendimiento y análisis.
- Inferencia avanzada por lotes: Mejora el rendimiento agrupando inteligentemente las solicitudes entrantes en lotes, maximizando el rendimiento y la eficiencia.
- Integración fluida con GPU: Aprovecha la potencia de las GPUs para acelerar drásticamente los procesos de inferencia, permitiendo tiempos de respuesta más rápidos.
- Gestión dinámica de modelos: Actualiza, versiona y retrocede fácilmente los modelos sin interrupción del servicio, asegurando una mejora continua y flexibilidad.
Esta sección proporcionará una guía completa para implementar un modelo utilizando TorchServe. Cubriremos todo el proceso, desde preparar el modelo en un formato compatible con TorchServe hasta configurar y lanzar el servidor de modelos. Además, exploraremos las mejores prácticas para optimizar la implementación y aprovechar las características avanzadas de TorchServe para garantizar un servicio robusto y escalable en entornos de producción.
4.5.1 Preparación del modelo para TorchServe
Antes de implementar un modelo PyTorch con TorchServe, es crucial preparar el modelo en un formato que TorchServe pueda interpretar y utilizar de manera efectiva. Este proceso de preparación implica varios pasos clave:
1. Serialización del modelo
El primer paso para preparar un modelo PyTorch para su implementación con TorchServe es serializar el modelo entrenado. La serialización es el proceso de convertir una estructura de datos compleja o el estado de un objeto en un formato que se pueda almacenar o transmitir y reconstruir más tarde. En el contexto de los modelos de PyTorch, esto implica principalmente guardar el diccionario de estado del modelo.
El diccionario de estado, al que se accede a través de model.state_dict()
, es un diccionario de Python que asigna cada capa a sus tensores de parámetros. Contiene todos los parámetros entrenables (pesos y sesgos) del modelo. PyTorch proporciona una función conveniente, torch.save()
, para serializar este diccionario de estado.
Aquí tienes un proceso típico para la serialización de modelos:
- Entrena tu modelo PyTorch al nivel de rendimiento deseado.
- Accede al diccionario de estado del modelo utilizando
model.state_dict()
. - Usa
torch.save(model.state_dict(), 'model.pth')
para guardar el diccionario de estado en un archivo. La extensión '.pth' se usa comúnmente para archivos de modelos PyTorch, aunque no es obligatoria.
Este paso de serialización es crucial porque te permite:
- Conservar los parámetros del modelo entrenado para uso futuro.
- Compartir el modelo con otros sin necesidad de compartir todo el proceso de entrenamiento.
- Implementar el modelo en entornos de producción, como con TorchServe.
- Reanudar el entrenamiento desde un estado previamente guardado.
Es importante tener en cuenta que torch.save()
utiliza el módulo pickle de Python para serializar el objeto, por lo que debes tener precaución al cargar modelos desde fuentes no confiables. Además, aunque puedes guardar todo el objeto del modelo, generalmente se recomienda guardar solo el diccionario de estado para una mejor portabilidad y flexibilidad.
2. Creación de un archivo de modelo
TorchServe requiere que los modelos se empaqueten en un archivo de Model Archive (.mar
). Este archivo es un paquete integral que encapsula todos los componentes necesarios para implementar y servir un modelo de aprendizaje automático. El formato .mar
está específicamente diseñado para trabajar perfectamente con TorchServe, asegurando que todos los elementos requeridos estén empaquetados juntos para un servicio eficiente del modelo. Este archivo incluye:
- Los pesos y la arquitectura del modelo: Este es el núcleo del archivo, que contiene los parámetros entrenados (pesos) y la estructura (arquitectura) de la red neuronal. Estos normalmente se guardan como un diccionario de estado de PyTorch (
.pth
) o un archivo de modelo serializado. - Cualquier archivo de configuración necesario: Estos pueden incluir archivos JSON o YAML que especifiquen configuraciones específicas del modelo, hiperparámetros u otros detalles de configuración necesarios para la inicialización y ejecución del modelo.
- Código personalizado para preprocesamiento, posprocesamiento o manejo de requisitos específicos del modelo: Esto a menudo incluye un script de controlador personalizado (generalmente un archivo Python) que define cómo deben preprocesarse los datos de entrada antes de ser enviados al modelo, cómo debe posprocesarse la salida del modelo y cualquier otra lógica específica del modelo requerida para la inferencia.
- Recursos adicionales como mapeos de etiquetas o tokenizadores: Estos son archivos complementarios que ayudan a interpretar la entrada o salida del modelo. Por ejemplo, un archivo de mapeo de etiquetas podría asociar predicciones numéricas de clases con etiquetas legibles por humanos, mientras que un tokenizador podría ser necesario para procesar entradas de texto en modelos de procesamiento de lenguaje natural.
El archivo de modelo sirve como una unidad autónoma que incluye todo lo que TorchServe necesita para implementar y ejecutar el modelo. Este enfoque de empaquetado garantiza portabilidad, lo que facilita la transferencia de modelos entre diferentes entornos o su implementación en varios sistemas sin preocuparse por dependencias faltantes o problemas de configuración.
3. Controlador del modelo
Crear una clase de controlador personalizado es un paso crucial para definir cómo TorchServe interactúa con tu modelo. Este controlador actúa como una interfaz entre TorchServe y tu modelo PyTorch, proporcionando métodos para:
- Preprocesar datos de entrada: Este método transforma los datos de entrada en bruto en un formato adecuado para tu modelo. Por ejemplo, podría redimensionar imágenes, tokenizar textos o normalizar valores numéricos.
- Ejecutar la inferencia: Este método pasa los datos preprocesados a través de tu modelo para generar predicciones.
- Posprocesar los resultados: Este método toma la salida en bruto del modelo y la formatea en una respuesta fácil de usar. Podría implicar decodificar predicciones, aplicar umbrales o formatear la salida como JSON.
El controlador también suele incluir métodos para la inicialización y carga del modelo. Al personalizar estos métodos, puedes asegurarte de que tu modelo se integre perfectamente con TorchServe, maneje correctamente varios tipos de entrada y proporcione salidas significativas a los usuarios o aplicaciones que consumen las predicciones de tu modelo.
4. Versionado
El archivo .mar
admite el control de versiones, una característica crucial para gestionar diferentes iteraciones de tu modelo. Esta capacidad te permite:
- Mantener varias versiones del mismo modelo de manera simultánea, cada una optimizada potencialmente para diferentes casos de uso o métricas de rendimiento.
- Implementar pruebas A/B al desplegar diferentes versiones de un modelo y comparar su rendimiento en escenarios del mundo real.
- Facilitar despliegues graduales de actualizaciones del modelo, permitiendo reemplazar incrementalmente una versión anterior con una más reciente mientras monitoreas posibles comportamientos inesperados o caídas de rendimiento.
- Revertir fácilmente a una versión anterior si surgen problemas con una nueva implementación, asegurando una mínima interrupción del servicio.
- Rastrear la evolución de tu modelo a lo largo del tiempo, proporcionando valiosos conocimientos sobre el proceso de desarrollo y ayudando con la gobernanza y los requisitos de cumplimiento del modelo.
Al aprovechar esta función de versionado, puedes asegurar una estrategia de implementación más robusta y flexible, permitiendo una mejora continua de tus modelos mientras mantienes la estabilidad y confiabilidad de tus servicios de aprendizaje automático.
Al preparar meticulosamente tu modelo en este formato compatible con TorchServe, aseguras una implementación fluida y un rendimiento óptimo en entornos de producción. Esta etapa de preparación es fundamental para aprovechar las capacidades de TorchServe al servir modelos PyTorch de manera eficiente y a gran escala.
Paso 1: Exportar el modelo
Para utilizar TorchServe de manera efectiva, hay dos pasos cruciales que debes seguir al preparar tu modelo:
- Guarda los pesos del modelo: Esto se hace utilizando la función
torch.save()
de PyTorch. Esta función serializa los parámetros del modelo (pesos y sesgos) en un archivo, normalmente con una extensión .pth. Este paso es esencial ya que captura el conocimiento aprendido de tu modelo entrenado. - Asegura una serialización adecuada: No basta con solo guardar los pesos; necesitas asegurarte de que el modelo esté serializado de una manera que TorchServe pueda entender y cargar. Esto a menudo implica guardar no solo el diccionario de estado del modelo, sino también cualquier capa personalizada, pasos de preprocesamiento u otra información específica del modelo que TorchServe necesitará para instanciar y usar correctamente tu modelo.
Siguiendo cuidadosamente estos pasos, aseguras que tu modelo pueda ser cargado y servido de manera eficiente por TorchServe, lo que permite una implementación fluida y una inferencia en entornos de producción.
Ejemplo: Exportando un modelo preentrenado
import torch
import torchvision.models as models
from torchvision import transforms
from PIL import Image
# Load a pretrained ResNet-18 model
model = models.resnet18(pretrained=True)
# Set the model to evaluation mode
model.eval()
# Save the model's state_dict (required by TorchServe)
torch.save(model.state_dict(), 'resnet18.pth')
# Define a function to preprocess the input image
def preprocess_image(image_path):
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
image = Image.open(image_path)
return transform(image).unsqueeze(0)
# Load and preprocess a sample image
sample_image = preprocess_image('sample_image.jpg')
# Perform inference
with torch.no_grad():
output = model(sample_image)
# Get the predicted class index
_, predicted_idx = torch.max(output, 1)
predicted_label = predicted_idx.item()
print(f"Predicted class index: {predicted_label}")
# Load ImageNet class labels from a file
imagenet_classes = []
with open("imagenet_classes.txt") as f:
imagenet_classes = [line.strip() for line in f.readlines()]
# Ensure the class index is within range
if predicted_label < len(imagenet_classes):
print(f"Predicted class: {imagenet_classes[predicted_label]}")
else:
print("Predicted class index is out of range.")
Este ejemplo de código demuestra un flujo de trabajo completo para usar un modelo ResNet-18 preentrenado, guardarlo y realizar inferencias con las etiquetas de clase correctas de ImageNet.
Desglose del código:
- Importación de bibliotecas necesarias:
torch
: La biblioteca principal de PyTorch.torchvision.models
: Proporciona modelos preentrenados.torchvision.transforms
: Para preprocesamiento de imágenes.PIL
: Para cargar y manipular imágenes.
- Carga del modelo preentrenado:
- Usamos
models.resnet18(pretrained=True)
para cargar un modelo ResNet-18 con pesos preentrenados entrenado en ImageNet.
- Usamos
- Configuración del modelo en modo evaluación:
model.eval()
asegura que el modelo esté en modo de inferencia, desactivando dropout y actualizaciones de normalización por lotes para predicciones más estables.
- Guardado del diccionario de estado del modelo:
torch.save(model.state_dict(), 'resnet18.pth')
guarda solo los parámetros del modelo, que es la forma recomendada de guardar un modelo PyTorch para implementación.
- Definición de una función de preprocesamiento:
preprocess_image(image_path)
aplica el preprocesamiento estándar de ImageNet:- Redimensionar a
256x256
- Recorte central a
224x224
- Conversión a tensor
- Normalización usando los valores de media y desviación estándar de ImageNet
- Redimensionar a
- Carga y preprocesamiento de una imagen de ejemplo:
- Llamamos a
preprocess_image('sample_image.jpg')
para transformar una imagen en un formato compatible con el modelo.
- Llamamos a
- Realización de inferencia:
- El bloque
with torch.no_grad():
asegura que no se calculen gradientes, reduciendo el uso de memoria y acelerando la inferencia.
- El bloque
- Interpretación de la salida:
- Usamos
torch.max(output, 1)
para obtener el índice de clase con la probabilidad más alta.
- Usamos
- Carga y mapeo de etiquetas de clase:
- El modelo predice un índice de clase de ImageNet (0-999), por lo que cargamos las etiquetas correctas de ImageNet desde
imagenet_classes.txt
. - Nos aseguramos de que el índice predicho esté dentro del rango antes de imprimir la etiqueta.
- El modelo predice un índice de clase de ImageNet (0-999), por lo que cargamos las etiquetas correctas de ImageNet desde
- Impresión de resultados:
- Se imprimen el índice de clase y el nombre de clase legible para una mejor interpretación.
Este ejemplo asegura un flujo de trabajo robusto para usar un modelo preentrenado, guardarlo para implementación y realizar inferencias con etiquetas correctas, que son elementos esenciales para aplicaciones de aprendizaje profundo en el mundo real.
4.5.2 Escribir un controlador de modelo personalizado (Opcional)
TorchServe utiliza controladores de modelo como un componente crucial en su arquitectura. Estos controladores sirven como un puente entre el marco de TorchServe y tu modelo específico de PyTorch, definiendo dos aspectos clave de la implementación del modelo:
- Carga del modelo: Los controladores especifican cómo debe inicializarse y cargarse tu modelo en memoria. Esto incluye tareas como:
- Cargar la arquitectura del modelo y los pesos desde archivos guardados.
- Configurar el modelo en modo de evaluación para la inferencia.
- Mover el modelo al dispositivo adecuado (CPU o GPU).
- Manejo de solicitudes de inferencia: Los controladores dictan cómo TorchServe debe procesar las solicitudes de inferencia entrantes, lo que generalmente implica:
- Preprocesar los datos de entrada para que coincidan con el formato esperado del modelo.
- Pasar los datos preprocesados a través del modelo.
- Posprocesar la salida del modelo para generar la respuesta final.
Si bien TorchServe proporciona controladores predeterminados para escenarios comunes, es posible que necesites crear un controlador personalizado si tu modelo requiere pasos específicos de preprocesamiento o posprocesamiento. Por ejemplo:
- Preprocesamiento de imágenes personalizado para modelos de visión por computadora.
- Tokenización de texto para modelos de procesamiento de lenguaje natural.
- Formateo especializado de la salida para las necesidades de tu aplicación.
Al implementar un controlador personalizado, aseguras que tu modelo se integre sin problemas con TorchServe, permitiendo una inferencia eficiente y precisa en entornos de producción.
Ejemplo: Escribir un controlador personalizado (Opcional)
import torch
import torchvision.models as models
from torchvision import transforms
from PIL import Image
import json
import logging
class ResNetHandler:
def __init__(self):
self.model = None
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
self.class_to_idx = None
self.logger = logging.getLogger(__name__)
def initialize(self, context):
"""
Initialize the handler at startup.
:param context: Initial context containing model server system properties.
"""
self.manifest = context.manifest
properties = context.system_properties
model_dir = properties.get("model_dir")
self.logger.info(f"Model directory: {model_dir}")
# Load the model architecture
self.model = models.resnet18(pretrained=False)
self.model.fc = torch.nn.Linear(self.model.fc.in_features, 1000) # Adjust if needed
# Load the model's state_dict
state_dict_path = f"{model_dir}/resnet18.pth"
self.logger.info(f"Loading model from {state_dict_path}")
self.model.load_state_dict(torch.load(state_dict_path, map_location=self.device))
self.model.eval()
self.model.to(self.device)
# Load class mapping
class_mapping_path = f"{model_dir}/class_mapping.json"
try:
with open(class_mapping_path, 'r') as f:
self.class_to_idx = json.load(f)
self.logger.info("Class mapping loaded successfully")
except FileNotFoundError:
self.logger.warning(f"Class mapping file not found at {class_mapping_path}")
self.logger.info("Model initialized successfully")
def preprocess(self, data):
"""
Preprocess the input data before inference.
:param data: Input data to be preprocessed.
:return: Preprocessed data for model input.
"""
self.logger.info("Preprocessing input data")
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
images = []
for row in data:
image = row.get("data") or row.get("body")
if isinstance(image, (bytes, bytearray)):
image = Image.open(io.BytesIO(image))
elif isinstance(image, str):
image = Image.open(image)
else:
raise ValueError(f"Unsupported image format: {type(image)}")
images.append(transform(image))
return torch.stack(images).to(self.device)
def inference(self, data):
"""
Perform inference on the preprocessed data.
:param data: Preprocessed data for model input.
:return: Raw model output.
"""
self.logger.info("Performing inference")
with torch.no_grad():
output = self.model(data)
return output
def postprocess(self, inference_output):
"""
Postprocess the model output.
:param inference_output: Raw model output.
:return: Processed output.
"""
self.logger.info("Postprocessing inference output")
probabilities = torch.nn.functional.softmax(inference_output, dim=1)
top_prob, top_class = torch.topk(probabilities, 5)
result = []
for i in range(top_prob.shape[0]):
item_result = []
for j in range(5):
class_idx = top_class[i][j].item()
if self.class_to_idx:
class_name = self.class_to_idx.get(str(class_idx), f"Unknown class {class_idx}")
else:
class_name = f"Class {class_idx}"
item_result.append({
"class": class_name,
"probability": top_prob[i][j].item()
})
result.append(item_result)
return json.dumps(result)
def handle(self, data, context):
"""
Handle a request to the model.
:param data: Input data for inference.
:param context: Context object containing request details.
:return: Processed output.
"""
self.logger.info("Handling inference request")
preprocessed_data = self.preprocess(data)
inference_output = self.inference(preprocessed_data)
return self.postprocess(inference_output)
Este ejemplo de código proporciona una implementación completa de un controlador personalizado para TorchServe.
Aquí tienes un desglose detallado de los cambios y adiciones:
- Importaciones:
Se añadieron las importaciones necesarias, incluyendo
logging
para mejorar la depuración y el seguimiento de errores. - Inicialización:
- Se agregó la configuración de registro (
logging
). - Se incluyó el manejo de errores para la carga del modelo y el mapeo de clases.
- Se hizo la inicialización más robusta utilizando el objeto de contexto proporcionado por TorchServe.
- Se agregó la configuración de registro (
- Preprocesamiento:
- Mejorado para manejar múltiples formatos de entrada (bytes, rutas de archivo).
- Se añadió soporte para el procesamiento por lotes.
- Inferencia:
- Se mantuvo simple y enfocado en ejecutar el modelo.
- Posprocesamiento:
- Mejorado para devolver las 5 mejores predicciones con probabilidades.
- Se agregó soporte para el mapeo de nombres de clases, si está disponible.
- Método Handle:
- Se añadió un método principal
handle
que TorchServe llama, el cual orquesta los pasos de preprocesamiento, inferencia y posprocesamiento.
- Se añadió un método principal
- Manejo de errores y registro:
- Incorporado en todo el código para facilitar la depuración y mejorar la robustez.
- Flexibilidad:
- Ahora el controlador es más flexible, capaz de trabajar con o sin un archivo de mapeo de clases.
Esta implementación proporciona un controlador más preparado para la producción que puede manejar varios escenarios y casos límite, haciéndolo más adecuado para la implementación en el mundo real con TorchServe.
4.5.3 Creación del archivo de modelo (.mar)
El archivo de modelo, denotado por la extensión .mar
, es un componente crucial en el proceso de implementación de TorchServe. Este archivo actúa como un paquete integral que encapsula todos los elementos esenciales necesarios para servir un modelo, incluyendo:
- Pesos del modelo: Los parámetros entrenados de tu red neuronal.
- Controlador del modelo: Un script en Python que define cómo cargar el modelo y procesar las solicitudes.
- Configuración del modelo: Cualquier archivo o metadato adicional necesario para la operación del modelo.
TorchServe utiliza este archivo como un punto de referencia único al cargar y ejecutar el modelo, lo que simplifica el proceso de implementación y asegura que todos los componentes necesarios estén empaquetados juntos.
Paso 2: Crear el archivo de modelo utilizando torch-model-archiver
Para facilitar la creación de estos archivos de modelo, TorchServe proporciona una herramienta de línea de comandos llamada torch-model-archiver
. Esta utilidad simplifica el proceso de empaquetar tus modelos PyTorch y los archivos asociados en el formato requerido .mar
.
La herramienta torch-model-archiver
requiere dos entradas principales:
- state_dict del modelo: Esta es la forma serializada de los parámetros de tu modelo, normalmente guardada como un archivo
.pth
o.pt
. - Archivo de controlador: Un script en Python que define cómo TorchServe debe interactuar con tu modelo, incluyendo métodos para preprocesar entradas, ejecutar inferencia y posprocesar salidas.
Además, puedes incluir otros archivos necesarios como etiquetas de clase, archivos de configuración o cualquier otro recurso requerido para la operación de tu modelo.
Al usar torch-model-archiver
, te aseguras de que todos los componentes estén empaquetados correctamente y listos para la implementación con TorchServe, promoviendo consistencia y facilidad de uso en diferentes entornos.
Comando para crear el archivo .mar
:
# Archive the ResNet18 model for TorchServe
torch-model-archiver \
--model-name resnet18 \ # Model name
--version 1.0 \ # Version number
--model-file model.py \ # Path to model definition (if needed)
--serialized-file resnet18.pth \ # Path to saved weights
--handler handler.py \ # Path to custom handler (if any)
--export-path model_store \ # Output directory
--extra-files index_to_name.json # Additional files like class labels
4.5.4 Iniciar el servidor de modelos TorchServe
Una vez que el archivo de modelo se ha creado, puedes iniciar TorchServe para desplegar el modelo. Este proceso implica inicializar el servidor de TorchServe, que actúa como un entorno de ejecución para tus modelos PyTorch. TorchServe carga el archivo de modelo (.mar) que has creado, configura los puntos de acceso necesarios para la inferencia y gestiona el ciclo de vida del modelo.
Cuando inicias TorchServe, realiza varias acciones clave:
- Carga el modelo desde el archivo .mar en la memoria.
- Inicializa cualquier controlador personalizado que hayas definido.
- Configura puntos de acceso API REST para la gestión del modelo y la inferencia.
- Prepara el modelo para su servicio, asegurándose de que esté listo para manejar solicitudes entrantes.
Este paso de implementación es crucial, ya que convierte tu modelo de un archivo estático a un servicio activo y accesible, capaz de procesar solicitudes de inferencia en tiempo real. Una vez que TorchServe está en funcionamiento con tu modelo, está listo para aceptar y responder a solicitudes de predicciones, llevando efectivamente tu modelo de machine learning a un estado listo para producción.
Paso 3: Iniciar TorchServe
torchserve --start --model-store model_store --models resnet18=resnet18.mar
Aquí tienes un desglose del comando:
torchserve
: Este es el comando principal para ejecutar TorchServe.-start
: Esta bandera indica a TorchServe que inicie el servidor.-model-store model_store
: Esto especifica el directorio donde se almacenan tus archivos de modelo (.mar). En este caso, es un directorio llamado "model_store".-models resnet18=resnet18.mar
: Esto le indica a TorchServe qué modelos cargar. Aquí, está cargando un modelo ResNet-18 desde un archivo llamado "resnet18.mar".
Cuando ejecutas este comando, TorchServe se iniciará, cargará el modelo ResNet-18 especificado desde el archivo .mar en el almacén de modelos y lo pondrá disponible para servir predicciones a través de una API.
4.5.5 Realizar predicciones a través de la API
Una vez que el modelo se ha desplegado, puedes enviar solicitudes de inferencia a la API para obtener predicciones en tiempo real. Este paso es crucial, ya que te permite utilizar tu modelo entrenado en aplicaciones prácticas. A continuación se explica este proceso en más detalle:
- Punto de acceso API: TorchServe crea un punto de acceso API REST para tu modelo. Este punto de acceso generalmente está disponible en una URL como http://localhost:8080/predictions/[model_name].
- Formato de solicitud: Puedes enviar solicitudes HTTP POST a este punto de acceso. El cuerpo de la solicitud generalmente contiene los datos de entrada (por ejemplo, un archivo de imagen para tareas de clasificación de imágenes) sobre los que deseas realizar predicciones.
- Procesamiento en tiempo real: Cuando envías una solicitud, TorchServe la procesa en tiempo real. Utiliza el modelo desplegado para generar predicciones basadas en los datos de entrada.
- Respuesta: La API devuelve una respuesta que contiene las predicciones del modelo. Esto podría ser probabilidades de clases para una tarea de clasificación, cuadros delimitadores para una tarea de detección de objetos, o cualquier otra salida relevante para el propósito de tu modelo.
- Integración: Este enfoque basado en API permite una fácil integración de tu modelo en varias aplicaciones, sitios web o servicios, lo que te permite aprovechar tu modelo de IA en escenarios del mundo real.
Al utilizar esta API, puedes incorporar sin problemas las capacidades de tu modelo PyTorch en tu ecosistema de software más amplio, convirtiéndolo en una herramienta poderosa para implementar funciones y características impulsadas por IA.
Paso 4: Enviar una solicitud de predicción a la API de TorchServe
import requests
import json
from PIL import Image
import io
def predict_image(image_path, model_name, server_url):
"""
Send an image to TorchServe for prediction.
Args:
image_path (str): Path to the image file
model_name (str): Name of the model to use for prediction
server_url (str): Base URL of the TorchServe server
Returns:
dict: Prediction results
"""
# Prepare the image file for prediction
with open(image_path, 'rb') as file:
image_data = file.read()
# Prepare the request
url = f"{server_url}/predictions/{model_name}"
files = {'data': ('image.jpg', image_data)}
try:
# Send a POST request to the model's endpoint
response = requests.post(url, files=files)
response.raise_for_status() # Raise an exception for bad status codes
# Parse and return the prediction result
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error occurred: {e}")
return None
# Example usage
if __name__ == "__main__":
image_path = 'test_image.jpg'
model_name = 'resnet18'
server_url = 'http://localhost:8080'
result = predict_image(image_path, model_name, server_url)
if result:
print("Prediction Result:")
print(json.dumps(result, indent=2))
else:
print("Failed to get prediction.")
Este ejemplo de código proporciona un enfoque integral para realizar predicciones utilizando TorchServe. A continuación, se detalla cada uno de los componentes clave:
- Definición de la función:
- Definimos una función
predict_image
que encapsula el proceso de predicción. - Esta función toma tres parámetros: la ruta al archivo de imagen, el nombre del modelo y la URL del servidor TorchServe.
- Definimos una función
- Preparación de la imagen:
- El archivo de imagen se lee como datos binarios, lo que es más eficiente que abrirlo como un objeto PIL Image.
- Preparación de la solicitud:
- Construimos la URL completa para el punto de acceso de predicción utilizando la URL del servidor y el nombre del modelo.
- Los datos de la imagen se preparan como un archivo para ser enviados en la solicitud POST.
- Manejo de errores:
- El código utiliza un bloque try-except para manejar posibles errores durante la solicitud.
- Se usa
raise_for_status()
para capturar cualquier error HTTP.
- Procesamiento de la respuesta:
- La respuesta en formato JSON del servidor se devuelve si la solicitud es exitosa.
- Ejecución principal:
- El script incluye un bloque de ejecución condicional principal.
- Demuestra cómo utilizar la función
predict_image
con parámetros de ejemplo.
- Visualización de resultados:
- Si se obtiene una predicción correctamente, se imprime en una estructura JSON formateada para mejorar la legibilidad.
- Si la predicción falla, se muestra un mensaje de error.
Este ejemplo ofrece un manejo de errores robusto, mayor flexibilidad mediante la parametrización y una estructura más clara que aísla la funcionalidad central en una función reutilizable. Está mejor adaptado para la integración en proyectos más grandes y proporciona una base sólida para el desarrollo futuro o la personalización.
4.5.6 Monitorización y gestión de modelos con TorchServe
TorchServe ofrece una suite completa de características para monitorear y gestionar tus modelos desplegados, mejorando tu capacidad para mantener y optimizar tu infraestructura de machine learning:
- Métricas: TorchServe proporciona métricas detalladas de rendimiento accesibles a través del punto de acceso
/metrics
. Estas métricas incluyen:- Latencia: Mide el tiempo que tarda tu modelo en procesar solicitudes, ayudándote a identificar y solucionar cuellos de botella en el rendimiento.
- Rendimiento: Rastrea el número de solicitudes que tu modelo puede manejar por unidad de tiempo, lo que es crucial para la planificación de la capacidad y las decisiones de escalado.
- Utilización de la GPU: Para modelos que se ejecutan en GPUs, monitorea el uso de recursos para asegurar un rendimiento óptimo.
- Tasas de solicitud: Analiza la frecuencia de las solicitudes entrantes para entender los patrones de uso y los momentos de mayor actividad.
Estas métricas permiten tomar decisiones basadas en datos para la optimización del modelo y la planificación de la infraestructura.
- Escalado: Las capacidades de escalado de TorchServe están diseñadas para manejar cargas variables en entornos de producción:
- Escalado horizontal: Despliega múltiples instancias del mismo modelo en diferentes servidores para distribuir la carga de trabajo.
- Escalado vertical: Ajusta los recursos (CPU, GPU, memoria) asignados a cada instancia del modelo según la demanda.
- Autoescalado: Implementa reglas de autoescalado predictivo o basado en reglas para ajustar dinámicamente el número de instancias del modelo en función de los patrones de tráfico.
- Balanceo de carga: Distribuye eficientemente las solicitudes entrantes entre múltiples instancias del modelo para asegurar una utilización óptima de los recursos.
Estas características de escalado permiten que tu despliegue maneje sin problemas escenarios de alto tráfico y mantenga un rendimiento consistente bajo cargas variables.
- Registros: El sistema de registro de TorchServe es una herramienta poderosa para monitorear y solucionar problemas en tus modelos desplegados:
- Registros de errores: Captura y clasifica errores que ocurren durante la inferencia del modelo, ayudando a identificar y resolver problemas rápidamente.
- Registros de solicitudes: Rastrea solicitudes individuales, incluyendo los datos de entrada y las respuestas del modelo, útiles para depuración y auditoría.
- Registros del sistema: Monitorea eventos a nivel del servidor, como la carga o descarga de modelos y cambios de configuración.
- Registro personalizado: Implementa registros personalizados dentro de tus controladores de modelo para capturar información específica de la aplicación.
- Agregación de registros: Integra con herramientas de gestión de registros para la recolección y análisis centralizados de registros en múltiples instancias.
Estos registros exhaustivos proporcionan información invaluable para mantener la salud y el rendimiento de tus modelos desplegados.
Al aprovechar estas funciones avanzadas, puedes garantizar que tu implementación de TorchServe sea robusta, escalable y fácil de gestionar en entornos de producción.