Pytorch C++ Export to ONNX

PyMike: <p>Hi,</p>
<p>I’m using PyTorch C++ in a high performance embedded system. I was able to create and train a custom model, and now I want to export it to ONNX to bring it into NVIDIA’s TensorRT. I found an example on how to export to ONNX if using the Python version of PyTorch, but I need to avoid Python if possible and only stick with PyTorch C++. Here’s the Python code snippet:</p>
<blockquote>
<p>dummy_input = torch.randn(1, 3, 224, 224, device=‘cuda’)<br>
input_names = [ “input” ]<br>
output_names = [ “output” ]<br>
torch.onnx.export(model, dummy_input, “my_model.onnx”, verbose=True, input_names=input_names, output_names=output_names)</p>
</blockquote>
<p>How do I do this using the PyTorch C++ API?<br>
If this ability does not work, is there a simple way to convert the output of:</p>
<blockquote>
<p>torch::save(network, “network_and_weights.pt”);</p>
</blockquote>
<p>to an ONNX file without needing to use the world of Python?</p>
<p>Thank you for any guidance.</p>

PyMike: <p>To expand on this question, In C++ I can save and load an entire model with parameters using:</p>
<blockquote>
<p>torch::save(network, “network_and_weights.pt”);<br>
torch::load(network, “network_and_weights.pt”);</p>
</blockquote>
<p>But there does not seem to be a way to save and load just the weights in C++. In Python you can do this with:</p>
<blockquote>
<p>torch.save(model.state_dict(), “weights.pt”)<br>
model.load_state_dict(torch.load(“weights.pt”))<br>
The only thing I found in C++ that might be how to save is:</p>
</blockquote>
<blockquote>
<p>torch::save(network-&gt;parameters(), “weights.pt”);</p>
</blockquote>
<p>But there is no comparable C++ function to load… I was hoping for something like:</p>
<blockquote>
<p>network-&gt;load_parameters(torch::load(“weights.pt”));</p>
</blockquote>
<p>Saving and loading just the weights seems like such a fundamental aspect of using a framework, and being able to export to ONNX also seems fundamental. I feel like I’m missing something obvious. Is there anyone out there who can help explain how to save/load weights and export to ONNX using C++?</p>
<p>Thanks</p>

PyMike: <p>With all the fanfare of PyTorch, LibTorch, &amp; ONNX, I’m surprised I’m not seeing any responses to this discussion. Day after day I just keep digging.</p>
<p>It’s counter-intuitive that the PyTorch and LibTorch have different file formats for the same torch functions save() and load(). Just provide an analogy… can you imagine if a image company writing functions for python saveJPEG() and the C++ saveJPEG() saved to completely different incompatible file formats? I’m not trying to criticize, I’m trying to show how the development community is being confused, in a way that causes days or weeks of lost time and money.</p>
<p>Anyways, my goal is to train in LibTorch C++ (PyTorch is not an option for training with our embedded customers)  and somehow save it to ONNX so I can use it with NVIDIA’s TensorRT. Since it sounds like there’s no activity with implementing LibTorch’s <code>torch::onnx::export()</code>, and there’s no activity to make save() &amp; load() interoperable between PyTorch and LibTorch, then my only option is to try various hacks, as you can see from the posts above.</p>
<p>Another hack was to try (in C++):</p>
<pre><code class="lang-auto">  torch::Tensor dummy_input = torch::randn({1, 3, 224, 224});
  dummy_input.to(torch::kCUDA);
  auto traced_script_module = torch::jit::trace(model, dummy_input);
  traced_script_module.save("traced_model.pt");
</code></pre>
<p>and then import it into a simple PyTorch script to convert to ONNX:</p>
<pre><code class="lang-auto">import torch
import torchvision
model = torch.jit.load("traced_model.pt")
model = model.cuda()
model.eval()
input_names = [ "input" ]
output_names = [ "output" ]
dummy_input = torch.randn(1, 3, 224, 244, device='cuda')
dummy_output = torch.rand((1, 102), device='cuda')
torch.onnx.export(model, dummy_input, "resnet18_3x256x256.onnx", verbose=True, input_names=input_names, output_names=output_names, example_outputs=dummy_output)
</code></pre>
<p>But <code>torch::jit::trace()</code> is not implemented in LibTorch, and I don’t see any activity indicating it will be worked on.</p>
<p>Am I the only person out there who needs to train in C++, export to ONNX, and import to TensorRT? If not, could you please voice yourself so the LibTorch developers can prioritize this a little higher.</p>

IknowWhatYouMean: <p>I had the same expectations for the Pytorch -&gt; ONNX -&gt; TRT export. The day I realized I had to pass trough Python in order to export to ONNX, was the last day of me using Pytorch. If we have to build communities to beg the devs and wait for something so fundamental - it’s beyond the joke.</p>

sshuair: <p>I need this feature too.</p>

jimoskar: <p>I need this feature too. <img src="https://discuss.pytorch.org/images/emoji/apple/sob.png?v=9" title=":sob:" class="emoji" alt=":sob:"></p>

Michal_Laszczewski: <p>I need this feature too.</p>

kydyahah: <p>torch::jit::tracer::trace()和torch::jit::export_onnx()这两个接口也许可以解决这个问题。但是到目前为止，我也不知道怎么使用。</p>

ptrblck: <p>From Google translate:</p>
<blockquote>
<p>The two interfaces torch::jit::tracer::trace() and torch::jit::export_onnx() may be able to solve this problem. But so far, I don’t know how to use it.</p>
</blockquote>

swilson314: <p>I need this feature too!</p>

birds_are_drones: <p>Same here ! I need this feature too</p>

allinall: <p>I need this feature too!</p>

ximitiejiang: <p>seems until now still no solution for libtorch trained model transfer to onnx or even to torchscript model(libtorch saved model is not exactly same as torchscript model export from python)?</p>

KongCang: <p>i need this feature too! is anyone solved the problem？</p>

ptrblck: <p>I’m not aware of anyone working on this feature, but am sure it would be accepted, so maybe you and/or <a class="mention" href="/u/ximitiejiang">@ximitiejiang</a>, <a class="mention" href="/u/allinall">@allinall</a>, and <a class="mention" href="/u/birds_are_drones">@birds_are_drones</a> would be interested in adding this feautre?</p>

take-cheeze: <p>I think this would be a hard work to replace all symbolic aten(torch) to onnx operator function which is totally implemented in python.(see symbolic_opset*.py in <a href="https://github.com/pytorch/pytorch/tree/master/torch/onnx" class="inline-onebox" rel="noopener nofollow ugc">pytorch/torch/onnx at master · pytorch/pytorch · GitHub</a>)<br>
<code>torch.onnx.export</code> is a PyTorch’s feature, not libtorch’s feature</p>

TiStar: <p>Hello, has anyone of you been able to find a solution to this problem? I would also have the use case of C++ → Onnx → TensorRT. Thanks.</p>