Type notes to Python scripts for running PyTorch model in C ++ with libtorch

background

I want to trace a pytorch model (especially a voice processing system) (frozen model, tflite model in TensorFlow).

pytorch itself does some type inference, but it has its limits. Especially in the case of speech processing system, there are various codes other than the neural part. Also, since there are dynamic arrays and recursion, it is necessary to type appropriately.

environment

Assume pytorch v1.4.0 (latest stable as of 04/04/2020).

JIT model

https://pytorch.org/docs/stable/jit.html

Is the traced model ideal and the runner-up TorchScript?

It seems that you can combine both.

environment

Examine the type

You can step through the types of your current Python script to find out.

Should I use the Python debugger or ipython ... Will it be displayed on Jupyter lab?

I only know basic vim + command line execution, so I'm checking by inserting print (type (x)) etc. where I want each type ...

Type

https://pytorch.org/docs/stable/jit.html

For python2 etc. and 3.5, you can use torch.jit.annotate or write the type in the comment, but it is recommended to use the typing module and type annotation in the python syntax.

sample


def forward(self, x: List[torch.Tensor]) -> Tuple[torch.Tensor]:
  my_list: List[Tuple[int, float]] = []

You can feel that.

Optional

Like std :: optional in C ++, None or have some type, can be ʻOptional [T]`.

Optional[int]

@torch.jit.export

Normally, only the forward () method and the function called from forward are JIT compiled, but you can explicitly export (JIT compile) the method by using the @ torch.jit.export decorator. (forward is implicitly decorated with @ torch.jit.export)

nn.ModuleList

nn.ModuleList (array)

...
self.mods = nn.Modulelist([...])

for i in range(10):
  self.mods[i](x)

It is currently not possible to access by array index like.

[jit] Can't index nn.ModuleList in script function #16123 https://github.com/pytorch/pytorch/issues/16123

For the time being, it seems that iterate in the form of __constants__ and for mod in modules, but if you use multiple nn.ModuleList, you will have to redefine a dedicated class. Masu. However, in this case, the definition of network op changes (the name of state_dict changes), and the weight of the pretrained model needs to be dealt with well.

Also, in v1.5.0 (v1.6.0?), Array indexes with constants such as self.mods [0] have begun to be supported.

[JIT] Add modulelist indexing for integer literal #29236 https://github.com/pytorch/pytorch/pull/29236

An error occurred when evaluating (libtorch side) of TorchScript. (It has an expression like getattr (xxx, 10), which cannot be parsed at runtime)

We need to wait a little longer for maturity.

In addition, iterate nn.ModuleList does not support reverse iteration with reversed.

print, assert

In TorchScript, print, ʻassert` also works in TorchScript (maybe not in trace). It can be used to send a message for debugging.

Is the script running in the JIT?

When it is executed by scripting, you want to omit some processing, or None is expected, but when it is non None, the type is arbitrary, so you can not type with ʻOptional [T]`, so the processing is divided. I have a case I want.

torch.jit.is_scripting () determines whether the script is executed (executed by libtorch) at runtime, so it cannot be used to determine whether it is traced (compiled).

It would be nice to have some decorators, but there seems to be no current situation.

Therefore, it seems that it is not possible to switch between python and TorchScript for each function. As you can see in the torchscript documentation,

@torch.jit.ignore
def forward_pytorch():
  ...

def forward_for_torchscript():
  ...

def forward():
  if torch.jit.is_scripting():
    forward_for_torchscript()
  else
    foward_pytorch()

However, since the expression (statement) itself is the target of tracing, if there is code using numpy () etc., it will not be possible to compile and an error will occur. You need to function it as above and migrate the code that runs with pytorch (+ numpy) to @ torch.jit.ignore (because @ torch.jit.unused will be compiled)

_Flatten_parameters () in nn.RNN

The internally used GeneratorExp does not support TorchScript. It's for adjusting the memory layout for the GPU, so you can safely ignore it (delete the code).

Other

For unused and ignore, forward is defined, but this is for learning purposes, and can be used when you want to ignore it in TorchScript.

The difference between unused and ignore is that unused raises an exception when you call a method, but ignore does nothing when you call a method. Basically, it seems better to use unused.

F.pad(x, [0, 0, maxlen - m.size(2), 0])
         ^^^^^^^^^^^^^^^^^^^^^

It wasn't type inferred as List [int]. (M is torch.Tensor). It was solved by explicitly creating an int type variable.

.numpy()

It seems that .numpy () cannot be used. Eg x.cpu (). data.numpy (). On the C ++ side, aten handles it well, so you don't have to use .numpy (). maybe...? Also, it is desirable not to use the numpy function in the tracing code.

T.B.W.

Return type of the entry forward

It seems good to explicitly specify the type returned by forward of the model that will be the entry. This is to make it easier to see what type it is when running on the C ++ side. (If the types do not match, an assertion will be issued at runtime)

When returning only one Tensor, it can be treated as torch :: Tensor.

If you want to return multiple tensors, it will be Tuple, so

model.forward(inputs).toTuple()

will do.

TODO


def myfun(x, activation = None):
  if activation:
    x = activation(x)

  return x

myfun(activation=torch.relu)

What should I do when I want to handle something like an arbitrary function or None?

class Mod:
  def forward(self, x, alpha=1.0):
    ...

class Model:
  def __init__(self):
    self.mod = Mod()

  def forward(self, x):
    self.mod.forward(x)
    ...

Like, there is an optional argument in the forward of the class called internally. Should I delete it if I'm not actually using it?

Recommended Posts

Type notes to Python scripts for running PyTorch model in C ++ with libtorch
Type Python scripts to run in QGIS Processing
How to wrap C in Python
Python script written in PyTorch is converted to exe with PyInstaller
Try logging in to qiita with Python
WEB scraping with Python (for personal notes)
Memo to ask for KPI with python
Notes on nfc.ContactlessFrontend () for nfcpy in python
Tips for dealing with binaries in Python
Type annotations for Python2 in stub files!
How to work with BigQuery in Python
[Python] Introduction to CNN with Pytorch MNIST
Process multiple lists with for in Python
[With commentary] Solve Fizz Buzz (equivalent to paiza rank C) in Python
To work with timestamp stations in Python
An introduction to Python for C programmers
Notes for Python beginners with experience in other languages 12 (+1) items by function
Notes from installing Homebrew to building an Anaconda environment for Python with pyenv
A confusing story with two ways to implement XGBoost in Python + overall notes
Searching for an efficient way to write a Dockerfile in Python with poetry
Python learning notes for machine learning with Chainer Chapters 11 and 12 Introduction to Pandas Matplotlib
How to use the C library in Python
[REAPER] How to play with Reascript in Python
How to generate permutations in Python and C ++
Convert PDFs to images in bulk with Python
Wrap C with Cython for use from Python
Log in to Yahoo Business with Selenium Python
Boost.NumPy Tutorial for Extending Python in C ++ (Practice)
Try to calculate RPN in Python (for beginners)
Notes for implementing simple collaborative filtering in Python
How to use tkinter with python in pyenv
Wrap C ++ with Cython for use from Python
How to handle datetime type in python sqlite3
[Introduction for beginners] Working with MySQL in Python
Settings for getting started with MongoDB in python
python C ++ notes
[For beginners in competition professionals] I tried to solve 40 AOJ "ITP I" questions with python
C / Python> Read fwrite () value in C in Python> v0.1: 1 value / v0.2: 3 values / v0.3: corresponds to size_t / v0.4: Read double complex type
[For beginners] Web scraping with Python "Access the URL in the page to get the contents"
Tutorial to infer the model learned in Tensorflow with C ++/OpenVINO at high speed
Tool to make mask image for ETC in Python
[For beginners] How to use say command in python!
How to convert / restore a string with [] in python
Try to make a Python module in C language
[Unity (C #), Python] Try running Python code in Unity using IronPython
How to do hash calculation with salt in Python
Specific sample code for working with SQLite3 in Python
Explain in detail how to make sounds with python
Benchmark for C, Java and Python with prime factorization
How to run python in virtual space (for MacOS)
How to run tests in bulk with Python unittest
VS Code settings for developing in Python with completion
Try embedding Python in a C ++ program with pybind11
Convert the image in .zip to PDF with Python
Super Primer to python-Getting started with python3.5 in 3 minutes
Python --Notes when converting from str type to int type
[Introduction to python] A high-speed introduction to Python for busy C ++ programmers
I was addicted to scraping with Selenium (+ Python) in 2020
Reasons to use long type in SQLite3 (C # Mono.Data.Sqlite)
From buying a computer to running a program with python
For those who want to write Python with vim