Tapez des notes sur les scripts Python pour exécuter le modèle PyTorch en C ++ avec libtorch

Contexte

Je souhaite tracer un modèle pytorch (en particulier un système de traitement de la voix) (modèle gelé, modèle tflite dans TensorFlow).

pytorch lui-même fait des inférences de types, mais il a ses limites. En particulier dans le système de traitement de la voix, il existe différents codes autres que la partie neuronale.De plus, comme il existe des tableaux dynamiques et des récidives, il est nécessaire de taper de manière appropriée.

environnement

Supposons que pytorch v1.4.0 (dernière stable au 04/04/2020).

Modèle JIT

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

Le modèle tracé est-il idéal et le second TorchScript?

Il semble que vous puissiez combiner les deux.

environnement

Examiner le type

Vous pouvez parcourir les types de votre script Python actuel pour le découvrir.

Dois-je utiliser un débogueur Python ou ipython ... Sera-t-il affiché dans le laboratoire Jupyter?

Je ne connais que l'exécution de base de la ligne de commande vim +, donc je vérifie en insérant print (type (x)) etc. où je veux chaque type ...

Type

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

Pour python2 etc. et 3.5, vous pouvez utiliser torch.jit.annotate ou écrire le type dans le commentaire, mais il est recommandé d'utiliser le module typing et de taper l'annotation dans la syntaxe python.

échantillon


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

Vous pouvez le sentir.

Optional

Comme std :: optionnel en C ++, None ou avoir un type peut être ʻOptional [T] `.

Optional[int]

@torch.jit.export

Normalement, seules la méthode forward () et la fonction appelée depuis forward sont compilées JIT, mais vous pouvez explicitement exporter (compiler JIT) la méthode en utilisant le décorateur @ torch.jit.export. (Forward est implicitement décoré avec @ torch.jit.export)

nn.ModuleList

nn.ModuleList (tableau)

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

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

Il n'est actuellement pas possible d'accéder par index de tableau comme.

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

Pour le moment, il semble que cela puisse être géré par itération sous la forme de __constants__ et for mod in modules, mais si vous utilisez plusieurs nn.ModuleList, vous devrez redéfinir une classe dédiée. Masu. Cependant, dans ce cas, la définition des opérations réseau change (le nom de state_dict change), et le poids du modèle pré-entraîné doit être bien traité.

De plus, dans la v1.5.0 (v1.6.0?), Les index Array avec des constantes telles que self.mods [0] ont commencé à être supportés.

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

Une erreur s'est produite lors de l'évaluation de TorchScript (côté libtorch). (Il a une expression comme getattr (xxx, 10), qui ne peut pas être analysée à l'exécution)

Il faut attendre encore un peu la maturité.

De plus, il ne prend pas en charge l'itération inverse avec reverse lors de l'itération de nn.ModuleList.

print, assert

Dans TorchScript, print, ʻassert` fonctionnent également dans TorchScript (peut-être pas dans trace). Il peut être utilisé pour envoyer un message de débogage.

Le script s'exécute-t-il dans JIT?

Quand il est exécuté par script, certains traitements sont omis, ou Aucun est supposé, mais quand il est non None, le type est arbitraire, donc il ne peut pas être tapé avec ʻOptional [T] `, donc le traitement est divisé. J'ai un étui que je veux.

torch.jit.is_scripting () détermine si le script est exécuté (exécuté par libtorch) à l'exécution, il ne peut donc pas être utilisé pour déterminer s'il est tracé (compilé).

Ce serait bien s'il y avait des décorateurs, mais il ne semble pas y avoir de situation actuelle.

Par conséquent, il semble qu'il n'est pas possible de basculer entre python et TorchScript fonction par fonction. Comme vous pouvez le voir dans la documentation torchscript,

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

def forward_for_torchscript():
  ...

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

Cependant, puisque l'expression (instruction) elle-même est la cible du traçage, s'il y a du code utilisant numpy () etc., il ne pourra pas compiler et une erreur se produira. Vous devez le faire fonctionner comme ci-dessus et migrer le code qui fonctionne avec pytorch (+ numpy) vers @ torch.jit.ignore (car @ torch.jit.unused est soumis à la compilation).

_flatten_parameters () dans nn.RNN

GeneratorExp utilisé en interne ne prend pas en charge TorchScript. C'est pour ajuster la disposition de la mémoire pour le GPU, afin que vous puissiez l'ignorer en toute sécurité (supprimer le code).

Autre

Pour inutilisé et ignorer, forward est défini, mais c'est à des fins d'apprentissage et peut être utilisé lorsque vous voulez l'ignorer dans TorchScript.

La différence entre non utilisé et ignorer est que non utilisé déclenche une exception lorsque vous appelez une méthode, mais ignore ne fait rien lorsque vous appelez une méthode.

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

Il n'a pas été déduit de type comme List [int] (M est torch.Tensor). Il a été résolu en créant explicitement une variable de type int.

.numpy()

Il semble que .numpy () ne puisse pas être utilisé. Par exemple x.cpu (). Data.numpy (). Du côté C ++, aten le gère bien, vous n'avez donc pas à utiliser .numpy (). peut être...? En outre, il est souhaitable de ne pas utiliser la fonction numpy dans le code à tracer.

T.B.W.

Type de retour de l'entrée «avant»

Il semble bon de spécifier explicitement le type renvoyé par forward du modèle qui sera l'entrée. Cela permet de mieux comprendre de quel type il s'agit lors de l'exécution côté C ++. (Si les types ne correspondent pas, une assertion sera émise lors de l'exécution)

Lors du retour d'un seul Tensor, il peut être traité comme torch :: Tensor.

Si vous souhaitez renvoyer plusieurs tenseurs, ce sera Tuple,

model.forward(inputs).toTuple()

ça ira.

TODO


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

  return x

myfun(activation=torch.relu)

Que dois-je faire lorsque je souhaite gérer quelque chose comme une fonction arbitraire ou Aucune?

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)
    ...

Il y a un argument facultatif dans l'avant de la classe appelée en interne, comme dans. Dois-je le supprimer si je ne l'utilise pas réellement?

Recommended Posts

Tapez des notes sur les scripts Python pour exécuter le modèle PyTorch en C ++ avec libtorch
Comment envelopper C en Python
Convertir un script Python écrit dans PyTorch en exe avec PyInstaller
Essayez de vous connecter à qiita avec Python
Grattage WEB avec Python (pour mémo personnel)
Mémo pour demander des KPI avec python
Note de nfc.ContactlessFrontend () de nfcpy de python
Conseils pour gérer les binaires en Python
Tapez les annotations pour Python2 dans les fichiers stub!
Comment utiliser BigQuery en Python
Traiter plusieurs listes avec for en Python
[Avec commentaire] Résoudre Fizz Buzz (équivalent au rang C de paiza) avec Python
Pour faire fonctionner la station d'horodatage en Python
Une introduction à Python pour les programmeurs en langage C
Notes pour les débutants en Python ayant de l'expérience dans d'autres langues 12 (+1) éléments par fonction
Notes de l'installation de Homebrew à la création d'un environnement Anaconda pour Python avec pyenv
Une histoire déroutante avec deux façons d'implémenter XGBoost en Python + notes générales
Recherche d'un moyen efficace d'écrire un Dockerfile avec Python avec de la poésie
Mémo d'apprentissage Python pour l'apprentissage automatique par Chainer Chapitres 11 et 12 Introduction à Pandas Matplotlib
Comment utiliser la bibliothèque C en Python
[REAPER] Comment jouer à Reascript avec Python
Comment générer une séquence en Python et C ++
Convertissez des PDF en images en masse avec Python
Envelopper C avec Cython pour une utilisation à partir de Python
Connectez-vous à Yahoo Business avec Selenium Python
Tutoriel Boost.NumPy pour l'extension de Python en C ++ (pratique)
Essayez de calculer RPN avec Python (pour les débutants)
Notes pour la mise en œuvre d'un co-filtrage simple en Python
Comment utiliser tkinter avec python dans pyenv
Envelopper C ++ avec Cython pour une utilisation à partir de Python
Comment gérer le type datetime dans sqlite3 de python
[Introduction pour les débutants] Manipuler MySQL avec Python
Paramètres pour démarrer avec MongoDB avec python
notes de python C ++
[Pour les professionnels de la compétition débutants] J'ai essayé de résoudre 40 questions AOJ "ITP I" avec python
C / Python> Lire la valeur fwrite () en C avec Python> v0.1: 1 valeur / v0.2: 3 valeurs / v0.3: correspond à size_t / v0.4: lire le type complexe double
[Pour les débutants] Web scraping avec Python "Accédez à l'URL de la page pour obtenir le contenu"
Un outil pour créer des images de masque pour ETC en Python
[Pour les débutants] Comment utiliser la commande say avec python!
Comment convertir / restaurer une chaîne avec [] en python
Essayez de créer un module Python en langage C
Comment faire un calcul de hachage avec Salt en Python
Exemple de code spécifique pour travailler avec SQLite3 en Python
Expliquez en détail comment créer un son avec python
Benchmarks langage C, Java, Python avec factorisation prime
Comment exécuter python dans l'espace virtuel (pour MacOS)
Comment exécuter des tests avec Python unittest
Paramètres VS Code pour le développement en Python avec achèvement
Essayez d'incorporer Python dans un programme C ++ avec pybind11
Convertissez l'image au format .zip en PDF avec Python
Super Primer to python - Premiers pas avec python3.5 en 3 minutes
Python - Remarques lors de la conversion du type str en type int
[Introduction à python] Introduction rapide à Python pour les programmeurs C ++ occupés
J'étais accro au grattage avec Selenium (+ Python) en 2020
De l'achat d'un ordinateur à l'exécution d'un programme sur python
Pour ceux qui veulent écrire Python avec vim