Introduction
ONNX (Open Neural Network Exchange) is an open, framework-agnostic format for representing machine learning models, and ONNX Export is the process of converting a trained PyTorch model into this shared format so it can run on a much broader range of platforms, runtimes, and even other frameworks entirely. While TorchScript (covered in the previous topic) keeps a model within the PyTorch ecosystem — just freed from the Python dependency — ONNX takes portability a step further, enabling a model trained in PyTorch to potentially run in TensorFlow-based tools, specialized inference engines, or hardware-specific accelerators that never need to know PyTorch was involved at all.
ONNX has become a widely adopted standard precisely because it decouples where a model is trained from where it's deployed, letting teams use PyTorch's flexibility for development while deploying through whichever runtime best fits their specific production environment.
Why Does ONNX Export Matter?
ONNX Export helps to:
- Enable a PyTorch model to run in non-PyTorch environments and runtimes
- Provide a standard, shared format supported across many frameworks and tools
- Unlock specialized, highly optimized inference engines (like ONNX Runtime) for faster serving
- Support deployment on specialized hardware accelerators with ONNX-compatible drivers
- Decouple model training decisions from deployment infrastructure decisions
- Serve as a common interchange format between different parts of an ML pipeline or team
Exporting a PyTorch Model to ONNX
Similar to TorchScript's tracing method, ONNX export works by
running the model once with an example input and recording the
resulting computation graph — meaning ONNX export shares the
same important limitation covered in the TorchScript topic:
it can silently produce incorrect results for models containing
data-dependent control flow, since only the executed path gets
captured in the exported graph.Understanding dynamic_axes
By default, an exported ONNX graph "bakes in" the exact shape
of the example input used during export — including the batch
size. Since real-world inference often needs to handle different
batch sizes (a single request vs. a large batch), dynamic_axes
tells the exporter which dimensions should remain flexible
rather than fixed, so the exported model can accept inputs
of varying batch size at inference time.Verifying the Exported Model
Validating the exported model before deployment is an important step, since export issues — especially around dynamic shapes or unsupported operations — are often much easier to catch and debug immediately after export than after the model has already been deployed elsewhere.
Running an ONNX Model with ONNX Runtime
Notice that this code has no dependency on PyTorch at all —
onnxruntime is a separate, highly optimized inference engine
that can load and run the exported .onnx file directly, often
significantly faster than running the equivalent model through
PyTorch's own eager-mode execution, especially in production
serving scenarios.Comparing the Original PyTorch Output to the ONNX Output
Comparing outputs between the original PyTorch model and the exported ONNX version is a critical validation step, catching any subtle discrepancies introduced during the export process before they cause problems in production.
What ONNX Enables Beyond PyTorch
Because ONNX is an open, shared standard (not PyTorch-specific),
an exported .onnx file can potentially be:
- Loaded and run using ONNX Runtime, a fast, cross-platform
inference engine
- Converted for use with other frameworks that support
importing ONNX models
- Deployed to specialized hardware accelerators with
ONNX-compatible support
- Used within tools and platforms built around the ONNX
standard, regardless of whether they have any native
PyTorch integration at allTorchScript vs ONNX Export
| Aspect | TorchScript | ONNX Export |
|---|---|---|
| Ecosystem | Stays within the PyTorch/LibTorch ecosystem | Framework-agnostic, open standard |
| Primary Use Case | Running PyTorch models without Python, still via PyTorch's own runtime | Running models via other runtimes, tools, or hardware |
| Control Flow Handling | Scripting handles it correctly; tracing does not | Shares tracing's limitation — data-dependent control flow can be lost |
| Typical Deployment Target | C++ applications using LibTorch, PyTorch Mobile | ONNX Runtime, specialized hardware, or other frameworks |
| Conversion Method | Tracing or scripting | Primarily tracing-based export |
When to Choose ONNX vs TorchScript
| Scenario | Better Choice |
|---|---|
| Deploying with LibTorch in a C++ application | TorchScript |
| Needing maximum cross-framework/tool compatibility | ONNX Export |
| Model has significant data-dependent control flow | TorchScript (via scripting) |
| Deploying to specialized hardware with ONNX support | ONNX Export |
| Wanting to use ONNX Runtime's optimized inference engine | ONNX Export |
Key Properties of ONNX Export
- ONNX is an open, framework-agnostic format for representing machine learning models.
- Exporting to ONNX, like tracing, captures the computation graph from one example run of the model.
dynamic_axesmust be specified to allow the exported model to handle varying input shapes, like batch size.- ONNX Runtime provides a fast, PyTorch-independent way to run exported models in production.
- Comparing PyTorch and ONNX outputs directly after export is an important validation step.
Where Is ONNX Export Used?
| Field | Application |
|---|---|
| Cross-Framework Deployment | Running a PyTorch-trained model in a non-PyTorch serving environment |
| High-Performance Inference Serving | Leveraging ONNX Runtime's optimizations for faster production inference |
| Hardware-Accelerated Deployment | Running models on specialized chips with ONNX support |
| Multi-Team ML Pipelines | Providing a standard interchange format between data science and deployment teams |
| Edge and Embedded Deployment | Running optimized ONNX models on resource-constrained devices |
Advantages
- Enables deployment across a much broader range of platforms and tools than PyTorch alone
- ONNX Runtime often provides significant inference speed improvements over eager-mode PyTorch
- Decouples model training framework choice from deployment infrastructure choice
- Widely adopted, open standard with strong industry and tooling support
- Supports validation tools to check model correctness before deployment
Limitations
- Shares tracing's limitation around data-dependent control flow, since export is trace-based
- Not every custom PyTorch operation has a direct, supported ONNX equivalent
- Requires careful configuration (like
dynamic_axes) to handle real-world variable input shapes correctly - Adds an additional validation step to confirm exported behavior matches the original model
- Debugging export failures can require understanding both PyTorch's and ONNX's internal representations
Real-World Examples
| Application | ONNX Export Use |
|---|---|
| Cross-Platform Model Serving | Deploying a single exported model across multiple different runtime environments |
| High-Throughput Inference APIs | Using ONNX Runtime to serve predictions faster than native PyTorch |
| Hardware-Accelerated Edge Devices | Running ONNX-optimized models on specialized inference chips |
| Multi-Framework ML Teams | Sharing models between teams using different primary frameworks |
| Model Interoperability Research | Studying how models transfer and perform across different runtime engines |
Best Practices
- Always set
model.eval()before exporting to ensure correct layer behavior (e.g., Dropout, BatchNorm) is captured. - Use
dynamic_axesto support realistic, variable input shapes like batch size at inference time. - Validate the exported model with
onnx.checker.check_model()before deploying it anywhere. - Compare PyTorch and ONNX outputs directly on representative inputs to confirm the export preserved correct behavior.
- Be aware of the same data-dependent control flow limitations that apply to tracing-based TorchScript export.
Interview Tip
A common interview question is:
"Why would you export a PyTorch model to ONNX instead of just using TorchScript, and what's a key limitation both approaches share?"
A strong answer is:
I'd export to ONNX specifically when I need to deploy a model outside the PyTorch ecosystem entirely — for example, running it through ONNX Runtime for optimized inference performance, deploying to specialized hardware with ONNX support, or integrating with tools and frameworks that have no native PyTorch dependency at all. TorchScript, by contrast, keeps the model within PyTorch's own runtime (LibTorch), which is the better choice for C++ deployment specifically using PyTorch's ecosystem. Both approaches share a key limitation, though: since ONNX export and TorchScript's tracing method both work by recording operations from a single example execution, they can silently produce incorrect results for models with data-dependent control flow, since only the branch actually taken during that example gets captured in the resulting graph.
Explaining the shared tracing limitation ties this topic directly back to the previous one, showing connected understanding.
Conclusion
ONNX Export provides a framework-agnostic path for deploying PyTorch models across a broad range of runtimes, tools, and hardware, trading some of tracing's control-flow limitations for significantly wider deployment flexibility than TorchScript alone. With both major deployment paths — TorchScript and ONNX Export — now covered, the final topic in this section, Save/Load Models, addresses the more everyday, general-purpose task of persisting and restoring PyTorch models for continued use within the PyTorch ecosystem itself.