Como exportar modelos PyTorch não-YOLO com Ultralytics#
A Ultralytics disponibiliza utilitários de exportação independentes em ultralytics.utils.export que encapsulam vários backends sob uma única interface consistente. Podes exportar qualquer torch.nn.Module, incluindo modelos de imagem timm, classificadores e detetores torchvision, ou as tuas próprias arquiteturas personalizadas, para ONNX, TorchScript, OpenVINO, CoreML, NCNN, PaddlePaddle, MNN, ExecuTorch e TensorFlow SavedModel sem precisares de aprender cada backend separadamente.
Implementar modelos PyTorch em produção significa habitualmente gerir um exportador diferente para cada destino: torch.onnx.export para ONNX, coremltools para dispositivos Apple, onnx2tf para TensorFlow, pnnx para NCNN, e assim por diante. Cada ferramenta tem a sua própria API, peculiaridades de dependências e convenções de saída. Estes utilitários consolidam tudo isto num único padrão de chamada.
Por que usar a Ultralytics para exportação não-YOLO?#
- Uma única API para 10 formatos: aprenda uma única convenção de chamada em vez de uma dúzia.
- Superfície de utilitários partilhados: os assistentes de exportação encontram-se em
ultralytics.utils.export, por isso, assim que os pacotes do backend estiverem instalados, podes manter o mesmo padrão de chamada em todos os formatos. - Mesmo caminho de código das exportações YOLO: os mesmos auxiliares impulsionam todas as exportações Ultralytics YOLO.
- Quantização FP16 e INT8 integrada para formatos que a suportam (OpenVINO, CoreML, MNN, NCNN).
- Funciona na CPU: nenhuma GPU é necessária para a etapa de exportação em si, então você pode executá-la localmente em qualquer laptop.
Início Rápido#
O caminho mais rápido é uma exportação de duas linhas para ONNX sem código YOLO e sem nenhuma configuração para além de 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 Exportação Suportados#
As funções torch2* aceitam um torch.nn.Module padrão e um tensor de entrada de exemplo. O MNN, o TF SavedModel e o TF Frozen Graph passam por um artefacto intermediário ONNX ou Keras. Não são necessários atributos específicos do YOLO em nenhum dos casos.
| Formato | Função | Instalar | Saída |
|---|---|---|---|
| ONNX | torch2onnx() | pip install onnx | Ficheiro .onnx |
| TorchScript | torch2torchscript() | incluído com PyTorch | Ficheiro .torchscript |
| OpenVINO | torch2openvino() | pip install openvino | Diretório _openvino_model/ |
| CoreML | torch2coreml() | pip install coremltools | .mlpackage |
| TF SavedModel | onnx2saved_model() | ver requisitos detalhados abaixo | Diretório _saved_model/ |
| TF Frozen Graph | keras2pb() | ver requisitos detalhados abaixo | Ficheiro .pb |
| NCNN | torch2ncnn() | pip install ncnn pnnx | Diretório _ncnn_model/ |
| MNN | onnx2mnn() | pip install MNN | Ficheiro .mnn |
| PaddlePaddle | torch2paddle() | pip install paddlepaddle x2paddle | Diretório _paddle_model/ |
| ExecuTorch | torch2executorch() | pip install executorch | Diretório _executorch_model/ |
As exportações para MNN, TF SavedModel e TF Frozen Graph passam pelo ONNX como um passo intermediário. Exporta primeiro para ONNX e depois converte.
Várias funções de exportação aceitam um dicionário metadata opcional (por exemplo, torch2torchscript(..., metadata={"author": "me"})) que incorpora pares chave-valor personalizados no artefacto exportado, caso o formato o suporte.
Exemplos passo a passo#
Cada exemplo abaixo usa a mesma configuração, uma ResNet-18 pré-treinada do timm em modo de avaliação:
import timm
import torch
model = timm.create_model("resnet18", pretrained=True).eval()
im = torch.randn(1, 3, 224, 224)O Dropout, a normalização em lote e outras camadas exclusivas de treino comportam-se de forma diferente durante a inferência. Omitir .eval() produz exportações com resultados incorretos.
Exportar para ONNX#
from ultralytics.utils.export import torch2onnx
torch2onnx(model, im, output_file="resnet18.onnx")Para um tamanho de lote dinâmico, passa um dicionário dynamic:
torch2onnx(model, im, output_file="resnet18_dyn.onnx", dynamic={"images": {0: "batch_size"}})O opset predefinido é 14 e o nome da entrada predefinido é "images". Podes substituir estes valores com os argumentos opset, input_names ou output_names.
Exportar para TorchScript#
Não são necessárias dependências extra. Utiliza torch.jit.trace internamente.
from ultralytics.utils.export import torch2torchscript
torch2torchscript(model, im, output_file="resnet18.torchscript")Exportar para OpenVINO#
from ultralytics.utils.export import torch2openvino
ov_model = torch2openvino(model, im, output_dir="resnet18_openvino_model")O diretório contém um par model.xml e model.bin de nome fixo:
resnet18_openvino_model/
├── model.xml
└── model.binPassa dynamic=True para formas de entrada dinâmicas, quantize=16 para FP16 ou quantize=8 para quantização INT8. A quantização INT8 requer adicionalmente um argumento calibration_dataset.
Requer openvino>=2024.0.0 (ou >=2025.2.0 no macOS 15.4+) e torch>=2.1.
Exportar para 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, classifier_names=None, output_file="resnet18.mlpackage")Para modelos de classificação, passa uma lista de nomes de classes para classifier_names para adicionar uma cabeça de classificação ao modelo CoreML.
Requer coremltools>=9.0, torch>=1.11 e numpy<=2.3.5. Não suportado no Windows.
O coremltools>=9.0 disponibiliza wheels para Python 3.10–3.13 no macOS e Linux. Em versões mais recentes do Python, a extensão C nativa falha ao carregar. Utiliza o Python 3.10–3.13 para a exportação CoreML.
Exportar para TensorFlow SavedModel#
A exportação para TF SavedModel passa pelo ONNX como um passo intermediário:
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")A função devolve um modelo Keras e também gera ficheiros TFLite (.tflite) dentro do diretório de saída:
resnet18_saved_model/
├── saved_model.pb
├── variables/
├── resnet18_float32.tflite
├── resnet18_float16.tflite
└── resnet18_int8.tfliteRequisitos:
tensorflow>=2.0.0,<=2.19.0onnx2tf>=1.26.3,<1.29.0tf_keras<=2.19.0sng4onnx>=1.0.1onnx_graphsurgeon>=0.3.26ai-edge-litert>=1.2.0,<1.4.0no macOS (ai-edge-litert>=1.2.0noutras plataformas)onnxslim>=0.1.82onnx>=1.12.0,<2.0.0protobuf>=5
Exportar para TensorFlow Frozen Graph#
Continuando a partir da exportação do SavedModel acima, converte o keras_model devolvido num grafo .pb congelado:
from pathlib import Path
from ultralytics.utils.export import keras2pb
keras2pb(keras_model, output_file=Path("resnet18_saved_model/resnet18.pb"))Exportar para NCNN#
from ultralytics.utils.export import torch2ncnn
torch2ncnn(model, im, output_dir="resnet18_ncnn_model")O diretório contém arquivos param e bin de nome fixo, juntamente com um wrapper em Python:
resnet18_ncnn_model/
├── model.ncnn.param
├── model.ncnn.bin
└── model_ncnn.pyO torch2ncnn() verifica a existência de ncnn e pnnx na primeira utilização.
Exportar para MNN#
A exportação MNN requer um arquivo ONNX como entrada. Exporte para ONNX primeiro e, em seguida, converta:
from ultralytics.utils.export import onnx2mnn, torch2onnx
torch2onnx(model, im, output_file="resnet18.onnx")
onnx2mnn("resnet18.onnx", output_file="resnet18.mnn")Suporta quantize=16 para FP16 e quantize=8 para quantização INT8. Requer MNN>=2.9.6 e torch>=1.10.
Exportar para PaddlePaddle#
from ultralytics.utils.export import torch2paddle
torch2paddle(model, im, output_dir="resnet18_paddle_model")O diretório contém o modelo PaddlePaddle e os arquivos de parâmetros:
resnet18_paddle_model/
├── model.pdmodel
└── model.pdiparamsRequer x2paddle e a distribuição PaddlePaddle correta para a tua plataforma:
paddlepaddle-gpu>=3.0.0,<3.3.0em CUDApaddlepaddle==3.0.0em CPU ARM64paddlepaddle>=3.0.0,<3.3.0noutros CPUs
Não suportado em NVIDIA Jetson.
Exportar para ExecuTorch#
from ultralytics.utils.export import torch2executorch
torch2executorch(model, im, output_dir="resnet18_executorch_model")O ficheiro .pte exportado é guardado dentro do diretório de saída:
resnet18_executorch_model/
└── model.pteRequer torch>=2.9.0 e um runtime ExecuTorch correspondente (pip install executorch). Para utilização em runtime, consulta a integração ExecuTorch.
Verifique seu modelo exportado#
Após a exportação, verifica a paridade numérica com o modelo PyTorch original antes de o colocar em produção. Um teste rápido com ONNXBackend de ultralytics.nn.backends compara as saídas e sinaliza precocemente erros de rastreio ou de quantização:
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(im)[0]
diff = np.abs(pytorch_output - onnx_output).max()
print(f"Max difference: {diff:.6f}") # typically ~1e-5, well under 1e-4 for FP32Para exportações FP32, a diferença máxima absoluta ronda habitualmente 1e-5 e deve manter-se bem abaixo de 1e-4. Diferenças maiores apontam para operações não suportadas, formas de entrada incorretas ou um modelo que não está em modo de avaliação. As exportações FP16 e INT8 têm tolerâncias mais amplas. Valida com dados reais em vez de tensores aleatórios.
Para outros runtimes, o nome do tensor de entrada pode diferir. O OpenVINO, por exemplo, utiliza o nome do argumento forward do modelo (habitualmente x para modelos genéricos), enquanto o torch2onnx predefini para "images".
Limitações conhecidas#
- O suporte a múltiplas entradas é irregular:
torch2onnxetorch2openvinoaceitam um tuplo ou lista de tensores de exemplo para modelos com múltiplas entradas.torch2torchscript,torch2coreml,torch2ncnn,torch2paddleetorch2executorchassumem um único tensor de entrada. - O ExecuTorch precisa de
flatc: O runtime do ExecuTorch requer o compilador FlatBuffers. Instala combrew install flatbuffersno macOS ouapt install flatbuffers-compilerno Ubuntu. - Sem inferência através do Ultralytics: Os modelos não YOLO exportados não podem ser carregados de volta através de
YOLO()para inferência. Utiliza o runtime nativo para cada formato (ONNX Runtime, OpenVINO Runtime, etc.). - Formatos exclusivos para YOLO: As exportações para Axelera e Sony IMX500 requerem atributos de modelo específicos do YOLO e não estão disponíveis para modelos genéricos.
- Formatos específicos de plataforma: TensorRT requer uma GPU NVIDIA. RKNN requer o SDK
rknn-toolkit2(apenas Linux). Edge TPU requer o binárioedgetpu_compiler(apenas Linux).
Conclusão#
Estes utilitários transformam qualquer modelo PyTorch, desde um simples torch.nn.Module até um artefacto pronto para produção em ONNX, OpenVINO, CoreML, TensorFlow ou runtime móvel, através de uma única API consistente. Escolhe o formato que corresponde ao teu hardware de destino, verifica a paridade numérica em relação ao modelo original e, em seguida, segue o guia de integração correspondente para os passos de implementação específicos do runtime.
FAQ#
Qualquer
torch.nn.Module. Isto inclui modelos de timm, torchvision ou qualquer modelo PyTorch personalizado. O modelo tem de estar em modo de avaliação (model.eval()) antes da exportação. O ONNX e o OpenVINO aceitam adicionalmente um tuplo de tensores de exemplo para modelos de múltiplas entradas.Todos os formatos suportados (TorchScript, ONNX, OpenVINO, CoreML, TF SavedModel, TF Frozen Graph, NCNN, PaddlePaddle, MNN, ExecuTorch) podem ser exportados via CPU. Nenhuma GPU é necessária para o processo de exportação em si. TensorRT é o único formato que requer uma GPU NVIDIA.
Utiliza o
>=8.4.38da Ultralytics, que inclui o móduloultralytics.utils.exporte os argumentos normalizadosoutput_file/output_dir.Sim. Os classificadores, detetores e modelos de segmentação da torchvision são exportados para
.mlpackageatravés detorch2coreml. Para modelos de classificação de imagens, passa uma lista de nomes de classes paraclassifier_namespara incorporar uma cabeça de classificação. Executa a exportação no macOS ou Linux. O CoreML não é suportado no Windows. Consulta a integração CoreML para obter detalhes de implementação no iOS.Sim, para vários formatos. Passa
quantize=16para FP16 ouquantize=8para INT8 ao exportar para OpenVINO, CoreML, MNN ou NCNN. O INT8 no OpenVINO requer adicionalmente um argumentocalibration_datasetpara quantização pós-treino. Consulta a página de integração de cada formato para conhecer as vantagens e desvantagens da quantização.Executa o modelo PyTorch original e o modelo exportado com a mesma entrada e, em seguida, compara as saídas. Carrega o ficheiro exportado com o backend correspondente (por exemplo,
ONNXBackendpara ONNX) e verifica a diferença máxima absoluta. Para exportações FP32, esta ronda habitualmente1e-5e deve manter-se bem abaixo de1e-4; discrepâncias maiores apontam para operações não suportadas, uma forma de entrada incorreta ou um modelo que não está em modo de avaliação. Consulta Verify Your Exported Model para ver um exemplo executável.