Exportar para el despliegue
Exporta best.pt a ONNX, OpenVINO, TensorRT, CoreML, LiteRT o QNN y, antes de desplegarlo, demuestra que la exportación coincide con el modelo PyTorch.
Tu best.pt necesita Python y PyTorch para funcionar; los móviles, los navegadores, los Jetson y los servidores de producción normalmente no disponen de ellos. El modo Export convierte el modelo en un archivo autónomo para esos entornos de ejecución con una sola llamada. El problema es que el hecho de que una exportación se cargue no significa que sea correcta, y una comparación descuidada puede hacer que una exportación correcta parezca defectuosa o esconder los fallos de una defectuosa.
En esta lección exportarás a ONNX el modelo de pastillas, lo ejecutarás con la misma API YOLO, demostrarás que coincide con PyTorch en las cajas y en el mAP de validación con los mismos ajustes y elegirás el formato que necesita tu destino: ONNX, OpenVINO, TensorRT, CoreML, LiteRT o QNN.
Práctico
Ejemplo práctico: exportar a ONNX#

yolo export model=runs/detect/pills_v1/weights/best.pt format=onnxPyTorch: starting from 'runs/detect/pills_v1/weights/best.pt' with input shape (1, 3, 320, 320) BCHW and output shape(s) (1, 5, 2100) (5.2 MB)
ONNX: export success ✅ 0.9s, saved as 'runs/detect/pills_v1/weights/best.onnx' (9.3 MB)
Predict: yolo predict task=detect model=runs/detect/pills_v1/weights/best.onnx imgsz=320
Validate: yolo val task=detect model=runs/detect/pills_v1/weights/best.onnx imgsz=320 data=my_dataset/data.yamlLínea por línea:
input shape (1, 3, 320, 320): una imagen, 3 canales de color y un cuadrado fijo de 320×320: elimgszdel entrenamiento, integrado en el archivo.output shape(s) (1, 5, 2100): 4 valores de caja más 1 puntuación de clase para 2100 cajas candidatas; NMS se ejecuta fuera del grafo de forma predeterminada.9.3 MB: el archivo ONNX almacena pesos FP32, por lo que es más grande que.pten FP16.Predict:/Validate:: comandos listos para el archivo exportado, ya configurados con elimgszadecuado.
Bastan unos pocos argumentos para cubrir la mayoría de los casos; la guía de integración de ONNX enumera los demás.
| Parámetro | Predeterminado | Para qué sirve |
|---|---|---|
imgsz | Tamaño de entrenamiento | Exportar con otro tamaño de entrada fijo, por ejemplo, imgsz=640 |
dynamic | False | Aceptar tamaños de entrada variables en lugar de una única forma fija |
quantize | Ninguno (FP32) | 16 para pesos FP16 (yolo26n.onnx reduce el tamaño de 9,5 MB a 4,8 MB); 8 para INT8 si el formato lo admite |
nms | Ninguno | nms=True integra NMS en el grafo, de modo que el entorno de ejecución devuelve las cajas finales |
Ejemplo práctico: demostrar que la exportación coincide#
La clase YOLO también carga archivos exportados, por lo que el código de predicción anterior funciona sin cambios. Compara ambos archivos con la misma imagen de validación:
from ultralytics import YOLO
image = "my_dataset/images/val/Frame_144.jpg"
pt = YOLO("runs/detect/pills_v1/weights/best.pt")(image, rect=False, verbose=False)[0] # square input, like ONNX
onnx = YOLO("runs/detect/pills_v1/weights/best.onnx")(image, verbose=False)[0]
print(f"pt: {len(pt.boxes)} pills, mean conf {pt.boxes.conf.mean():.3f}")
print(f"onnx: {len(onnx.boxes)} pills, mean conf {onnx.boxes.conf.mean():.3f}")
print(f"max box difference: {(pt.boxes.xyxy - onnx.boxes.xyxy).abs().max():.4f} px")pt: 25 pills, mean conf 0.870
onnx: 25 pills, mean conf 0.870
max box difference: 0.0002 pxMismo recuento, misma confianza y cajas idénticas con una precisión de una fracción de píxel. Ahora, la comprobación más rigurosa: validación en todo el subconjunto:
from ultralytics import YOLO
pt = YOLO("runs/detect/pills_v1/weights/best.pt").val(data="my_dataset/data.yaml", rect=False, verbose=False)
onnx = YOLO("runs/detect/pills_v1/weights/best.onnx").val(data="my_dataset/data.yaml", verbose=False)
print(f".pt mAP50-95 {pt.box.map:.4f}")
print(f".onnx mAP50-95 {onnx.box.map:.4f}").pt mAP50-95 0.6570
.onnx mAP50-95 0.6570Idénticos. (La validación rectangular predeterminada del archivo .pt obtuvo 0,659: una pequeña diferencia debida al relleno de entrada, no a la exportación).
Cuando coincidan, mide el tiempo con yolo benchmark en el dispositivo de destino para conocer su velocidad real antes de desplegarlo.
Elige un formato para tu destino#

| Objetivo | Formato | Notas |
|---|---|---|
| Opción portátil predeterminada: servidores y equipos de escritorio con Linux, Windows y Mac | onnx | ONNX Runtime en CPU o GPU; la exportación más rápida de verificar |
| GPU NVIDIA y Jetson | engine (TensorRT) | La opción más rápida en NVIDIA; exporta en el dispositivo. Consulta Optimiza con TensorRT |
| CPU e iGPU de Intel | openvino | Aceleraciones reales de CPU gracias a los kernels de Intel. Consulta OpenVINO en CPU |
| Aplicaciones para iPhone, iPad y Mac | coreml | Nativo; usa el motor neuronal de Apple |
| Android y otros dispositivos móviles o integrados | litert | Se recomienda INT8 para móviles |
| NPU Snapdragon | qnn | Aceleración Hexagon HTP; pesos INT8 con activaciones de 16 bits de forma predeterminada; elige la arquitectura HTP con name |
| Navegador web | onnx con ONNX Runtime Web | Los modelos más pequeños son viables: n y s |
from ultralytics import YOLO
model = YOLO("runs/detect/pills_v1/weights/best.pt")
model.export(format="onnx") # Multiplataforma: ONNX Runtime
model.export(format="openvino") # CPU / iGPU de Intel
model.export(format="engine", quantize=16) # NVIDIA TensorRT, FP16 (ejecútalo en la GPU de destino)
model.export(format="coreml") # Apple iOS / macOS
model.export(format="litert", quantize=8, data="my_dataset/data.yaml") # Android / edge, INT8
model.export(format="qnn", name="73", data="my_dataset/data.yaml") # NPU Qualcomm Snapdragon (HTP v73); calibra con tus propios datosCada exportación se guarda junto a los pesos: best.onnx, best_openvino_model/, best.engine, etc. Empieza con ONNX aunque acabes usando otro formato: es el más rápido de verificar y sirve como entrada para varias cadenas de herramientas. La guía de opciones de despliegue compara todos los formatos, y Elige un destino de despliegue te guía en la decisión.
La cuantización del modelo sacrifica precisión para reducir el tamaño y aumentar la velocidad. FP16 (quantize=16) reduce el tamaño del archivo a la mitad con una precisión casi idéntica. INT8 (quantize=8) reduce aún más el tamaño y aumenta la velocidad, pero necesita imágenes de calibración: fotogramas representativos que se procesan durante la exportación para elegir los rangos de valores; Ultralytics recomienda al menos 300. Valida siempre un modelo INT8 antes de ponerlo en producción: la pérdida puede ser insignificante o considerable, según el modelo y el conjunto de calibración.
Evita estos errores#
Síntoma: el modelo .pt detecta 35 pastillas en Frame_144.jpg y el archivo ONNX detecta 25; parece que la exportación está rota. Causa: la inferencia de PyTorch rellena cada imagen hasta el rectángulo más pequeño alineado con el stride (192×320 para estos fotogramas de 16:9), mientras que un modelo ONNX estático siempre recibe un cuadrado de 320×320. Las entradas distintas producen detecciones distintas con baja confianza. Solución: al comparar, pasa rect=False al modelo .pt, como en parity.py.
Síntoma: pasas imgsz=640 a best.onnx, pero el registro sigue indicando 320x320. Causa: una exportación estática tiene un único tamaño de entrada, establecido en el momento de la exportación. Solución: exporta con el tamaño que vayas a usar (imgsz=640) o exporta con dynamic=True.
Un .engine creado en una A100 no funcionará en una Jetson Orin y puede que no sobreviva a una actualización de TensorRT. Exporta en el dispositivo de destino y con la versión de TensorRT que vaya a usar. ONNX es portable; los motores no.
Si omites data en una exportación INT8, Ultralytics muestra una advertencia y después calibra con la muestra predeterminada de COCO8: ocho imágenes que no se parecen en nada a tus pastillas. Pasa tu propia muestra: model.export(format="litert", quantize=8, data="my_dataset/data.yaml").
Ya lo has puesto en producción#
Ahora tienes un best.pt entrenado, pruebas de validación junto a una línea de base, un archivo exportado para tu entorno de ejecución y la confirmación de que la exportación coincide con el original. Ese es el ciclo completo —datos, entrenamiento, validación, exportación y despliegue—, y los equipos de producción lo ejecutan según un calendario. Ultralytics YOLO en producción parte de tu exportación verificada y abarca entornos de ejecución optimizados, flujos de trabajo de seguimiento, servicio de varios flujos y supervisión.
Mostrar solución
from ultralytics import YOLO
# Train
model = YOLO("yolo26n.pt")
model.train(data="my_dataset/data.yaml", epochs=10, imgsz=320, name="pills_e2e")
# Validate
metrics = model.val()
print(f"mAP50-95 = {metrics.box.map:.3f}") # 0.659
# Export
model.export(format="onnx")parity.py: pt 25 pills, onnx 25 pills, max box difference 0.0002 px
without rect: pt 35 pills (192x320 input) vs onnx 25 (320x320): input mismatch, not an export bug
val_export.py: .pt 0.6570, .onnx 0.6570
Target: Intel laptop CPU -> openvino, for faster CPU inference than ONNX Runtime