Skip to content

Commit 65e8aa2

Browse files
author
Thiago Crepaldi
committed
Add ONNX tutorial using torch.onnx.dynamo_export API
1 parent 32d8341 commit 65e8aa2

9 files changed

+181
-6
lines changed
Loading

_static/img/onnx/netron_web_ui.png

64.5 KB
Loading
Loading

advanced_source/super_resolution_with_onnxruntime.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,16 @@
22
(optional) Exporting a Model from PyTorch to ONNX and Running it using ONNX Runtime
33
========================================================================
44
5+
.. Note::
6+
As of PyTorch 2.1, there are two versions of ONNX Exporter.
7+
8+
* ``torch.onnx.dynamo_export` is the latest and recommended exporter based on the TorchDynamo and is the default starting from PyTorch 2.1
9+
* ``torch.onnx.export`` is based on TorchScript backend and has been the default until PyTorch 2.0.
10+
511
In this tutorial, we describe how to convert a model defined
6-
in PyTorch into the ONNX format and then run it with ONNX Runtime.
12+
in PyTorch into the ONNX format using the legacy ``torch.onnx.export` ONNX exporter.
713
14+
The exported model will be executed it with ONNX Runtime.
815
ONNX Runtime is a performance-focused engine for ONNX models,
916
which inferences efficiently across multiple platforms and hardware
1017
(Windows, Linux, and Mac and on both CPUs and GPUs).
@@ -15,13 +22,16 @@
1522
For this tutorial, you will need to install `ONNX <https://github.com/onnx/onnx>`__
1623
and `ONNX Runtime <https://github.com/microsoft/onnxruntime>`__.
1724
You can get binary builds of ONNX and ONNX Runtime with
18-
``pip install onnx onnxruntime``.
25+
26+
.. code-block:: bash
27+
%%bash
28+
pip install onnxruntime
29+
1930
ONNX Runtime recommends using the latest stable runtime for PyTorch.
2031
2132
"""
2233

2334
# Some standard imports
24-
import io
2535
import numpy as np
2636

2737
from torch import nn
@@ -185,7 +195,7 @@ def _initialize_weights(self):
185195

186196
import onnxruntime
187197

188-
ort_session = onnxruntime.InferenceSession("super_resolution.onnx")
198+
ort_session = onnxruntime.InferenceSession("super_resolution.onnx", providers=['CPUExecutionProvider'])
189199

190200
def to_numpy(tensor):
191201
return tensor.detach().cpu().numpy() if tensor.requires_grad else tensor.cpu().numpy()
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Export a PyTorch model to ONNX
4+
==============================
5+
6+
**Author**: `Thiago Crepaldi <https://github.com/thiagocrepaldi>`_
7+
8+
.. Note::
9+
As of PyTorch 2.1, there are two versions of ONNX Exporter.
10+
11+
* ``torch.onnx.dynamo_export` is the latest and recommended exporter basedon the TorchDynamo and is the default starting from PyTorch 2.1
12+
* ``torch.onnx.export`` is based on TorchScript backend and has been the default until PyTorch 2.0.
13+
14+
In this tutorial, we describe how to convert a model defined in PyTorch into the ONNX format using
15+
the latest and preferred ``torch.onnx.dynamo_export` ONNX exporter.
16+
17+
"""
18+
19+
###############################################################################
20+
# In the `60 Minute Blitz <https://pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html>`_,
21+
# we had the opportunity to learn about PyTorch at a high level and train a small neural network to classify images.
22+
#
23+
# While PyTorch is great for iterating on the development of models, the resulting models are not typically deployed
24+
# to production in this fashion. This is where `ONNX <https://onnx.ai/>`_ (Open Neural Network Exchange) comes in!
25+
# ONNX is a flexible open standard format for representing machine learning models which standardized representations
26+
# of machine learning that allow them to be executed across a gamut of hardware platforms and runtime environments
27+
# from large-scale cloud-based supercomputers to resource-constrained edge devices such as your web browser and phone.
28+
#
29+
# In this tutorial, we’ll learn how to:
30+
#
31+
# 1. Author a simple image classifier model in PyTorch (from the 60 Minute Blitz tutorial).
32+
# 2. Export the model to ONNX format.
33+
# 3. Save the ONNX model in a file.
34+
# 4. Visualize the ONNX model graph using `Netron <https://github.com/lutzroeder/netron>`_.
35+
# 5. Execute the ONNX model with `ONNX Runtime
36+
#
37+
# Note that because the ONNX exporter uses ``onnx`` and ``onnxscript`` to translate PyTorch operators into ONNX operators,
38+
# we will need to install them.
39+
# %%
40+
# .. code-block:: bash
41+
#
42+
# %%bash
43+
# pip install onnx
44+
# pip install onnxscript
45+
#
46+
# Once your environment is set up, let’s start modeling our image classifier with PyTorch,
47+
# exactly like we did in the 60 Minute Blitz tutorial.
48+
#
49+
50+
import torch
51+
import torch.nn as nn
52+
import torch.nn.functional as F
53+
54+
55+
class Net(nn.Module):
56+
57+
def __init__(self):
58+
super(Net, self).__init__()
59+
# 1 input image channel, 6 output channels, 5x5 square convolution kernel
60+
self.conv1 = nn.Conv2d(1, 6, 5)
61+
self.conv2 = nn.Conv2d(6, 16, 5)
62+
# an affine operation: y = Wx + b
63+
self.fc1 = nn.Linear(16 * 5 * 5, 120) # 5*5 from image dimension
64+
self.fc2 = nn.Linear(120, 84)
65+
self.fc3 = nn.Linear(84, 10)
66+
67+
def forward(self, x):
68+
# Max pooling over a (2, 2) window
69+
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
70+
# If the size is a square, you can specify with a single number
71+
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
72+
x = torch.flatten(x, 1) # flatten all dimensions except the batch dimension
73+
x = F.relu(self.fc1(x))
74+
x = F.relu(self.fc2(x))
75+
x = self.fc3(x)
76+
return x
77+
78+
net = Net()
79+
80+
# Analogous to the 60 Minute Blitz tutorial, we need to create a random 32x32 input.
81+
82+
input = torch.randn(1, 1, 32, 32)
83+
84+
# That is all we need to export the model to ONNX format: a model instance and a dummy input.
85+
# We can now export the model with the following code:
86+
87+
export_output = torch.onnx.dynamo_export(net, input)
88+
89+
# As we can see, we didn't need any code change on our model.
90+
# The resulting ONNX model is saved within ``torch.onnx.ExportOutput`` as a binary protobuf file.
91+
#
92+
# We can save it to disk with the following code:
93+
94+
export_output.save("my_image_classifier.onnx")
95+
96+
# Now that we have our model saved, we can visualize it with `Netron <https://github.com/lutzroeder/netron>`_.
97+
# Netron can either be installed on MacOS, Linux or Windows computers, or run directly from the browser.
98+
# Let's try the web version by opening the following link: https://netron.app/.
99+
#
100+
# .. image:: ../_static/img/onnx/netron_web_ui.png
101+
#
102+
# Once Netron is open, we can drag and drop our ``my_image_classifier.onnx`` file into the browser or select it after
103+
# clicking on `Open model` button.
104+
#
105+
# .. image:: ../_static/img/onnx/image_clossifier_onnx_modelon_netron_web_ui.png
106+
#
107+
# And that is it! We have successfully exported our PyTorch model to ONNX format and visualized it with Netron.
108+
#
109+
# The last step is executing the ONNX model with `ONNX Runtime`, but before we do that, let's install ONNX Runtime.
110+
# %%
111+
# .. code-block:: bash
112+
#
113+
# %%bash
114+
# pip install onnxruntime
115+
116+
# One aspect that wasn't mentioned before was that the exported ONNX Model may have more inputs than the original PyTorch model.
117+
# That can happen for several reasons we are going to explore in future topics, but suffices to say that we can
118+
# adapt PyTorch input to ONNX with a simple API as shown below.
119+
120+
onnx_input = export_output.adapt_torch_inputs_to_onnx(input)
121+
print(f"Input legth: {len(onnx_input)}")
122+
print(f"Sample input: {onnx_input}")
123+
124+
# in our example, the input is the same, but we can have more inputs
125+
# than the original PyTorch model in more complex cases.
126+
# Now we can execute the ONNX model with ONNX Runtime.
127+
128+
import onnxruntime
129+
130+
# We are using CPU as the execution provider, but ``providers=['CUDAExecutionProvider']`` enables CUDA too.
131+
132+
ort_session = onnxruntime.InferenceSession("./my_image_classifier.onnx", providers=['CPUExecutionProvider'])
133+
134+
# ONNX Runtime requires the input to be on CPU and using numpy Tensors,
135+
# so we need to convert our PyTorch input to numpy.
136+
137+
def to_numpy(tensor):
138+
return tensor.detach().cpu().numpy() if tensor.requires_grad else tensor.cpu().numpy()
139+
140+
# ONNX Runtime also requires the input to be a dictionary with
141+
# the keys being the input name and the value the Numpy tensor
142+
143+
onnxruntime_input = {k.name: to_numpy(v) for k, v in zip(ort_session.get_inputs(), onnx_input)}
144+
145+
# Finally, we can execute the ONNX model with ONNX Runtime.
146+
147+
onnxruntime_output = ort_session.run(None, onnxruntime_input)
148+
149+
# The output can be a single tensor or a list of tensors, depending on the model.
150+
151+
print(onnxruntime_output)
152+
153+
# That is about it! We have successfully exported our PyTorch model to ONNX format,
154+
# saved it to disk, and executed it with ONNX Runtime.

en-wordlist.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ NumPy
151151
Numericalization
152152
Numpy's
153153
ONNX
154+
ONNX Runtime
154155
OpenAI
155156
OpenMP
156157
Ornstein

index.rst

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,11 +329,18 @@ What's new in PyTorch tutorials?
329329
:tags: Production,TorchScript
330330

331331
.. customcarditem::
332-
:header: (optional) Exporting a Model from PyTorch to ONNX and Running it using ONNX Runtime
332+
:header: (optional) Exporting a PyTorch model to ONNX using TorchDynamo backend and Running it using ONNX Runtime
333+
:card_description: Build a image classifier model in PyTorch and convert it to ONNX before deploying it with ONNX Runtime.
334+
:image: _static/img/thumbnails/cropped/Exporting-PyTorch-Models-to-ONNX-Graphs.png
335+
:link: beginner/export_simple_model_to_onnx_tutorial.html
336+
:tags: ONNX
337+
338+
.. customcarditem::
339+
:header: (optional) Exporting a PyTorch Model to ONNX using TorchScript backend and Running it using ONNX Runtime
333340
:card_description: Convert a model defined in PyTorch into the ONNX format and then run it with ONNX Runtime.
334341
:image: _static/img/thumbnails/cropped/optional-Exporting-a-Model-from-PyTorch-to-ONNX-and-Running-it-using-ONNX-Runtime.png
335342
:link: advanced/super_resolution_with_onnxruntime.html
336-
:tags: Production
343+
:tags: Production,ONNX
337344

338345
.. Code Transformations with FX
339346

requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ datasets
3333
transformers
3434
torchmultimodal-nightly # needs to be updated to stable as soon as it's avaialable
3535
deep_phonemizer==0.0.17
36+
onnx
37+
onnxscript
38+
onnxruntime
3639

3740
importlib-metadata==6.8.0
3841

0 commit comments

Comments
 (0)