Ich möchte ein Pytorch-Modell (insbesondere ein Sprachverarbeitungssystem) verfolgen (eingefrorenes Modell, Tflite-Modell in TensorFlow).
Pytorch selbst macht eine Art Inferenz, aber es hat seine Grenzen. Insbesondere im Sprachverarbeitungssystem gibt es verschiedene Codes außer dem neuronalen Teil. Da es dynamische Arrays und Wiederholungen gibt, ist es auch erforderlich, entsprechend zu tippen.
Angenommen, Pytorch v1.4.0 (letzter Stand vom 04.04.2020).
https://pytorch.org/docs/stable/jit.html
Ist das verfolgte Modell ideal und das zweitplatzierte TorchScript?
Es scheint, dass Sie beide kombinieren können.
Sie können die Typen Ihres aktuellen Python-Skripts durchgehen, um dies herauszufinden.
Soll ich einen Python-Debugger oder Ipython verwenden ... Wird es im Jupyter-Labor angezeigt?
Ich kenne nur die grundlegende Ausführung von vim + Befehlszeilen, daher überprüfe ich durch Einfügen von print (Typ (x)) usw., wo ich jeden Typ haben möchte ...
https://pytorch.org/docs/stable/jit.html
Für Python2 usw. und 3.5 können Sie "torch.jit.annotate" verwenden oder den Typ in den Kommentar schreiben. Es wird jedoch empfohlen, das "Typing" -Modul und die Typanmerkung in der Python-Syntax zu verwenden.
def forward(self, x: List[torch.Tensor]) -> Tuple[torch.Tensor]:
my_list: List[Tuple[int, float]] = []
Das kannst du fühlen.
Optional
Wie std :: optional in C ++ kann None oder mit einem Typ "Optional [T]" sein.
Optional[int]
@torch.jit.export
Normalerweise werden nur die Methode "forward ()" und die von forward aufgerufene Funktion JIT-kompiliert. Sie können die Methode jedoch explizit exportieren (JIT kompilieren), indem Sie den Dekorator "@ torch.jit.export" verwenden.
(Forward
ist implizit mit @ torch.jit.export
dekoriert)
nn.ModuleList
nn.ModuleList (Array)
...
self.mods = nn.Modulelist([...])
for i in range(10):
self.mods[i](x)
[jit] Can't index nn.ModuleList in script function #16123 https://github.com/pytorch/pytorch/issues/16123
[JIT] Add modulelist indexing for integer literal #29236 https://github.com/pytorch/pytorch/pull/29236
Derzeit scheint es, dass es durch Iteration in Form von "constants" und "for mod in modules" behandelt werden kann. Wenn Sie jedoch mehrere nn.ModuleList verwenden, müssen Sie eine dedizierte Klasse neu definieren. In diesem Fall muss jedoch die Definition von Netzwerkoperationsänderungen (der Name von state_dict ändert sich) und das Gewicht des vorab trainierten Modells gut behandelt werden. Auch in Version 1.5.0 (Version 1.6.0?) Wird self. Array-Indizes mit Konstanten wie mods [0]
werden allmählich unterstützt, aber bei der Auswertung (libtorch-Seite) von TorchScript ist ein Fehler aufgetreten. (Der Ausdruck ist wiegetattr (xxx, 10)
. Ich muss etwas länger warten (was zur Laufzeit nicht analysiert werden kann).
Darüber hinaus wird die umgekehrte Iteration mit "umgekehrt" beim Iterieren von nn.ModuleList nicht unterstützt.
print, assert
In TorchScript funktionieren print
und assert
auch in TorchScript (möglicherweise nicht in der Spur).
Es kann verwendet werden, um eine Nachricht zum Debuggen zu senden.
Wenn es per Skript ausgeführt wird, möchten Sie einige Verarbeitungen weglassen. Wenn Keine, aber keine angenommen wird, ist der Typ beliebig, sodass Sie nicht mit "Optional [T]" tippen können, sodass die Verarbeitung aufgeteilt wird. Ich habe einen Fall, den ich will.
torch.jit.is_scripting ()
bestimmt, ob das Skript zur Laufzeit ausgeführt (von libtorch ausgeführt) wird, sodass nicht bestimmt werden kann, ob es verfolgt (kompiliert) wird.
Es wäre schön, wenn es einige Dekorateure gäbe, aber es scheint keine aktuelle Situation zu geben.
Daher scheint es nicht möglich zu sein, funktionsweise zwischen Python und TorchScript zu wechseln. Wie Sie in der Torchscript-Dokumentation sehen können,
@torch.jit.ignore
def forward_pytorch():
...
def forward_for_torchscript():
...
def forward():
if torch.jit.is_scripting():
forward_for_torchscript()
else
foward_pytorch()
Da der Ausdruck (Anweisung) selbst das Ziel der Ablaufverfolgung ist, kann er bei Verwendung von Code mit numpy () usw. nicht kompiliert werden, und es tritt ein Fehler auf.
Sie müssen wie oben beschrieben funktionieren und den mit pytorch (+ numpy) ausgeführten Code nach @ torch.jit.ignore
migrieren (da @ torch.jit.unused
kompiliert werden muss).
Das intern verwendete GeneratorExp unterstützt TorchScript nicht. Hiermit können Sie das Speicherlayout für die GPU anpassen, damit Sie es ignorieren können (löschen Sie den Code).
@torch.jit.unused
decorator@torch.jit.ignore
decoratorFür nicht verwendet und ignoriert wird "Weiterleiten" definiert, dies dient jedoch zu Lernzwecken und kann verwendet werden, wenn Sie es in TorchScript ignorieren möchten.
Der Unterschied zwischen unbenutzt und ignorieren besteht darin, dass unbenutzt beim Aufrufen einer Methode eine Ausnahme auslöst, beim Aufrufen einer Methode jedoch ignoriert. Grundsätzlich scheint es besser, unbenutzte zu verwenden.
F.pad(x, [0, 0, maxlen - m.size(2), 0])
^^^^^^^^^^^^^^^^^^^^^
Es wurde nicht als "List [int]" vom Typ abgeleitet (M ist torch.Tensor). Es wurde gelöst, indem explizit eine Variable vom Typ int erstellt wurde.
.numpy()
Es scheint, dass .numpy ()
nicht verwendet werden kann. ZB x.cpu (). Data.numpy ()
. vielleicht...?
Es ist auch wünschenswert, die numpy-Funktion in dem zu verfolgenden Code nicht zu verwenden.
T.B.W.
Es scheint gut, den Typ, der von "forward" des Modells zurückgegeben wird, das der Eintrag sein wird, explizit anzugeben. Dies soll es einfacher machen zu verstehen, um welchen Typ es sich bei der Ausführung auf der C ++ - Seite handelt. (Wenn die Typen nicht übereinstimmen, wird zur Laufzeit eine Zusicherung ausgegeben.)
Wenn nur ein Tensor zurückgegeben wird, kann er als "torch :: Tensor" behandelt werden.
Wenn Sie mehrere Tensoren zurückgeben möchten, ist dies Tupel,
model.forward(inputs).toTuple()
Wird besorgt.
TODO
def myfun(x, activation = None):
if activation:
x = activation(x)
return x
myfun(activation=torch.relu)
Was soll ich tun, wenn ich so etwas wie eine beliebige Funktion oder Keine ausführen möchte?
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)
...
Es gibt ein optionales Argument in der Weiterleitung der Klasse, das intern wie in aufgerufen wird. Soll ich es löschen, wenn ich es nicht benutze?
Recommended Posts