PyTorch - рекуррентная нейронная сеть

Рекуррентные нейронные сети - это один из типов алгоритмов, ориентированных на глубокое обучение, в котором используется последовательный подход. В нейронных сетях мы всегда предполагаем, что каждый вход и выход не зависят от всех других слоев. Нейронные сети этого типа называются рекуррентными, поскольку они выполняют математические вычисления последовательно, выполняя одну задачу за другой.

На диаграмме ниже показан полный подход и работа рекуррентных нейронных сетей.

На приведенном выше рисунке c1, c2, c3 и x1 рассматриваются как входы, которые включают некоторые скрытые входные значения, а именно h1, h2 и h3, доставляющие соответствующий выход o1. Теперь мы сосредоточимся на реализации PyTorch для создания синусоидальной волны с помощью повторяющихся нейронных сетей.

Во время обучения мы будем следовать тренировочному подходу к нашей модели с одной точкой данных за раз. Входная последовательность x состоит из 20 точек данных, и целевая последовательность считается такой же, как входная последовательность.

Шаг 1

Импортируйте необходимые пакеты для реализации рекуррентных нейронных сетей, используя приведенный ниже код -

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

Шаг 2

Мы установим гиперпараметры модели с размером входного слоя, равным 7. Будет 6 контекстных нейронов и 1 входной нейрон для создания целевой последовательности.

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)

Мы сгенерируем обучающие данные, где x - последовательность входных данных, а y - необходимая целевая последовательность.

Шаг 3

Веса инициализируются в рекуррентной нейронной сети с использованием нормального распределения с нулевым средним. W1 будет представлять принятие входных переменных, а w2 будет представлять выходные данные, которые генерируются, как показано ниже -

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)

Шаг 4

Теперь важно создать функцию прямой связи, которая однозначно определяет нейронную сеть.

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)

Шаг 5

Следующим шагом является запуск процедуры обучения реализации синусоидальной волны рекуррентной нейронной сети. Внешний цикл выполняет итерацию по каждому циклу, а внутренний цикл выполняет итерацию по элементу последовательности. Здесь мы также вычислим среднеквадратическую ошибку (MSE), которая помогает в прогнозировании непрерывных переменных.

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

Шаг 6

Теперь пришло время построить синусоидальную волну так, как это необходимо.

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

Вывод

Результат для вышеуказанного процесса выглядит следующим образом: