PyTorch - Réseau neuronal récurrent

Les réseaux de neurones récurrents sont un type d'algorithme axé sur l'apprentissage profond qui suit une approche séquentielle. Dans les réseaux de neurones, nous supposons toujours que chaque entrée et sortie est indépendante de toutes les autres couches. Ces types de réseaux de neurones sont appelés récurrents car ils effectuent des calculs mathématiques de manière séquentielle en complétant une tâche après l'autre.

Le schéma ci-dessous spécifie l'approche complète et le fonctionnement des réseaux de neurones récurrents -

Sur la figure ci-dessus, c1, c2, c3 et x1 sont considérés comme des entrées qui comprennent certaines valeurs d'entrée cachées à savoir h1, h2 et h3 délivrant la sortie respective de o1. Nous allons maintenant nous concentrer sur la mise en œuvre de PyTorch pour créer une onde sinusoïdale à l'aide de réseaux de neurones récurrents.

Pendant la formation, nous suivrons une approche de formation de notre modèle avec un point de données à la fois. La séquence d'entrée x se compose de 20 points de données et la séquence cible est considérée comme la même que la séquence d'entrée.

Étape 1

Importez les packages nécessaires pour implémenter des réseaux de neurones récurrents en utilisant le code ci-dessous -

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

Étape 2

Nous allons définir les hyper paramètres du modèle avec la taille de la couche d'entrée fixée à 7. Il y aura 6 neurones de contexte et 1 neurone d'entrée pour créer la séquence cible.

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)

Nous allons générer des données d'entraînement, où x est la séquence de données d'entrée et y est la séquence cible requise.

Étape 3

Les poids sont initialisés dans le réseau neuronal récurrent en utilisant une distribution normale avec une moyenne nulle. W1 représentera l'acceptation des variables d'entrée et w2 représentera la sortie qui est générée comme indiqué ci-dessous -

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)

Étape 4

Maintenant, il est important de créer une fonction de feed-back qui définit de manière unique le réseau neuronal.

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)

Étape 5

L'étape suivante consiste à démarrer la procédure de formation de l'implémentation de l'onde sinusoïdale récurrente du réseau neuronal. La boucle externe parcourt chaque boucle et la boucle interne parcourt l'élément de séquence. Ici, nous allons également calculer l'erreur quadratique moyenne (MSE) qui aide à la prédiction des variables continues.

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

Étape 6

Maintenant, il est temps de tracer l'onde sinusoïdale selon les besoins.

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

Production

La sortie pour le processus ci-dessus est la suivante -