diff --git a/.jenkins/validate_tutorials_built.py b/.jenkins/validate_tutorials_built.py index e02ea6028f7..4a9d0c4a118 100644 --- a/.jenkins/validate_tutorials_built.py +++ b/.jenkins/validate_tutorials_built.py @@ -25,7 +25,6 @@ "intermediate_source/mnist_train_nas", # used by ax_multiobjective_nas_tutorial.py "intermediate_source/fx_conv_bn_fuser", "intermediate_source/_torch_export_nightly_tutorial", # does not work on release - "advanced_source/super_resolution_with_onnxruntime", "advanced_source/usb_semisup_learn", # fails with CUDA OOM error, should try on a different worker "prototype_source/fx_graph_mode_ptq_dynamic", "prototype_source/vmap_recipe", diff --git a/_static/img/cat_224x224.jpg b/_static/img/cat_224x224.jpg deleted file mode 100755 index 05660ce53f9..00000000000 Binary files a/_static/img/cat_224x224.jpg and /dev/null differ diff --git a/_static/img/cat_resized.jpg b/_static/img/cat_resized.jpg deleted file mode 100644 index c7746e65308..00000000000 Binary files a/_static/img/cat_resized.jpg and /dev/null differ diff --git a/_static/img/cat_superres_with_ort.jpg b/_static/img/cat_superres_with_ort.jpg deleted file mode 100644 index 7e4143c3e79..00000000000 Binary files a/_static/img/cat_superres_with_ort.jpg and /dev/null differ diff --git a/_static/img/thumbnails/cropped/optional-Exporting-a-Model-from-PyTorch-to-ONNX-and-Running-it-using-ONNX-Runtime.png b/_static/img/thumbnails/cropped/optional-Exporting-a-Model-from-PyTorch-to-ONNX-and-Running-it-using-ONNX-Runtime.png deleted file mode 100644 index 00156df042e..00000000000 Binary files a/_static/img/thumbnails/cropped/optional-Exporting-a-Model-from-PyTorch-to-ONNX-and-Running-it-using-ONNX-Runtime.png and /dev/null differ diff --git a/advanced_source/README.txt b/advanced_source/README.txt index 0dbaffef5f7..232d2bc439e 100644 --- a/advanced_source/README.txt +++ b/advanced_source/README.txt @@ -9,10 +9,6 @@ Advanced Tutorials Creating Extensions Using numpy and scipy https://pytorch.org/tutorials/advanced/numpy_extensions_tutorial.html -3. c_extension.rst +3. cpp_extension.rst Custom C Extensions for PyTorch - https://pytorch.org/tutorials/advanced/c_extension.html - -4. super_resolution_with_onnxruntime.py - Exporting a Model from PyTorch to ONNX and Running it using ONNXRuntime - https://pytorch.org/tutorials/advanced/super_resolution_with_onnxruntime.html + https://docs.pytorch.org/tutorials/advanced/cpp_extension.html diff --git a/advanced_source/super_resolution_with_onnxruntime.py b/advanced_source/super_resolution_with_onnxruntime.py deleted file mode 100644 index 264678ee17a..00000000000 --- a/advanced_source/super_resolution_with_onnxruntime.py +++ /dev/null @@ -1,356 +0,0 @@ -""" -(optional) Exporting a Model from PyTorch to ONNX and Running it using ONNX Runtime -=================================================================================== - -.. note:: - As of PyTorch 2.1, there are two versions of ONNX Exporter. - - * ``torch.onnx.dynamo_export`` is the newest (still in beta) exporter based on the TorchDynamo technology released with PyTorch 2.0. - * ``torch.onnx.export`` is based on TorchScript backend and has been available since PyTorch 1.2.0. - -In this tutorial, we describe how to convert a model defined -in PyTorch into the ONNX format using the TorchScript ``torch.onnx.export`` ONNX exporter. - -The exported model will be executed with ONNX Runtime. -ONNX Runtime is a performance-focused engine for ONNX models, -which inferences efficiently across multiple platforms and hardware -(Windows, Linux, and Mac and on both CPUs and GPUs). -ONNX Runtime has proved to considerably increase performance over -multiple models as explained `here -`__ - -For this tutorial, you will need to install `ONNX `__ -and `ONNX Runtime `__. -You can get binary builds of ONNX and ONNX Runtime with - -.. code-block:: bash - - %%bash - pip install onnx onnxruntime - -ONNX Runtime recommends using the latest stable runtime for PyTorch. - -""" - -# Some standard imports -import numpy as np - -from torch import nn -import torch.utils.model_zoo as model_zoo -import torch.onnx - - -###################################################################### -# Super-resolution is a way of increasing the resolution of images, videos -# and is widely used in image processing or video editing. For this -# tutorial, we will use a small super-resolution model. -# -# First, let's create a ``SuperResolution`` model in PyTorch. -# This model uses the efficient sub-pixel convolution layer described in -# `"Real-Time Single Image and Video Super-Resolution Using an Efficient -# Sub-Pixel Convolutional Neural Network" - Shi et al `__ -# for increasing the resolution of an image by an upscale factor. -# The model expects the Y component of the ``YCbCr`` of an image as an input, and -# outputs the upscaled Y component in super resolution. -# -# `The -# model `__ -# comes directly from PyTorch's examples without modification: -# - -# Super Resolution model definition in PyTorch -import torch.nn as nn -import torch.nn.init as init - - -class SuperResolutionNet(nn.Module): - def __init__(self, upscale_factor, inplace=False): - super(SuperResolutionNet, self).__init__() - - self.relu = nn.ReLU(inplace=inplace) - self.conv1 = nn.Conv2d(1, 64, (5, 5), (1, 1), (2, 2)) - self.conv2 = nn.Conv2d(64, 64, (3, 3), (1, 1), (1, 1)) - self.conv3 = nn.Conv2d(64, 32, (3, 3), (1, 1), (1, 1)) - self.conv4 = nn.Conv2d(32, upscale_factor ** 2, (3, 3), (1, 1), (1, 1)) - self.pixel_shuffle = nn.PixelShuffle(upscale_factor) - - self._initialize_weights() - - def forward(self, x): - x = self.relu(self.conv1(x)) - x = self.relu(self.conv2(x)) - x = self.relu(self.conv3(x)) - x = self.pixel_shuffle(self.conv4(x)) - return x - - def _initialize_weights(self): - init.orthogonal_(self.conv1.weight, init.calculate_gain('relu')) - init.orthogonal_(self.conv2.weight, init.calculate_gain('relu')) - init.orthogonal_(self.conv3.weight, init.calculate_gain('relu')) - init.orthogonal_(self.conv4.weight) - -# Create the super-resolution model by using the above model definition. -torch_model = SuperResolutionNet(upscale_factor=3) - - -###################################################################### -# Ordinarily, you would now train this model; however, for this tutorial, -# we will instead download some pretrained weights. Note that this model -# was not trained fully for good accuracy and is used here for -# demonstration purposes only. -# -# It is important to call ``torch_model.eval()`` or ``torch_model.train(False)`` -# before exporting the model, to turn the model to inference mode. -# This is required since operators like dropout or batchnorm behave -# differently in inference and training mode. -# - -# Load pretrained model weights -model_url = 'https://s3.amazonaws.com/pytorch/test_data/export/superres_epoch100-44c6958e.pth' -batch_size = 64 # just a random number - -# Initialize model with the pretrained weights -map_location = lambda storage, loc: storage -if torch.cuda.is_available(): - map_location = None -torch_model.load_state_dict(model_zoo.load_url(model_url, map_location=map_location)) - -# set the model to inference mode -torch_model.eval() - - -###################################################################### -# Exporting a model in PyTorch works via tracing or scripting. This -# tutorial will use as an example a model exported by tracing. -# To export a model, we call the ``torch.onnx.export()`` function. -# This will execute the model, recording a trace of what operators -# are used to compute the outputs. -# Because ``export`` runs the model, we need to provide an input -# tensor ``x``. The values in this can be random as long as it is the -# right type and size. -# Note that the input size will be fixed in the exported ONNX graph for -# all the input's dimensions, unless specified as a dynamic axes. -# In this example we export the model with an input of batch_size 1, -# but then specify the first dimension as dynamic in the ``dynamic_axes`` -# parameter in ``torch.onnx.export()``. -# The exported model will thus accept inputs of size [batch_size, 1, 224, 224] -# where batch_size can be variable. -# -# To learn more details about PyTorch's export interface, check out the -# `torch.onnx documentation `__. -# - -# Input to the model -x = torch.randn(batch_size, 1, 224, 224, requires_grad=True) -torch_out = torch_model(x) - -# Export the model -torch.onnx.export(torch_model, # model being run - x, # model input (or a tuple for multiple inputs) - "super_resolution.onnx", # where to save the model (can be a file or file-like object) - export_params=True, # store the trained parameter weights inside the model file - opset_version=10, # the ONNX version to export the model to - do_constant_folding=True, # whether to execute constant folding for optimization - input_names = ['input'], # the model's input names - output_names = ['output'], # the model's output names - dynamic_axes={'input' : {0 : 'batch_size'}, # variable length axes - 'output' : {0 : 'batch_size'}}) - -###################################################################### -# We also computed ``torch_out``, the output after of the model, -# which we will use to verify that the model we exported computes -# the same values when run in ONNX Runtime. -# -# But before verifying the model's output with ONNX Runtime, we will check -# the ONNX model with ONNX API. -# First, ``onnx.load("super_resolution.onnx")`` will load the saved model and -# will output a ``onnx.ModelProto`` structure (a top-level file/container format for bundling a ML model. -# For more information `onnx.proto documentation `__.). -# Then, ``onnx.checker.check_model(onnx_model)`` will verify the model's structure -# and confirm that the model has a valid schema. -# The validity of the ONNX graph is verified by checking the model's -# version, the graph's structure, as well as the nodes and their inputs -# and outputs. -# - -import onnx - -onnx_model = onnx.load("super_resolution.onnx") -onnx.checker.check_model(onnx_model) - - -###################################################################### -# Now let's compute the output using ONNX Runtime's Python APIs. -# This part can normally be done in a separate process or on another -# machine, but we will continue in the same process so that we can -# verify that ONNX Runtime and PyTorch are computing the same value -# for the network. -# -# In order to run the model with ONNX Runtime, we need to create an -# inference session for the model with the chosen configuration -# parameters (here we use the default config). -# Once the session is created, we evaluate the model using the run() API. -# The output of this call is a list containing the outputs of the model -# computed by ONNX Runtime. -# - -import onnxruntime - -ort_session = onnxruntime.InferenceSession("super_resolution.onnx", providers=["CPUExecutionProvider"]) - -def to_numpy(tensor): - return tensor.detach().cpu().numpy() if tensor.requires_grad else tensor.cpu().numpy() - -# compute ONNX Runtime output prediction -ort_inputs = {ort_session.get_inputs()[0].name: to_numpy(x)} -ort_outs = ort_session.run(None, ort_inputs) - -# compare ONNX Runtime and PyTorch results -np.testing.assert_allclose(to_numpy(torch_out), ort_outs[0], rtol=1e-03, atol=1e-05) - -print("Exported model has been tested with ONNXRuntime, and the result looks good!") - - -###################################################################### -# We should see that the output of PyTorch and ONNX Runtime runs match -# numerically with the given precision (``rtol=1e-03`` and ``atol=1e-05``). -# As a side-note, if they do not match then there is an issue in the -# ONNX exporter, so please contact us in that case. -# - -###################################################################### -# Timing Comparison Between Models -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# - -###################################################################### -# Since ONNX models optimize for inference speed, running the same -# data on an ONNX model instead of a native pytorch model should result in an -# improvement of up to 2x. Improvement is more pronounced with higher batch sizes. - - -import time - -x = torch.randn(batch_size, 1, 224, 224, requires_grad=True) - -start = time.time() -torch_out = torch_model(x) -end = time.time() -print(f"Inference of Pytorch model used {end - start} seconds") - -ort_inputs = {ort_session.get_inputs()[0].name: to_numpy(x)} -start = time.time() -ort_outs = ort_session.run(None, ort_inputs) -end = time.time() -print(f"Inference of ONNX model used {end - start} seconds") - - -###################################################################### -# Running the model on an image using ONNX Runtime -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# - - -###################################################################### -# So far we have exported a model from PyTorch and shown how to load it -# and run it in ONNX Runtime with a dummy tensor as an input. - -###################################################################### -# For this tutorial, we will use a famous cat image used widely which -# looks like below -# -# .. figure:: /_static/img/cat_224x224.jpg -# :alt: cat -# - -###################################################################### -# First, let's load the image, preprocess it using standard PIL -# python library. Note that this preprocessing is the standard practice of -# processing data for training/testing neural networks. -# -# We first resize the image to fit the size of the model's input (224x224). -# Then we split the image into its Y, Cb, and Cr components. -# These components represent a grayscale image (Y), and -# the blue-difference (Cb) and red-difference (Cr) chroma components. -# The Y component being more sensitive to the human eye, we are -# interested in this component which we will be transforming. -# After extracting the Y component, we convert it to a tensor which -# will be the input of our model. -# - -from PIL import Image -import torchvision.transforms as transforms - -img = Image.open("./_static/img/cat.jpg") - -resize = transforms.Resize([224, 224]) -img = resize(img) - -img_ycbcr = img.convert('YCbCr') -img_y, img_cb, img_cr = img_ycbcr.split() - -to_tensor = transforms.ToTensor() -img_y = to_tensor(img_y) -img_y.unsqueeze_(0) - - -###################################################################### -# Now, as a next step, let's take the tensor representing the -# grayscale resized cat image and run the super-resolution model in -# ONNX Runtime as explained previously. -# - -ort_inputs = {ort_session.get_inputs()[0].name: to_numpy(img_y)} -ort_outs = ort_session.run(None, ort_inputs) -img_out_y = ort_outs[0] - - -###################################################################### -# At this point, the output of the model is a tensor. -# Now, we'll process the output of the model to construct back the -# final output image from the output tensor, and save the image. -# The post-processing steps have been adopted from PyTorch -# implementation of super-resolution model -# `here `__. -# - -img_out_y = Image.fromarray(np.uint8((img_out_y[0] * 255.0).clip(0, 255)[0]), mode='L') - -# get the output image follow post-processing step from PyTorch implementation -final_img = Image.merge( - "YCbCr", [ - img_out_y, - img_cb.resize(img_out_y.size, Image.BICUBIC), - img_cr.resize(img_out_y.size, Image.BICUBIC), - ]).convert("RGB") - -# Save the image, we will compare this with the output image from mobile device -final_img.save("./_static/img/cat_superres_with_ort.jpg") - -# Save resized original image (without super-resolution) -img = transforms.Resize([img_out_y.size[0], img_out_y.size[1]])(img) -img.save("cat_resized.jpg") - -###################################################################### -# Here is the comparison between the two images: -# -# .. figure:: /_static/img/cat_resized.jpg -# -# Low-resolution image -# -# .. figure:: /_static/img/cat_superres_with_ort.jpg -# -# Image after super-resolution -# -# -# ONNX Runtime being a cross platform engine, you can run it across -# multiple platforms and on both CPUs and GPUs. -# -# ONNX Runtime can also be deployed to the cloud for model inferencing -# using Azure Machine Learning Services. More information `here `__. -# -# More information about ONNX Runtime's performance `here `__. -# -# -# For more information about ONNX Runtime `here `__. -# diff --git a/beginner_source/onnx/export_simple_model_to_onnx_tutorial.py b/beginner_source/onnx/export_simple_model_to_onnx_tutorial.py index 1676e4adc06..8948cbaa2c1 100644 --- a/beginner_source/onnx/export_simple_model_to_onnx_tutorial.py +++ b/beginner_source/onnx/export_simple_model_to_onnx_tutorial.py @@ -11,10 +11,9 @@ **Author**: `Ti-Tai Wang `_, `Justin Chu `_, `Thiago Crepaldi `_. .. note:: - As of PyTorch 2.5, there are two versions of ONNX Exporter. - - * ``torch.onnx.export(..., dynamo=True)`` is the newest (still in beta) exporter using ``torch.export`` and Torch FX to capture the graph. It was released with PyTorch 2.5 - * ``torch.onnx.export`` uses TorchScript and has been available since PyTorch 1.2.0 + Starting with PyTorch 2.5, there are two ONNX Exporter options available. + * ``torch.onnx.export(..., dynamo=True)`` is the recommended exporter that leverages ``torch.export`` and Torch FX for graph capture. + * ``torch.onnx.export`` is the legacy approach that relies on the deprecated TorchScript and is no longer recommended for use. """ @@ -93,15 +92,6 @@ def forward(self, x: torch.Tensor): example_inputs = (torch.randn(1, 1, 32, 32),) onnx_program = torch.onnx.export(torch_model, example_inputs, dynamo=True) -###################################################################### -# 3.5. (Optional) Optimize the ONNX model -# --------------------------------------- -# -# The ONNX model can be optimized with constant folding, and elimination of redundant nodes. -# The optimization is done in-place, so the original ONNX model is modified. - -onnx_program.optimize() - ###################################################################### # As we can see, we didn't need any code change to the model. # The resulting ONNX model is stored within ``torch.onnx.ONNXProgram`` as a binary protobuf file. diff --git a/beginner_source/onnx/intro_onnx.py b/beginner_source/onnx/intro_onnx.py index 2fb73a86c15..ecb0be97bf2 100644 --- a/beginner_source/onnx/intro_onnx.py +++ b/beginner_source/onnx/intro_onnx.py @@ -19,12 +19,6 @@ `runtimes that support ONNX `_, including Microsoft's `ONNX Runtime `_. -.. note:: - Currently, you can choose either through `TorchScript https://pytorch.org/docs/stable/jit.html`_ or - `ExportedProgram https://pytorch.org/docs/stable/export.html`_ to export the model to ONNX by the - boolean parameter dynamo in `torch.onnx.export `_. - In this tutorial, we will focus on the ``ExportedProgram`` approach. - When setting ``dynamo=True``, the exporter will use `torch.export `_ to capture an ``ExportedProgram``, before translating the graph into ONNX representations. This approach is the new and recommended way to export models to ONNX. It works with PyTorch 2.0 features more robustly, has better support for newer ONNX operator sets, and consumes less resources diff --git a/index.rst b/index.rst index 71cddc0bda9..2c27326d0aa 100644 --- a/index.rst +++ b/index.rst @@ -249,7 +249,7 @@ Welcome to PyTorch Tutorials .. ONNX .. customcarditem:: - :header: (optional) Exporting a PyTorch model to ONNX using TorchDynamo backend and Running it using ONNX Runtime + :header: Exporting a PyTorch model to ONNX using TorchDynamo backend and Running it using ONNX Runtime :card_description: Build a image classifier model in PyTorch and convert it to ONNX before deploying it with ONNX Runtime. :image: _static/img/thumbnails/cropped/Exporting-PyTorch-Models-to-ONNX-Graphs.png :link: beginner/onnx/export_simple_model_to_onnx_tutorial.html @@ -329,13 +329,6 @@ Welcome to PyTorch Tutorials :link: advanced/cpp_export.html :tags: Production,TorchScript -.. customcarditem:: - :header: (optional) Exporting a PyTorch Model to ONNX using TorchScript backend and Running it using ONNX Runtime - :card_description: Convert a model defined in PyTorch into the ONNX format and then run it with ONNX Runtime. - :image: _static/img/thumbnails/cropped/optional-Exporting-a-Model-from-PyTorch-to-ONNX-and-Running-it-using-ONNX-Runtime.png - :link: advanced/super_resolution_with_onnxruntime.html - :tags: Production,ONNX - .. customcarditem:: :header: Profiling PyTorch :card_description: Learn how to profile a PyTorch application @@ -977,7 +970,6 @@ Additional Resources beginner/onnx/intro_onnx beginner/Intro_to_TorchScript_tutorial advanced/cpp_export - advanced/super_resolution_with_onnxruntime intermediate/realtime_rpi .. toctree:: diff --git a/redirects.py b/redirects.py index 6e2d5f34c17..4b4c6299122 100644 --- a/redirects.py +++ b/redirects.py @@ -3,6 +3,7 @@ "beginner/ptcheat.html": "../index.html", "beginner/deploy_seq2seq_hybrid_frontend_tutorial.html": "../index.html", "recipes/bundled_inputs.html": "../index.html", + "advanced/super_resolution_with_onnxruntime.html": "../index.html", "intermediate/torchserve_with_ipex.html": "../index.html", "intermediate/torchserve_with_ipex_2.html": "../index.html", "recipes/torchserve_vertexai_tutorial.html": "../index.html",