Skip to content

Commit 7b1ab2c

Browse files
authored
Merge branch 'main' into python-agnostic-1st
2 parents 9a96b75 + 15ef015 commit 7b1ab2c

21 files changed

+200
-378
lines changed

.jenkins/validate_tutorials_built.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,6 @@
5050
"intermediate_source/flask_rest_api_tutorial",
5151
"intermediate_source/text_to_speech_with_torchaudio",
5252
"intermediate_source/tensorboard_profiler_tutorial", # reenable after 2.0 release.
53-
"intermediate_source/torch_export_tutorial", # reenable after 2940 is fixed.
54-
"advanced_source/pendulum",
55-
"beginner_source/onnx/export_simple_model_to_onnx_tutorial",
56-
"beginner_source/onnx/onnx_registry_tutorial"
5753
]
5854

5955
def tutorial_source_dirs() -> List[Path]:
38.1 KB
Loading
Binary file not shown.
-7.37 KB
Binary file not shown.
-15.9 KB
Binary file not shown.
-8.41 KB
Binary file not shown.
-381 Bytes
Loading
Loading
Binary file not shown.

advanced_source/coding_ddpg.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,7 @@ def make_recorder(actor_model_explore, transform_state_dict, record_interval):
893893
record_frames=1000,
894894
policy_exploration=actor_model_explore,
895895
environment=environment,
896-
exploration_type=ExplorationType.MEAN,
896+
exploration_type=ExplorationType.DETERMINISTIC,
897897
record_interval=record_interval,
898898
)
899899
return recorder_obj

advanced_source/pendulum.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ def __init__(self, td_params=None, seed=None, device="cpu"):
604604
env,
605605
# ``Unsqueeze`` the observations that we will concatenate
606606
UnsqueezeTransform(
607-
unsqueeze_dim=-1,
607+
dim=-1,
608608
in_keys=["th", "thdot"],
609609
in_keys_inv=["th", "thdot"],
610610
),

beginner_source/examples_autograd/polynomial_autograd.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@
1717
import torch
1818
import math
1919

20+
# We want to be able to train our model on an `accelerator <https://pytorch.org/docs/stable/torch.html#accelerators>`__
21+
# such as CUDA, MPS, MTIA, or XPU. If the current accelerator is available, we will use it. Otherwise, we use the CPU.
22+
2023
dtype = torch.float
21-
device = "cuda" if torch.cuda.is_available() else "cpu"
24+
device = torch.accelerator.current_accelerator().type if torch.accelerator.is_available() else "cpu"
25+
print(f"Using {device} device")
2226
torch.set_default_device(device)
2327

2428
# Create Tensors to hold input and outputs.

beginner_source/fgsm_tutorial.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,9 @@
125125
# `pytorch/examples/mnist <https://github.com/pytorch/examples/tree/master/mnist>`__.
126126
# For simplicity, download the pretrained model `here <https://drive.google.com/file/d/1HJV2nUHJqclXQ8flKvcWmjZ-OU5DGatl/view?usp=drive_link>`__.
127127
#
128-
# - ``use_cuda`` - boolean flag to use CUDA if desired and available.
129-
# Note, a GPU with CUDA is not critical for this tutorial as a CPU will
130-
# not take much time.
131-
#
132128

133129
epsilons = [0, .05, .1, .15, .2, .25, .3]
134130
pretrained_model = "data/lenet_mnist_model.pth"
135-
use_cuda=True
136131
# Set random seed for reproducibility
137132
torch.manual_seed(42)
138133

@@ -184,9 +179,10 @@ def forward(self, x):
184179
])),
185180
batch_size=1, shuffle=True)
186181

187-
# Define what device we are using
188-
print("CUDA Available: ",torch.cuda.is_available())
189-
device = torch.device("cuda" if use_cuda and torch.cuda.is_available() else "cpu")
182+
# We want to be able to train our model on an `accelerator <https://pytorch.org/docs/stable/torch.html#accelerators>`__
183+
# such as CUDA, MPS, MTIA, or XPU. If the current accelerator is available, we will use it. Otherwise, we use the CPU.
184+
device = torch.accelerator.current_accelerator().type if torch.accelerator.is_available() else "cpu"
185+
print(f"Using {device} device")
190186

191187
# Initialize the network
192188
model = Net().to(device)

beginner_source/onnx/export_simple_model_to_onnx_tutorial.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
Export a PyTorch model to ONNX
88
==============================
99
10-
**Author**: `Thiago Crepaldi <https://github.com/thiagocrepaldi>`_
10+
**Author**: `Ti-Tai Wang <https://github.com/titaiwangms>`_ and `Xavier Dupré <https://github.com/xadupre>`_
1111
1212
.. note::
1313
As of PyTorch 2.1, there are two versions of ONNX Exporter.
@@ -127,7 +127,7 @@ def forward(self, x):
127127
# Once Netron is open, we can drag and drop our ``my_image_classifier.onnx`` file into the browser or select it after
128128
# clicking the **Open model** button.
129129
#
130-
# .. image:: ../../_static/img/onnx/image_clossifier_onnx_modelon_netron_web_ui.png
130+
# .. image:: ../../_static/img/onnx/image_classifier_onnx_model_on_netron_web_ui.png
131131
# :width: 50%
132132
#
133133
#
@@ -155,7 +155,7 @@ def forward(self, x):
155155

156156
import onnxruntime
157157

158-
onnx_input = onnx_program.adapt_torch_inputs_to_onnx(torch_input)
158+
onnx_input = [torch_input]
159159
print(f"Input length: {len(onnx_input)}")
160160
print(f"Sample input: {onnx_input}")
161161

@@ -166,7 +166,8 @@ def to_numpy(tensor):
166166

167167
onnxruntime_input = {k.name: to_numpy(v) for k, v in zip(ort_session.get_inputs(), onnx_input)}
168168

169-
onnxruntime_outputs = ort_session.run(None, onnxruntime_input)
169+
# onnxruntime returns a list of outputs
170+
onnxruntime_outputs = ort_session.run(None, onnxruntime_input)[0]
170171

171172
####################################################################
172173
# 7. Compare the PyTorch results with the ones from the ONNX Runtime
@@ -179,7 +180,6 @@ def to_numpy(tensor):
179180
# Before comparing the results, we need to convert the PyTorch's output to match ONNX's format.
180181

181182
torch_outputs = torch_model(torch_input)
182-
torch_outputs = onnx_program.adapt_torch_outputs_to_onnx(torch_outputs)
183183

184184
assert len(torch_outputs) == len(onnxruntime_outputs)
185185
for torch_output, onnxruntime_output in zip(torch_outputs, onnxruntime_outputs):

beginner_source/onnx/intro_onnx.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
====================
88
99
Authors:
10-
`Thiago Crepaldi <https://github.com/thiagocrepaldi>`_,
10+
`Ti-Tai Wang <https://github.com/titaiwangms>`_ and `Xavier Dupré <https://github.com/xadupre>`_
1111
1212
`Open Neural Network eXchange (ONNX) <https://onnx.ai/>`_ is an open standard
1313
format for representing machine learning models. The ``torch.onnx`` module provides APIs to

beginner_source/onnx/onnx_registry_tutorial.py

Lines changed: 9 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -31,148 +31,15 @@
3131
#
3232
# In this tutorial, we will cover three scenarios that require extending the ONNX registry with custom operators:
3333
#
34-
# * Unsupported ATen operators
3534
# * Custom operators with existing ONNX Runtime support
3635
# * Custom operators without ONNX Runtime support
3736
#
38-
# Unsupported ATen operators
39-
# --------------------------
40-
#
41-
# Although the ONNX exporter team does their best efforts to support all ATen operators, some of them
42-
# might not be supported yet. In this section, we will demonstrate how you can add
43-
# unsupported ATen operators to the ONNX Registry.
44-
#
45-
# .. note::
46-
# The steps to implement unsupported ATen operators are the same to replace the implementation of an existing
47-
# ATen operator with a custom implementation.
48-
# Because we don't actually have an unsupported ATen operator to use in this tutorial, we are going to leverage
49-
# this and replace the implementation of ``aten::add.Tensor`` with a custom implementation the same way we would
50-
# if the operator was not present in the ONNX Registry.
51-
#
52-
# When a model cannot be exported to ONNX due to an unsupported operator, the ONNX exporter will show an error message
53-
# similar to:
54-
#
55-
# .. code-block:: python
56-
#
57-
# RuntimeErrorWithDiagnostic: Unsupported FX nodes: {'call_function': ['aten.add.Tensor']}.
58-
#
59-
# The error message indicates that the fully qualified name of unsupported ATen operator is ``aten::add.Tensor``.
60-
# The fully qualified name of an operator is composed of the namespace, operator name, and overload following
61-
# the format ``namespace::operator_name.overload``.
62-
#
63-
# To add support for an unsupported ATen operator or to replace the implementation for an existing one, we need:
64-
#
65-
# * The fully qualified name of the ATen operator (e.g. ``aten::add.Tensor``).
66-
# This information is always present in the error message as show above.
67-
# * The implementation of the operator using `ONNX Script <https://github.com/microsoft/onnxscript>`__.
68-
# ONNX Script is a prerequisite for this tutorial. Please make sure you have read the
69-
# `ONNX Script tutorial <https://github.com/microsoft/onnxscript/blob/main/docs/tutorial/index.md>`_
70-
# before proceeding.
71-
#
72-
# Because ``aten::add.Tensor`` is already supported by the ONNX Registry, we will demonstrate how to replace it with a
73-
# custom implementation, but keep in mind that the same steps apply to support new unsupported ATen operators.
74-
#
75-
# This is possible because the :class:`OnnxRegistry` allows users to override an operator registration.
76-
# We will override the registration of ``aten::add.Tensor`` with our custom implementation and verify it exists.
77-
#
7837

7938
import torch
8039
import onnxruntime
8140
import onnxscript
8241
from onnxscript import opset18 # opset 18 is the latest (and only) supported version for now
8342

84-
class Model(torch.nn.Module):
85-
def forward(self, input_x, input_y):
86-
return torch.ops.aten.add(input_x, input_y) # generates a aten::add.Tensor node
87-
88-
input_add_x = torch.randn(3, 4)
89-
input_add_y = torch.randn(3, 4)
90-
aten_add_model = Model()
91-
92-
93-
# Now we create a ONNX Script function that implements ``aten::add.Tensor``.
94-
# The function name (e.g. ``custom_aten_add``) is displayed in the ONNX graph, so we recommend to use intuitive names.
95-
custom_aten = onnxscript.values.Opset(domain="custom.aten", version=1)
96-
97-
# NOTE: The function signature must match the signature of the unsupported ATen operator.
98-
# https://github.com/pytorch/pytorch/blob/main/aten/src/ATen/native/native_functions.yaml
99-
# NOTE: All attributes must be annotated with type hints.
100-
@onnxscript.script(custom_aten)
101-
def custom_aten_add(input_x, input_y, alpha: float = 1.0):
102-
input_y = opset18.Mul(input_y, alpha)
103-
return opset18.Add(input_x, input_y)
104-
105-
106-
# Now we have everything we need to support unsupported ATen operators.
107-
# Let's register the ``custom_aten_add`` function to ONNX registry, and export the model to ONNX again.
108-
onnx_registry = torch.onnx.OnnxRegistry()
109-
onnx_registry.register_op(
110-
namespace="aten", op_name="add", overload="Tensor", function=custom_aten_add
111-
)
112-
print(f"aten::add.Tensor is supported by ONNX registry: \
113-
{onnx_registry.is_registered_op(namespace='aten', op_name='add', overload='Tensor')}"
114-
)
115-
export_options = torch.onnx.ExportOptions(onnx_registry=onnx_registry)
116-
onnx_program = torch.onnx.dynamo_export(
117-
aten_add_model, input_add_x, input_add_y, export_options=export_options
118-
)
119-
120-
######################################################################
121-
# Now let's inspect the model and verify the model has a ``custom_aten_add`` instead of ``aten::add.Tensor``.
122-
# The graph has one graph node for ``custom_aten_add``, and inside of it there are four function nodes, one for each
123-
# operator, and one for constant attribute.
124-
#
125-
126-
# graph node domain is the custom domain we registered
127-
assert onnx_program.model_proto.graph.node[0].domain == "custom.aten"
128-
assert len(onnx_program.model_proto.graph.node) == 1
129-
# graph node name is the function name
130-
assert onnx_program.model_proto.graph.node[0].op_type == "custom_aten_add"
131-
# function node domain is empty because we use standard ONNX operators
132-
assert {node.domain for node in onnx_program.model_proto.functions[0].node} == {""}
133-
# function node name is the standard ONNX operator name
134-
assert {node.op_type for node in onnx_program.model_proto.functions[0].node} == {"Add", "Mul", "Constant"}
135-
136-
137-
######################################################################
138-
# This is how ``custom_aten_add_model`` looks in the ONNX graph using Netron:
139-
#
140-
# .. image:: /_static/img/onnx/custom_aten_add_model.png
141-
# :width: 70%
142-
# :align: center
143-
#
144-
# Inside the ``custom_aten_add`` function, we can see the three ONNX nodes we
145-
# used in the function (``CastLike``, ``Add``, and ``Mul``), and one ``Constant`` attribute:
146-
#
147-
# .. image:: /_static/img/onnx/custom_aten_add_function.png
148-
# :width: 70%
149-
# :align: center
150-
#
151-
# This was all that we needed to register the new ATen operator into the ONNX Registry.
152-
# As an additional step, we can use ONNX Runtime to run the model, and compare the results with PyTorch.
153-
#
154-
155-
156-
# Use ONNX Runtime to run the model, and compare the results with PyTorch
157-
onnx_program.save("./custom_add_model.onnx")
158-
ort_session = onnxruntime.InferenceSession(
159-
"./custom_add_model.onnx", providers=['CPUExecutionProvider']
160-
)
161-
162-
def to_numpy(tensor):
163-
return tensor.detach().cpu().numpy() if tensor.requires_grad else tensor.cpu().numpy()
164-
165-
onnx_input = onnx_program.adapt_torch_inputs_to_onnx(input_add_x, input_add_y)
166-
onnxruntime_input = {k.name: to_numpy(v) for k, v in zip(ort_session.get_inputs(), onnx_input)}
167-
onnxruntime_outputs = ort_session.run(None, onnxruntime_input)
168-
169-
torch_outputs = aten_add_model(input_add_x, input_add_y)
170-
torch_outputs = onnx_program.adapt_torch_outputs_to_onnx(torch_outputs)
171-
172-
assert len(torch_outputs) == len(onnxruntime_outputs)
173-
for torch_output, onnxruntime_output in zip(torch_outputs, onnxruntime_outputs):
174-
torch.testing.assert_close(torch_output, torch.tensor(onnxruntime_output))
175-
17643

17744
######################################################################
17845
# Custom operators with existing ONNX Runtime support
@@ -262,12 +129,11 @@ def custom_aten_gelu(input_x, approximate: str = "none"):
262129
def to_numpy(tensor):
263130
return tensor.detach().cpu().numpy() if tensor.requires_grad else tensor.cpu().numpy()
264131

265-
onnx_input = onnx_program.adapt_torch_inputs_to_onnx(input_gelu_x)
132+
onnx_input = [input_gelu_x]
266133
onnxruntime_input = {k.name: to_numpy(v) for k, v in zip(ort_session.get_inputs(), onnx_input)}
267-
onnxruntime_outputs = ort_session.run(None, onnxruntime_input)
134+
onnxruntime_outputs = ort_session.run(None, onnxruntime_input)[0]
268135

269136
torch_outputs = aten_gelu_model(input_gelu_x)
270-
torch_outputs = onnx_program.adapt_torch_outputs_to_onnx(torch_outputs)
271137

272138
assert len(torch_outputs) == len(onnxruntime_outputs)
273139
for torch_output, onnxruntime_output in zip(torch_outputs, onnxruntime_outputs):
@@ -369,25 +235,17 @@ def custom_addandround(input_x):
369235
#
370236

371237
assert onnx_program.model_proto.graph.node[0].domain == "test.customop"
372-
assert onnx_program.model_proto.graph.node[0].op_type == "custom_addandround"
373-
assert onnx_program.model_proto.functions[0].node[0].domain == "test.customop"
374-
assert onnx_program.model_proto.functions[0].node[0].op_type == "CustomOpOne"
375-
assert onnx_program.model_proto.functions[0].node[1].domain == "test.customop"
376-
assert onnx_program.model_proto.functions[0].node[1].op_type == "CustomOpTwo"
238+
assert onnx_program.model_proto.graph.node[0].op_type == "CustomOpOne"
239+
assert onnx_program.model_proto.graph.node[1].domain == "test.customop"
240+
assert onnx_program.model_proto.graph.node[1].op_type == "CustomOpTwo"
377241

378242

379243
######################################################################
380-
# This is how ``custom_addandround_model`` ONNX graph looks using Netron:
381-
#
382-
# .. image:: /_static/img/onnx/custom_addandround_model.png
383-
# :width: 70%
384-
# :align: center
385-
#
386-
# Inside the ``custom_addandround`` function, we can see the two custom operators we
387-
# used in the function (``CustomOpOne``, and ``CustomOpTwo``), and they are from module
388-
# ``test.customop``:
244+
# This is how ``custom_addandround_model`` ONNX graph looks using Netron.
245+
# We can see the two custom operators we used in the function (``CustomOpOne``, and ``CustomOpTwo``),
246+
# and they are from module ``test.customop``:
389247
#
390-
# .. image:: /_static/img/onnx/custom_addandround_function.png
248+
# .. image:: /_static/img/onnx/custom_addandround.png
391249
#
392250
# Custom Ops Registration in ONNX Runtime
393251
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

beginner_source/transfer_learning_tutorial.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,11 @@
9898
dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']}
9999
class_names = image_datasets['train'].classes
100100

101-
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
101+
# We want to be able to train our model on an `accelerator <https://pytorch.org/docs/stable/torch.html#accelerators>`__
102+
# such as CUDA, MPS, MTIA, or XPU. If the current accelerator is available, we will use it. Otherwise, we use the CPU.
103+
104+
device = torch.accelerator.current_accelerator().type if torch.accelerator.is_available() else "cpu"
105+
print(f"Using {device} device")
102106

103107
######################################################################
104108
# Visualize a few images

intermediate_source/dqn_with_rnn_tutorial.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@
433433
exploration_module.step(data.numel())
434434
updater.step()
435435

436-
with set_exploration_type(ExplorationType.MODE), torch.no_grad():
436+
with set_exploration_type(ExplorationType.DETERMINISTIC), torch.no_grad():
437437
rollout = env.rollout(10000, stoch_policy)
438438
traj_lens.append(rollout.get(("next", "step_count")).max().item())
439439

intermediate_source/reinforcement_ppo.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -419,8 +419,8 @@
419419
in_keys=["loc", "scale"],
420420
distribution_class=TanhNormal,
421421
distribution_kwargs={
422-
"min": env.action_spec.space.low,
423-
"max": env.action_spec.space.high,
422+
"low": env.action_spec.space.low,
423+
"high": env.action_spec.space.high,
424424
},
425425
return_log_prob=True,
426426
# we'll need the log-prob for the numerator of the importance weights

0 commit comments

Comments
 (0)