PyTorch - Rede Neural Recorrente
Redes neurais recorrentes são um tipo de algoritmo orientado para aprendizagem profunda que segue uma abordagem sequencial. Em redes neurais, sempre assumimos que cada entrada e saída é independente de todas as outras camadas. Esses tipos de redes neurais são chamados de recorrentes porque executam cálculos matemáticos de maneira sequencial, completando uma tarefa após a outra.
O diagrama abaixo especifica a abordagem completa e o funcionamento das redes neurais recorrentes -
Na figura acima, c1, c2, c3 e x1 são considerados como entradas que incluem alguns valores de entrada ocultos, nomeadamente h1, h2 e h3, fornecendo a respectiva saída de o1. Agora vamos nos concentrar na implementação do PyTorch para criar uma onda senoidal com a ajuda de redes neurais recorrentes.
Durante o treinamento, seguiremos uma abordagem de treinamento para nosso modelo com um ponto de dados por vez. A sequência de entrada x consiste em 20 pontos de dados e a sequência de destino é considerada igual à sequência de entrada.
Passo 1
Importe os pacotes necessários para implementar redes neurais recorrentes usando o código abaixo -
import torch
from torch.autograd import Variable
import numpy as np
import pylab as pl
import torch.nn.init as init
Passo 2
Vamos definir os hiperparâmetros do modelo com o tamanho da camada de entrada definido como 7. Haverá 6 neurônios de contexto e 1 neurônio de entrada para criar a sequência alvo.
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)
Iremos gerar dados de treinamento, onde x é a sequência de dados de entrada ey é a sequência de destino necessária.
etapa 3
Os pesos são inicializados na rede neural recorrente usando distribuição normal com média zero. W1 representará a aceitação das variáveis de entrada e w2 representará a saída que é gerada conforme mostrado abaixo -
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)
Passo 4
Agora, é importante criar uma função para feed forward que defina exclusivamente a rede neural.
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)
Etapa 5
A próxima etapa é iniciar o procedimento de treinamento da implementação de onda senoidal recorrente da rede neural. O loop externo itera sobre cada loop e o loop interno itera através do elemento de sequência. Aqui, também calcularemos o erro quadrático médio (MSE), que ajuda na previsão de variáveis contínuas.
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])
Etapa 6
Agora, é hora de plotar a onda senoidal conforme a necessidade.
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()
Resultado
O resultado do processo acima é o seguinte -