PyTorch - Rete neurale ricorrente
Le reti neurali ricorrenti sono un tipo di algoritmo orientato al deep learning che segue un approccio sequenziale. Nelle reti neurali, assumiamo sempre che ogni input e output sia indipendente da tutti gli altri livelli. Questo tipo di reti neurali sono chiamate ricorrenti perché eseguono calcoli matematici in modo sequenziale completando un'attività dopo l'altra.
Il diagramma seguente specifica l'approccio completo e il funzionamento delle reti neurali ricorrenti:
Nella figura sopra, c1, c2, c3 e x1 sono considerati input che includono alcuni valori di input nascosti, vale a dire h1, h2 e h3 che forniscono il rispettivo output di o1. Ci concentreremo ora sull'implementazione di PyTorch per creare un'onda sinusoidale con l'aiuto di reti neurali ricorrenti.
Durante l'addestramento, seguiremo un approccio di addestramento al nostro modello con un punto dati alla volta. La sequenza di input x è composta da 20 punti dati e la sequenza di destinazione è considerata uguale alla sequenza di input.
Passo 1
Importa i pacchetti necessari per l'implementazione di reti neurali ricorrenti utilizzando il codice seguente:
import torch
from torch.autograd import Variable
import numpy as np
import pylab as pl
import torch.nn.init as init
Passo 2
Imposteremo i parametri iper del modello con la dimensione del livello di input impostata su 7. Ci saranno 6 neuroni di contesto e 1 neurone di input per la creazione della sequenza target.
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)
Genereremo i dati di addestramento, dove x è la sequenza dei dati di input ey è la sequenza di destinazione richiesta.
Passaggio 3
I pesi vengono inizializzati nella rete neurale ricorrente utilizzando la distribuzione normale con media zero. W1 rappresenterà l'accettazione delle variabili di input e w2 rappresenterà l'output generato come mostrato di seguito -
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)
Passaggio 4
Ora, è importante creare una funzione per il feed forward che definisca in modo univoco la rete neurale.
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)
Passaggio 5
Il passo successivo è avviare la procedura di addestramento dell'implementazione dell'onda sinusoidale della rete neurale ricorrente. Il ciclo esterno itera su ogni ciclo e il ciclo interno itera attraverso l'elemento di sequenza. Qui, calcoleremo anche Mean Square Error (MSE) che aiuta nella previsione di variabili continue.
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])
Passaggio 6
Ora è il momento di tracciare l'onda sinusoidale nel modo in cui è necessaria.
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()
Produzione
L'output per il processo di cui sopra è il seguente: