Ir al contenido

Cómo exportarPyTorch YOLO con Ultralytics

La implementación PyTorch en producción suele implicar tener que utilizar un exportador diferente para cada destino: torch.onnx.export para ONNX, coremltools para dispositivos Apple, onnx2tf para TensorFlow, pnnx para NCNN, y así sucesivamente. Cada herramienta tiene su propia API, sus peculiaridades en cuanto a dependencias y sus propias convenciones de salida.

Ultralytics utilidades de exportación independientes que integran varios backends en una única interfaz unificada. Puedes exportar cualquier torch.nn.Module, entre otros timm modelos de imagen, torchvision clasificadores y detectores, o tus propias arquitecturas personalizadas, para ONNX, TorchScript, OpenVINO, CoreML, NCNN, PaddlePaddle, MNN, ExecuTorch, y TensorFlow SavedModel sin tener que aprender cada backend por separado.

¿Por qué utilizar Ultralytics YOLO ?

  • Una sola API para 10 formatos: aprende una única forma de llamar a la API en lugar de una docena.
  • Superficie de uso común: los auxiliares de exportación se encuentran en ultralytics.utils.export, por lo que, una vez instalados los paquetes de backend, podrás mantener el mismo patrón de llamada en todos los formatos.
  • La misma ruta de código que YOLO : todasYOLO Ultralytics se basan en los mismos componentes auxiliares.
  • Cuantificación FP16 e INT8 integrada para los formatos que la admiten (OpenVINO, CoreML, MNN, NCNN).
  • Funciona en CPU: no GPU para el proceso de exportación en sí, por lo que puedes ejecutarlo localmente en cualquier ordenador portátil.

Inicio rápido

La forma más rápida es realizar una exportación de dos líneas a ONNX sin YOLO y sin necesidad de configuración adicional pip install ultralytics onnx timm:

import timm
import torch

from ultralytics.utils.export import torch2onnx

model = timm.create_model("resnet18", pretrained=True).eval()
torch2onnx(model, torch.randn(1, 3, 224, 224), output_file="resnet18.onnx")

Formatos de exportación admitidos

El torch2* las funciones admiten un torch.nn.Module y un tensor de entrada de ejemplo. MNN, TF SavedModel y TF Graph pasan por un artefacto intermedio ONNX Keras. En ninguno de los dos casos se requieren atributos YOLO.

FormatoFunciónInstalarSalida
ONNXtorch2onnx()pip install onnx.onnx archivo
TorchScripttorch2torchscript()incluido en PyTorch.torchscript archivo
OpenVINOtorch2openvino()pip install openvino_openvino_model/ directorio
CoreMLtorch2coreml()pip install coremltools.mlpackage
TF SavedModelonnx2saved_model()Consulte los requisitos detallados a continuación_saved_model/ directorio
Gráfico TFkeras2pb()Consulte los requisitos detallados a continuación.pb archivo
NCNNtorch2ncnn()pip install ncnn pnnx_ncnn_model/ directorio
MNNonnx2mnn()pip install MNN.mnn archivo
PaddlePaddletorch2paddle()pip install paddlepaddle x2paddle_paddle_model/ directorio
ExecuTorchtorch2executorch()pip install executorch_executorch_model/ directorio

ONNX formato intermedio

MNN, TF SavedModely las exportaciones TF Graph pasan por ONNX paso intermedio. Exporta ONNX a ONNX y, a continuación, convierte.

Incorporación de metadatos

Varias funciones de exportación admiten un parámetro opcional metadata diccionario (p. ej., torch2torchscript(..., metadata={"author": "me"})) que incorpora pares clave-valor personalizados en el artefacto exportado, siempre que el formato lo permita.

Ejemplos paso a paso

Todos los ejemplos que se muestran a continuación utilizan la misma configuración: una red ResNet-18 preentrenada de timm en modo de evaluación:

import timm
import torch

model = timm.create_model("resnet18", pretrained=True).eval()
im = torch.randn(1, 3, 224, 224)

Llama siempre model.eval() antes de exportar

Abandono escolar, normalización por lotes, y otras capas exclusivas del entrenamiento se comportan de manera diferente durante la inferencia. Saltar .eval() genera exportaciones con resultados incorrectos.

Exportar a ONNX

from ultralytics.utils.export import torch2onnx

torch2onnx(model, im, output_file="resnet18.onnx")

Para un tamaño de lote dinámico, pasa un dynamic diccionario:

torch2onnx(model, im, output_file="resnet18_dyn.onnx", dynamic={"images": {0: "batch_size"}})

El opset predeterminado es 14 y el nombre predeterminado del campo de entrada es "images". Sobrescribir con el opset, input_names, o output_names argumentos.

Exportar a TorchScript

No se necesitan dependencias adicionales. Usos torch.jit.trace por dentro.

from ultralytics.utils.export import torch2torchscript

torch2torchscript(model, im, output_file="resnet18.torchscript")

Exportar a OpenVINO

from ultralytics.utils.export import torch2openvino

ov_model = torch2openvino(model, im, output_dir="resnet18_openvino_model")

El directorio contiene un archivo con nombre fijo model.xml y model.bin par:

resnet18_openvino_model/
├── model.xml
└── model.bin

Pasar dynamic=True para formas de entrada dinámicas, half=True para FP16, o int8=True para la cuantificación INT8. Además, INT8 requiere un calibration_dataset argumento.

Requerir openvino>=2024.0.0 (o >=2025.2.0 en macOS 15.4 y versiones posteriores) y torch>=2.1.

Exportar a CoreML

import coremltools as ct

from ultralytics.utils.export import torch2coreml

inputs = [ct.TensorType("input", shape=(1, 3, 224, 224))]
ct_model = torch2coreml(model, inputs, im, output_file="resnet18.mlpackage")

Para clasificación modelos, pasa una lista de nombres de clases a classifier_names para añadir una categoría de clasificación al CoreML .

Requerir coremltools>=9.0, torch>=1.11, y numpy<=2.3.5. No compatible con Windows.

BlobWriter not loaded Error

coremltools>=9.0 Es compatible con Python .10–3.13 en macOS y Linux. En Python más recientes Python , la extensión nativa en C no se carga. Utiliza Python .10–3.13 para CoreML .

Exportar a TensorFlow SavedModel

SavedModel TF SavedModel pasa por ONNX paso intermedio:

from ultralytics.utils.export import onnx2saved_model, torch2onnx

torch2onnx(model, im, output_file="resnet18.onnx")
keras_model = onnx2saved_model("resnet18.onnx", output_dir="resnet18_saved_model")

La función devuelve un modelo de Keras y también genera TFLite (.tflite) dentro del directorio de salida:

resnet18_saved_model/
├── saved_model.pb
├── variables/
├── resnet18_float32.tflite
├── resnet18_float16.tflite
└── resnet18_int8.tflite

Requisitos:

  • tensorflow>=2.0.0,<=2.19.0
  • onnx2tf>=1.26.3,<1.29.0
  • tf_keras<=2.19.0
  • sng4onnx>=1.0.1
  • onnx_graphsurgeon>=0.3.26 (instalar con --extra-index-url https://pypi.ngc.nvidia.com)
  • ai-edge-litert>=1.2.0,<1.4.0 en macOS (ai-edge-litert>=1.2.0 (en otras plataformas)
  • onnxslim>=0.1.71
  • onnx>=1.12.0,<2.0.0
  • protobuf>=5

Exportar a un gráfico TensorFlow

A continuación de la SavedModel anterior, convierte el modelo de Keras obtenido en un modelo congelado .pb gráfico:

from pathlib import Path

from ultralytics.utils.export import keras2pb

keras2pb(keras_model, output_file=Path("resnet18_saved_model/resnet18.pb"))

Exportar a NCNN

from ultralytics.utils.export import torch2ncnn

torch2ncnn(model, im, output_dir="resnet18_ncnn_model")

El directorio contiene archivos «param» y «bin» con nombres fijos, además de un Python :

resnet18_ncnn_model/
├── model.ncnn.param
├── model.ncnn.bin
└── model_ncnn.py

torch2ncnn() comprueba si ncnn y pnnx la primera vez que se utilice.

Exportar a MNN

La exportación de MNN requiere un ONNX como entrada. Exporta ONNX a ONNX y, a continuación, convierte:

from ultralytics.utils.export import onnx2mnn, torch2onnx

torch2onnx(model, im, output_file="resnet18.onnx")
onnx2mnn("resnet18.onnx", output_file="resnet18.mnn")

Compatible con half=True para FP16 y int8=True para la cuantificación INT8. Requiere MNN>=2.9.6 y torch>=1.10.

Exportar a PaddlePaddle

from ultralytics.utils.export import torch2paddle

torch2paddle(model, im, output_dir="resnet18_paddle_model")

El directorio contiene los archivos PaddlePaddle y parámetros de PaddlePaddle :

resnet18_paddle_model/
├── model.pdmodel
└── model.pdiparams

Requerir x2paddle y la PaddlePaddle correcta PaddlePaddle para tu plataforma:

  • paddlepaddle-gpu>=3.0.0,<3.3.0 en CUDA
  • paddlepaddle==3.0.0 en CPU ARM64
  • paddlepaddle>=3.0.0,<3.3.0 en otras CPU

No es compatible con NVIDIA .

Exportar a ExecuTorch

from ultralytics.utils.export import torch2executorch

torch2executorch(model, im, output_dir="resnet18_executorch_model")

El archivo exportado .pte El archivo se guarda en el directorio de salida:

resnet18_executorch_model/
└── model.pte

Requerir torch>=2.9.0 y un tiempo de ejecución de ExecuTorch compatible (pip install executorch). Para obtener información sobre su uso en tiempo de ejecución, consulte el Integración con ExecuTorch.

Comprueba el modelo exportado

Después de la exportación, comprueba la paridad numérica con el PyTorch original PyTorch antes de la entrega. Una prueba rápida con ONNXBackend de ultralytics.nn.backends compara los resultados y señala los errores de trazado o cuantificación en una fase temprana:

import numpy as np
import timm
import torch

from ultralytics.nn.backends import ONNXBackend

model = timm.create_model("resnet18", pretrained=True).eval()
im = torch.randn(1, 3, 224, 224)
with torch.no_grad():
    pytorch_output = model(im).numpy()

onnx_model = ONNXBackend("resnet18.onnx", device=torch.device("cpu"))
onnx_output = onnx_model.forward(im)[0]

diff = np.abs(pytorch_output - onnx_output).max()
print(f"Max difference: {diff:.6f}")  # should be < 1e-5

Diferencia prevista

En las exportaciones FP32, la diferencia absoluta máxima debe ser inferior a 1e-5. Las diferencias más grandes indican operaciones no admitidas, una forma de entrada incorrecta o un modelo que no está en modo de evaluación. Las exportaciones en FP16 e INT8 tienen tolerancias más amplias. Comprueba la validez con datos reales en lugar de tensores aleatorios.

En otros entornos de ejecución, el tensor de entrada puede variar. OpenVINO, por ejemplo, utiliza el nombre del argumento de propagación del modelo (normalmente x (para modelos genéricos), mientras que torch2onnx por defecto es "images".

Limitaciones Conocidas

  • La compatibilidad con múltiples entradas es desigual: torch2onnx y torch2openvino aceptar una tupla o una lista de tensores de ejemplo para modelos con múltiples entradas. torch2torchscript, torch2coreml, torch2ncnn, torch2paddle, y torch2executorch suponer un único tensor de entrada.
  • ExecuTorch necesita flatc: El entorno de ejecución de ExecuTorch requiere el compilador FlatBuffers. Instálalo con brew install flatbuffers en macOS o apt install flatbuffers-compiler en Ubuntu.
  • No se extraen conclusiones a través de Ultralytics:YOLO y que se hayan exportado no se pueden volver a cargar a través de YOLO() para la inferencia. Utiliza el tiempo de ejecución nativo de cada formato (ONNX Runtime, OpenVINO, etc.).
  • FormatosYOLO: las exportaciones de Axelera y Sony IMX500 requieren atributos de modelo YOLO y no están disponibles para modelos genéricos.
  • Formatos específicos para cada plataforma: TensorRT Requiere unaGPU NVIDIA . RKNN requiere el rknn-toolkit2 SDK (solo para Linux). Edge TPU requiere el edgetpu_compiler binario (solo para Linux).

Preguntas frecuentes

¿Qué modelos puedo exportar con Ultralytics?

Cualquiera torch.nn.Module. Esto incluye modelos de timm, torchvision o cualquier PyTorch personalizado PyTorch . El modelo debe estar en modo de evaluación (model.eval()) antes de la exportación. ONNX OpenVINO admiten OpenVINO una tupla de tensores de ejemplo para modelos con múltiples entradas.

¿Qué formatos de exportación funcionan sin una GPU?

Todos los formatos compatibles (TorchScript, ONNX, OpenVINO, CoreML, TF SavedModel, TF Graph, NCNN, PaddlePaddle, MNN, ExecuTorch) se pueden exportar en CPU. No GPU necesita GPU para el proceso de exportación en sí. TensorRT el único formato que requiere unaGPU NVIDIA .

¿Qué Ultralytics necesito?

Use Ultralytics >=8.4.38, que incluye el ultralytics.utils.export módulo y el estándar output_file/output_dir argumentos.

¿Puedo exportar un modelo de Torchvision a CoreML iOS ?

Sí. Los clasificadores, detectores y modelos de segmentación de TorchVision se exportan a .mlpackage a través de torch2coreml. En el caso de los modelos de clasificación de imágenes, pasa una lista de nombres de clases a classifier_names para procesar en un clasificador. Ejecuta la exportación en macOS o Linux. CoreML no CoreML compatible con Windows. Consulta la CoreML para obtener más información sobre iOS .

¿Puedo cuantificar mi modelo exportado a INT8 o FP16?

Sí, para varios formatos. Aceptar half=True para FP16 o int8=True para INT8 al exportar a OpenVINO, CoreML, MNN o NCNN. El formato INT8 en OpenVINO requiere OpenVINO un calibration_dataset argumento para cuantificación posterior al entrenamiento. Consulte la página de integración de cada formato para conocer las ventajas e inconvenientes de la cuantización.



📅 Creado hace 0 días ✏️ Actualizado hace 0 días
raimbekovm

Comentarios