PyTorch - Wiederkehrendes neuronales Netzwerk

Wiederkehrende neuronale Netze sind eine Art von Deep-Learning-orientiertem Algorithmus, der einem sequentiellen Ansatz folgt. In neuronalen Netzen gehen wir immer davon aus, dass jeder Ein- und Ausgang unabhängig von allen anderen Schichten ist. Diese Art von neuronalen Netzen wird als wiederkehrend bezeichnet, da sie nacheinander mathematische Berechnungen durchführen und eine Aufgabe nach der anderen ausführen.

Das folgende Diagramm zeigt den vollständigen Ansatz und die Funktionsweise wiederkehrender neuronaler Netze.

In der obigen Figur werden c1, c2, c3 und x1 als Eingaben betrachtet, die einige versteckte Eingabewerte enthalten, nämlich h1, h2 und h3, die die jeweilige Ausgabe von o1 liefern. Wir werden uns nun auf die Implementierung von PyTorch konzentrieren, um mithilfe wiederkehrender neuronaler Netze eine Sinuswelle zu erzeugen.

Während des Trainings verfolgen wir einen Trainingsansatz für unser Modell mit jeweils einem Datenpunkt. Die Eingabesequenz x besteht aus 20 Datenpunkten, und die Zielsequenz wird als dieselbe wie die Eingabesequenz angesehen.

Schritt 1

Importieren Sie die erforderlichen Pakete zum Implementieren wiederkehrender neuronaler Netze mit dem folgenden Code:

import torch
from torch.autograd import Variable
import numpy as np
import pylab as pl
import torch.nn.init as init

Schritt 2

Wir werden die Modell-Hyperparameter mit der Größe der Eingabeebene auf 7 setzen. Es werden 6 Kontextneuronen und 1 Eingangsneuron zum Erstellen der Zielsequenz vorhanden sein.

dtype = torch.FloatTensor
input_size, hidden_size, output_size = 7, 6, 1
epochs = 300
seq_length = 20
lr = 0.1
data_time_steps = np.linspace(2, 10, seq_length + 1)
data = np.sin(data_time_steps)
data.resize((seq_length + 1, 1))

x = Variable(torch.Tensor(data[:-1]).type(dtype), requires_grad=False)
y = Variable(torch.Tensor(data[1:]).type(dtype), requires_grad=False)

Wir werden Trainingsdaten generieren, wobei x die Eingabedatensequenz und y die erforderliche Zielsequenz ist.

Schritt 3

Die Gewichte werden im wiederkehrenden neuronalen Netzwerk unter Verwendung der Normalverteilung mit dem Mittelwert Null initialisiert. W1 repräsentiert die Akzeptanz von Eingangsvariablen und w2 repräsentiert die Ausgabe, die wie unten gezeigt erzeugt wird -

w1 = torch.FloatTensor(input_size, 
hidden_size).type(dtype)
init.normal(w1, 0.0, 0.4)
w1 = Variable(w1, requires_grad = True)
w2 = torch.FloatTensor(hidden_size, output_size).type(dtype)
init.normal(w2, 0.0, 0.3)
w2 = Variable(w2, requires_grad = True)

Schritt 4

Jetzt ist es wichtig, eine Funktion für die Vorwärtskopplung zu erstellen, die das neuronale Netzwerk eindeutig definiert.

def forward(input, context_state, w1, w2):
   xh = torch.cat((input, context_state), 1)
   context_state = torch.tanh(xh.mm(w1))
   out = context_state.mm(w2)
   return (out, context_state)

Schritt 5

Der nächste Schritt besteht darin, mit dem Trainingsverfahren für die Sinuswellenimplementierung eines wiederkehrenden neuronalen Netzwerks zu beginnen. Die äußere Schleife durchläuft jede Schleife und die innere Schleife durchläuft das Sequenzelement. Hier berechnen wir auch den Mean Square Error (MSE), der bei der Vorhersage kontinuierlicher Variablen hilft.

for i in range(epochs):
   total_loss = 0
   context_state = Variable(torch.zeros((1, hidden_size)).type(dtype), requires_grad = True)
   for j in range(x.size(0)):
      input = x[j:(j+1)]
      target = y[j:(j+1)]
      (pred, context_state) = forward(input, context_state, w1, w2)
      loss = (pred - target).pow(2).sum()/2
      total_loss += loss
      loss.backward()
      w1.data -= lr * w1.grad.data
      w2.data -= lr * w2.grad.data
      w1.grad.data.zero_()
      w2.grad.data.zero_()
      context_state = Variable(context_state.data)
   if i % 10 == 0:
      print("Epoch: {} loss {}".format(i, total_loss.data[0]))

context_state = Variable(torch.zeros((1, hidden_size)).type(dtype), requires_grad = False)
predictions = []

for i in range(x.size(0)):
   input = x[i:i+1]
   (pred, context_state) = forward(input, context_state, w1, w2)
   context_state = context_state
   predictions.append(pred.data.numpy().ravel()[0])

Schritt 6

Jetzt ist es an der Zeit, die Sinuswelle so zu zeichnen, wie sie benötigt wird.

pl.scatter(data_time_steps[:-1], x.data.numpy(), s = 90, label = "Actual")
pl.scatter(data_time_steps[1:], predictions, label = "Predicted")
pl.legend()
pl.show()

Ausgabe

Die Ausgabe für den obigen Prozess ist wie folgt: