PyTorch-Modelle inferieren
Erfahren Sie mehr über PyTorch und wie Sie Inferenz mit PyTorch-Modellen durchführen.
PyTorch führt die Deep-Learning-Landschaft mit seiner leicht verständlichen und flexiblen API an; der großen Anzahl von verfügbaren fertigen Modellen, insbesondere im Bereich der natürlichen Sprachverarbeitung (NLP); sowie seinen domänenspezifischen Bibliotheken.
Ein wachsendes Ökosystem von Entwicklern und Anwendungen sucht nach Möglichkeiten, mit PyTorch erstellte Modelle zu nutzen, und dieser Artikel bietet eine schnelle Tour durch die Inferenz von PyTorch-Modellen. Es gibt eine Reihe verschiedener Möglichkeiten, Inferenz von PyTorch-Modellen durchzuführen; diese sind unten aufgeführt.
Dieser Artikel geht davon aus, dass Sie Informationen zur Durchführung von Inferenz mit Ihrem PyTorch-Modell suchen und nicht dazu, wie man ein PyTorch-Modell trainiert.
Inhalt
Überblick über PyTorch
Das Herzstück von PyTorch ist `nn.Module`, eine Klasse, die ein gesamtes Deep-Learning-Modell oder eine einzelne Schicht darstellt. Module können kombiniert oder erweitert werden, um Modelle zu erstellen. Um Ihr eigenes Modul zu schreiben, implementieren Sie eine Forward-Funktion, die Ausgaben basierend auf den Modelleingaben und den trainierten Gewichten des Modells berechnet. Wenn Sie Ihr eigenes PyTorch-Modell schreiben, trainieren Sie es wahrscheinlich auch. Alternativ können Sie vortrainierte Modelle von PyTorch selbst oder von anderen Bibliotheken wie HuggingFace verwenden.
Ein Bildverarbeitungsmodell mit PyTorch selbst codieren
import torch
import torch.nn as nn
import torchvision.transforms as T
from torchvision.models import resnet18, ResNet18_Weights
class Predictor(nn.Module):
def __init__(self):
super().__init__()
weights = ResNet18_Weights.DEFAULT
self.resnet18 = resnet18(weights=weights, progress=False).eval()
self.transforms = weights.transforms()
def forward(self, x: torch.Tensor) -> torch.Tensor:
with torch.no_grad():
x = self.transforms(x)
y_pred = self.resnet18(x)
return y_pred.argmax(dim=1)
Ein Sprachmodell mit der HuggingFace-Bibliothek erstellen Sie können
model_name = "bert-large-uncased-whole-word-masking-finetuned-squad"
tokenizer = transformers.BertTokenizer.from_pretrained(model_name)
model = transformers.BertForQuestionAnswering.from_pretrained(model_name)
Sobald Sie ein trainiertes Modell erstellt oder importiert haben, wie führen Sie es aus, um Inferenz durchzuführen? Nachfolgend beschreiben wir mehrere Ansätze, die Sie zur Durchführung von Inferenz in PyTorch verwenden können.
Inferenzoptionen
Inferenz mit nativem PyTorch
Wenn Sie nicht empfindlich auf Leistung oder Größe reagieren und in einer Umgebung laufen, die Python-Executables und -Bibliotheken enthält, können Sie Ihre Anwendung in nativem PyTorch ausführen.
Sobald Sie Ihr trainiertes Modell haben, gibt es zwei Methoden, mit denen Sie (oder Ihr Data-Science-Team) das Modell für die Inferenz speichern und laden können
-
Das gesamte Modell speichern und laden
# Save the entire model to PATH torch.save(model, PATH) # Load the model from PATH and set eval mode for inference model = torch.load(PATH) model.eval() -
Die Parameter des Modells speichern, das Modell neu deklarieren und die Parameter laden
# Save the model parameters torch.save(model.state_dict(), PATH) # Redeclare the model and load the saved parameters model = TheModel(...) model.load_state_dict(torch.load(PATH)) model.eval()
Welche dieser Methoden Sie verwenden, hängt von Ihrer Konfiguration ab. Das Speichern und Laden des gesamten Modells bedeutet, dass Sie das Modell nicht neu deklarieren müssen oder überhaupt Zugriff auf den Modellcode selbst haben. Der Nachteil ist jedoch, dass sowohl die Speicherumgebung als auch die Ladeumgebung in Bezug auf die verfügbaren Klassen, Methoden und Parameter übereinstimmen müssen (da diese direkt serialisiert und deserialisiert werden).
Das Speichern der trainierten Parameter des Modells (des Zustands-Wörterbuchs oder state_dict) ist flexibler als der erste Ansatz, solange Sie Zugriff auf den ursprünglichen Modellcode haben.
Es gibt zwei Hauptgründe, warum Sie möglicherweise nicht natives PyTorch zur Inferenz Ihres Modells verwenden möchten. Der erste ist, dass Sie in einer Umgebung laufen müssen, die eine Python-Laufzeit und die PyTorch-Bibliotheken und zugehörigen Abhängigkeiten enthält - diese summieren sich zu mehreren Gigabyte an Dateien. Wenn Sie in einer Umgebung wie einem Mobiltelefon, einem Webbrowser oder auf spezialisierter Hardware laufen möchten, funktioniert die PyTorch-Inferenz mit nativem PyTorch nicht. Der zweite ist die Leistung. Standardmäßig liefern PyTorch-Modelle möglicherweise nicht die Leistung, die Ihre Anwendung benötigt.
Inferenz mit TorchScript
Wenn Sie in einer eingeschränkteren Umgebung laufen, in der Sie PyTorch oder andere Python-Bibliotheken nicht installieren können, haben Sie die Möglichkeit, Inferenz mit PyTorch-Modellen durchzuführen, die in TorchScript konvertiert wurden. TorchScript ist eine Teilmenge von Python, die es Ihnen ermöglicht, serialisierbare Modelle zu erstellen, die in Nicht-Python-Umgebungen geladen und ausgeführt werden können.
# Export to TorchScript
script = torch.jit.script(model, example)
# Save scripted model
script.save(PATH)
# Load scripted model
model = torch.jit.load(PATH)
model.eval()
#include <torch/script.h>
...
torch::jit::script::Module module;
try {
// Deserialize the ScriptModule
module = torch::jit::load(PATH);
}
catch (const c10::Error& e) {
...
}
...
Obwohl Sie keine Python-Laufzeit in Ihrer Umgebung benötigen, um mit dem TorchScript-Ansatz Inferenz mit Ihrem PyTorch-Modell durchzuführen, müssen Sie die libtorch-Binärdateien installieren, und diese können für Ihre Umgebung zu groß sein. Möglicherweise erzielen Sie auch nicht die Leistung, die Sie für Ihre Anwendung benötigen.
Inferenz mit ONNXRuntime
Wenn Leistung und Portabilität an erster Stelle stehen, können Sie ONNXRuntime verwenden, um Inferenz mit einem PyTorch-Modell durchzuführen. Mit ONNXRuntime können Sie Latenz und Speicher reduzieren und den Durchsatz erhöhen. Sie können ein Modell auch in der Cloud, am Edge, im Web oder auf Mobilgeräten ausführen, indem Sie die Sprachbindungen und Bibliotheken verwenden, die mit ONNXRuntime geliefert werden.
Der erste Schritt ist der Export Ihres PyTorch-Modells in das ONNX-Format mithilfe des PyTorch ONNX-Exporters.
# Specify example data
example = ...
# Export model to ONNX format
torch.onnx.export(model, PATH, example)
Nachdem Sie in das ONNX-Format exportiert haben, können Sie das Modell optional im Netron-Viewer anzeigen, um den Modellgraphen, die Namen und Formen der Eingabe- und Ausgabeknoten sowie die Knoten mit variabel großen Ein- und Ausgaben (dynamische Achsen) zu verstehen.
Dann können Sie das ONNX-Modell in der Umgebung Ihrer Wahl ausführen. Die ONNXRuntime-Engine ist in C++ implementiert und verfügt über APIs in C++, Python, C#, Java, Javascript, Julia und Ruby. ONNXRuntime kann Ihr Modell unter Linux, Mac, Windows, iOS und Android ausführen. Das folgende Code-Snippet zeigt beispielsweise ein Skelett einer C++-Inferenzanwendung.
// Allocate ONNXRuntime session
auto memory_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);
Ort::Env env;
Ort::Session session{env, ORT_TSTR("model.onnx"), Ort::SessionOptions{nullptr}};
// Allocate model inputs: fill in shape and size
std::array<float, ...> input{};
std::array<int64_t, ...> input_shape{...};
Ort::Value input_tensor = Ort::Value::CreateTensor<float>(memory_info, input.data(), input.size(), input_shape.data(), input_shape.size());
const char* input_names[] = {...};
// Allocate model outputs: fill in shape and size
std::array<float, ...> output{};
std::array<int64_t, ...> output_shape{...};
Ort::Value output_tensor = Ort::Value::CreateTensor<float>(memory_info, output.data(), output.size(), output_shape.data(), output_shape.size());
const char* output_names[] = {...};
// Run the model
session_.Run(Ort::RunOptions{nullptr}, input_names, &input_tensor, 1, output_names, &output_tensor, 1);
Standardmäßig wendet ONNXRuntime eine Reihe von Optimierungen auf den ONNX-Graphen an, kombiniert Knoten, wo möglich, und faktoriert konstante Werte aus (Constant Folding). ONNXRuntime integriert sich auch über seine Execution Provider-Schnittstelle mit einer Reihe von Hardwarebeschleunigern, darunter CUDA, TensorRT, OpenVINO, CoreML und NNAPI, je nachdem, welche Hardwareplattform Sie ansprechen.
Sie können die Leistung des ONNX-Modells weiter verbessern, indem Sie es quantisieren.
Wenn die Anwendung in eingeschränkten Umgebungen wie Mobilgeräten und Edge-Geräten läuft, können Sie eine Laufzeitumgebung mit reduziertem Umfang erstellen, die auf dem Modell oder der Menge von Modellen basiert, die die Anwendung ausführt.
Um in Ihrer bevorzugten Sprache und Umgebung loszulegen, siehe Erste Schritte mit ONNX Runtime
Beispiele
Modell nach ONNX exportieren
- Basischer PyTorch-Export über torch.onnx
- Super-Resolution mit ONNX Runtime
- PyTorch-Modell mit benutzerdefinierten Operationen exportieren
Beschleunigte Inferenz mit ONNXRuntime
- BERT-Modell auf CPU beschleunigen
- BERT-Modell auf GPU beschleunigen
-
BERT-Modell mit reduzierter Größe durch Quantisierung beschleunigen
- GPT2 auf CPU beschleunigen