Dies ist die fünfte Ausgabe von PyTorch Official Tutorial nach Last time. Diesmal ist der zweite Teil von PyTorch mit Beispielen lernen. Teil 1 ist hier.
3.1. PyTorch: nn
Sie können ein neuronales Netzwerk nicht allein mit Autograd modellieren. Das nn-Paket wird zum Erstellen des Modells verwendet. Das nn-Paket enthält auch eine sequentielle Klasse, die die Eingabe-, ausgeblendeten und Ausgabeebenen definiert, sowie eine Verlustfunktion. Im folgenden Beispiel wird das Paket nn verwendet, um ein zweistufiges Netzwerk zu implementieren.
import torch
#N: Chargengröße
# D_in: Anzahl der Eingangsdimensionen
#H: Anzahl der Dimensionen der verborgenen Schicht
# D_out: Anzahl der Ausgangsabmessungen
N, D_in, H, D_out = 64, 1000, 100, 10
#Erstellen Sie zufällige Eingabe- und Lehrerdaten
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
# Use the nn package to define our model as a sequence of layers. nn.Sequential
# is a Module which contains other Modules, and applies them in sequence to
# produce its output. Each Linear Module computes output from input using a
# linear function, and holds internal Tensors for its weight and bias.
#Verwenden Sie das Paket nn, um das Modell als eine Reihe von Ebenen zu definieren.
# nn.Sequential wendet die anderen Module nacheinander an, um das Modell zu generieren.
#Linear verwendet lineare Funktionen, um die Ausgabe aus der Eingabe sowie Gewichte und Vorspannungen zu berechnen
#Halten Sie den internen Tensor ein.
model = torch.nn.Sequential(
torch.nn.Linear(D_in, H),
torch.nn.ReLU(),
torch.nn.Linear(H, D_out),
)
#Das nn-Paket enthält auch eine Verlustfunktion.
#Dieses Mal verwenden wir den mittleren quadratischen Fehler (MSE) als Verlustfunktion.
loss_fn = torch.nn.MSELoss(reduction='sum')
learning_rate = 1e-4
for t in range(500):
#Vorwärtsausbreitung: Berechnet den vorhergesagten Wert y durch Übergabe von x an das Modell.
#Das Basisklassenmodul__call__Den Operator überschreiben
#Es kann wie eine Funktion aufgerufen werden.
#Übergeben Sie in diesem Fall den Eingangsdatentensor an das Modul und generieren Sie den Ausgangsdatentensor.
y_pred = model(x)
#Berechnet und gibt den Verlust aus.
#Übergabe des vorhergesagten Wertes von y und des Tensors der Lehrerdaten an die Verlustfunktion
#Gibt den Tensor zurück, der den Verlust enthält.
loss = loss_fn(y_pred, y)
if t % 100 == 99:
print(t, loss.item())
#Setzen Sie den Gradienten auf Null, bevor Sie die Backpropagation berechnen.
model.zero_grad()
#Backpropagation: Berechnet den Verlustgradienten.
#Intern erfordern Modulparameter_grad =Weil es als wahr gehalten wird
#Berechnen Sie den Gradienten aller Parameter.
loss.backward()
#Aktualisieren Sie die Gewichte mithilfe der probabilistischen Gradientenabstiegsmethode.
with torch.no_grad():
for param in model.parameters():
param -= learning_rate * param.grad
3.2. PyTorch: optim
Bisher habe ich die Modellgewichte selbst wie folgt berechnet und aktualisiert:
param -= learning_rate * param.grad
Diese Berechnungsmethode wird als stochastische Gradientenabstiegsmethode bezeichnet. Es gibt andere Möglichkeiten, Modellgewichte zu berechnen (Optimierer), und Sie können erweiterte Algorithmen wie AdaGrad, RMSProp und Adam verwenden. Das Optimierungspaket von PyTorch verfügt über eine Vielzahl von Optimierungsalgorithmen. Das folgende Beispiel definiert das Modell im nn-Paket wie im obigen Beispiel, verwendet jedoch den Adam-Algorithmus im optim-Paket, um die Gewichte zu aktualisieren.
import torch
#N: Chargengröße
# D_in: Anzahl der Eingangsdimensionen
#H: Anzahl der Dimensionen der verborgenen Schicht
# D_out: Anzahl der Ausgangsabmessungen
N, D_in, H, D_out = 64, 1000, 100, 10
#Erstellen Sie zufällige Eingabe- und Lehrerdaten
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
#Verwenden Sie das Paket nn, um das Modell und die Verlustfunktion zu definieren.
model = torch.nn.Sequential(
torch.nn.Linear(D_in, H),
torch.nn.ReLU(),
torch.nn.Linear(H, D_out),
)
loss_fn = torch.nn.MSELoss(reduction='sum')
#Verwenden Sie das Optimierungspaket, um einen Optimierungsalgorithmus (Optimierer) zu definieren, der die Modellgewichte aktualisiert.
#Wir werden Adam hier benutzen.
#Das Optimierungspaket enthält viele andere Optimierungsalgorithmen.
#Das erste Argument für den Adam-Konstruktor gibt an, welcher Tensor aktualisiert werden soll.
learning_rate = 1e-4
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
for t in range(500):
#Vorwärtsausbreitung: Berechnet den vorhergesagten Wert y durch Übergabe von x an das Modell.
y_pred = model(x)
#Berechnet und gibt den Verlust aus.
loss = loss_fn(y_pred, y)
if t % 100 == 99:
print(t, loss.item())
#Setzen Sie alle Gradienten der zu aktualisierenden Variablen (Gewichtung) auf Null, bevor Sie die Backpropagation berechnen.
#Dies liegt daran, dass der Gradient bei jedem Rückwärtsaufruf akkumuliert (nicht überschrieben) wird.
optimizer.zero_grad()
#Backpropagation: Berechnet den Verlustgradienten.
loss.backward()
#Die Parameter werden aktualisiert, wenn Sie die Optimierungsschrittfunktion aufrufen.
optimizer.step()
3.3. PyTorch: Custom nn Modules
Wenn Sie ein komplexes Modell erstellen möchten, können Sie nn.Module unterordnen. Sie können Ihr eigenes Modul definieren, indem Sie die Vorwärtsfunktion in der Unterklasse überschreiben und den Vorgang zum Zurückgeben des Ausgabe-Tensors vom Eingabe-Tensor schreiben. In diesem Beispiel implementieren wir ein zweistufiges Netzwerk als benutzerdefinierte Modulunterklasse.
import torch
class TwoLayerNet(torch.nn.Module):
def __init__(self, D_in, H, D_out):
"""
Im Konstruktor sind zwei nn.Instanziieren Sie ein lineares Modul
Weisen Sie sie als Mitgliedsvariablen zu.
"""
super(TwoLayerNet, self).__init__()
self.linear1 = torch.nn.Linear(D_in, H)
self.linear2 = torch.nn.Linear(H, D_out)
def forward(self, x):
"""
Die Vorwärtsfunktion sollte einen Ausgangstensor basierend auf dem Eingangstensor zurückgeben.
Sie können die im Konstruktor definierten Module verwenden.
"""
h_relu = self.linear1(x).clamp(min=0)
y_pred = self.linear2(h_relu)
return y_pred
#N: Chargengröße
# D_in: Anzahl der Eingangsdimensionen
#H: Anzahl der Dimensionen der verborgenen Schicht
# D_out: Anzahl der Ausgangsabmessungen
N, D_in, H, D_out = 64, 1000, 100, 10
#Erstellen Sie zufällige Eingabe- und Lehrerdaten
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
#Erstellen Sie ein Modell, indem Sie das oben definierte neuronale Netzwerkmodul instanziieren
model = TwoLayerNet(D_in, H, D_out)
#Verlustfunktion und Optimierungsalgorithmus(Optimierer)Ist definiert.
#SGD-Argumentmodell.parameters()Ist ein Mitglied der definierten Klasse
#2 nn.Es enthält auch die Parameter für das lineare Modul.
criterion = torch.nn.MSELoss(reduction='sum')
optimizer = torch.optim.SGD(model.parameters(), lr=1e-4)
for t in range(500):
#Vorwärtsausbreitung: Berechnet den vorhergesagten Wert y durch Übergabe von x an das Modell.
y_pred = model(x)
#Berechnet und gibt den Verlust aus.
loss = criterion(y_pred, y)
if t % 100 == 99:
print(t, loss.item())
#Setzen Sie den Gradienten auf Null, berechnen Sie die Backpropagation und aktualisieren Sie die Gewichte.
optimizer.zero_grad()
loss.backward()
optimizer.step()
3.4. PyTorch: Control Flow + Weight Sharing
Implementieren Sie ein spezielles Modell als Beispiel für dynamische Grafik und Gewichtsverteilung. Das folgende ReLU-Netzwerk berechnet, indem es mit der Vorwärtsfunktion eine Zufallszahl von 0 bis 3 auswählt und das gleiche Gewicht auf mehrere verborgene Schichten verteilt. Implementieren Sie dieses Modell als Modulunterklasse.
import random
import torch
class DynamicNet(torch.nn.Module):
def __init__(self, D_in, H, D_out):
"""
Im Konstruktor werden die drei nn in der Vorwärtsfunktion verwendet.Lineare Instanz(Eingabeebene, versteckte Ebene, Ausgabeebene)Ein ... kreieren.
"""
super(DynamicNet, self).__init__()
self.input_linear = torch.nn.Linear(D_in, H)
self.middle_linear = torch.nn.Linear(H, H)
self.output_linear = torch.nn.Linear(H, D_out)
def forward(self, x):
"""
Die Vorwärtsfunktion wählt zufällig einen Wert von 0 bis 3 Mal aus.
middle_Verwenden Sie das lineare Modul mehrmals, um die Verarbeitung versteckter Schichten zu berechnen.
Da Autograd ein dynamischer Berechnungsgraph ist, wird er während der Vorwärtsausbreitung erstellt.
Daher können Sie in der Forward-Funktion normale Python-Verarbeitung wie Schleifen und bedingte Anweisungen schreiben.
Sie können dasselbe Modul mehrmals verwenden, wenn Sie einen Berechnungsgraphen definieren.
Dies ist eine Verbesserung gegenüber Lua Torch, bei der jedes Modul nur einmal verwendet werden konnte.
"""
h_relu = self.input_linear(x).clamp(min=0)
for _ in range(random.randint(0, 3)):
h_relu = self.middle_linear(h_relu).clamp(min=0)
print(str(_))
print(h_relu.size())
y_pred = self.output_linear(h_relu)
return y_pred
#N: Chargengröße
# D_in: Anzahl der Eingangsdimensionen
#H: Anzahl der Dimensionen der verborgenen Schicht
# D_out: Anzahl der Ausgangsabmessungen
N, D_in, H, D_out = 64, 1000, 100, 10
#Erstellen Sie zufällige Eingabe- und Lehrerdaten
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
#Erstellen Sie ein Modell, indem Sie das oben definierte neuronale Netzwerkmodul instanziieren
model = DynamicNet(D_in, H, D_out)
#Erstellen Sie eine Verlustfunktion und einen Optimierer.
#Dieses Modell wird nach der üblichen stochastischen Gradientenabstiegsmethode trainiert(Konvergieren)Ist schwierig, geben Sie also den Impuls an.
criterion = torch.nn.MSELoss(reduction='sum')
optimizer = torch.optim.SGD(model.parameters(), lr=1e-4, momentum=0.9)
for t in range(500):
#Vorwärtsausbreitung: Berechnet den vorhergesagten Wert y durch Übergabe von x an das Modell.
y_pred = model(x)
#Berechnet und gibt den Verlust aus.
loss = criterion(y_pred, y)
if t % 100 == 99:
print(t, loss.item())
#Setzen Sie den Gradienten auf Null, berechnen Sie die Backpropagation und aktualisieren Sie die Gewichte.
optimizer.zero_grad()
loss.backward()
optimizer.step()
Das ist der Inhalt von PyTorchs fünftem Tutorial "PyTorch anhand von Beispielen lernen". Ich konnte mein Verständnis des Pakets autograd, torch.nn und torch.optim vertiefen.
Das nächste Mal möchte ich mit dem sechsten Tutorial "Was ist torch.nn wirklich?" fortfahren.
2020/07/10 Erste Ausgabe veröffentlicht 2020/07/10 Linkkorrektur des ersten Teils
Recommended Posts