Класс LSTM
Класс LSTM представляет собой многослойную рекуррентную
нейронную сеть с управляемыми вентилями. Слой принимает на вход
последовательности данных и возвращает выходные значения всех
шагов или только последнего шага. Класс может быть однонаправленным
или двунаправленным в зависимости от параметра bidirectional.
Синтаксис
torch.nn.LSTM(
input_size,
hidden_size,
num_layers=1,
bias=True,
batch_first=False,
dropout=0.0,
bidirectional=False,
proj_size=0,
dtype=None
)
Основные параметры конструктора:
input_size - размерность каждого входного признака,
hidden_size - размерность скрытого состояния,
num_layers - количество рекуррентных слоёв,
bias - использовать смещение,
batch_first - если True, то размерности входного тензора:
(батч, длина_последовательности, input_size),
dropout - вероятность обнуления нейронов между слоями (кроме последнего),
bidirectional - делать слой двунаправленным,
proj_size - размер проецируемого состояния.
Пример создания и применения
Давайте создадим однослойный LSTM и применим его к последовательности:
import torch
lstm = torch.nn.LSTM(input_size=10, hidden_size=20, batch_first=True)
x = torch.randn(8, 30, 10) # (batch, seq_len, input_size)
out, (h_n, c_n) = lstm(x)
print(out.shape)
print(h_n.shape)
print(c_n.shape)
Результат выполнения кода:
torch.Size([8, 30, 20])
torch.Size([1, 8, 20])
torch.Size([1, 8, 20])
Пример двунаправленного слоя
Создадим двунаправленный LSTM с двумя слоями:
import torch
lstm = torch.nn.LSTM(
input_size=10,
hidden_size=20,
num_layers=2,
batch_first=True,
bidirectional=True,
dropout=0.2
)
x = torch.randn(4, 15, 10)
out, (h_n, c_n) = lstm(x)
print(out.shape)
print(h_n.shape)
Результат выполнения кода:
torch.Size([4, 15, 40])
torch.Size([4, 4, 20])
Выходной тензор имеет размерность, увеличенную вдвое, так как объединяются выходы прямого и обратного проходов.
Пример работы с начальным состоянием
Передадим в слой начальные скрытое и ячеечное состояния:
import torch
lstm = torch.nn.LSTM(input_size=5, hidden_size=8, batch_first=True)
x = torch.randn(3, 10, 5)
h0 = torch.randn(1, 3, 8)
c0 = torch.randn(1, 3, 8)
out, (h_n, c_n) = lstm(x, (h0, c0))
print(out[:, -1, :].shape)
Результат выполнения кода:
torch.Size([3, 8])
Пример извлечения только последнего выхода
Для задач классификации часто требуется только последний выход:
import torch
lstm = torch.nn.LSTM(input_size=12, hidden_size=24, batch_first=True)
x = torch.randn(6, 20, 12)
out, _ = lstm(x)
last_out = out[:, -1, :]
print(last_out.shape)
Результат выполнения кода:
torch.Size([6, 24])
Последний выход по оси времени отлично подходит для подачи в полносвязный слой.
Пример использования в модели с полносвязным слоем
Построим простую модель для классификации последовательностей:
import torch
class RNNClassifier(torch.nn.Module):
def __init__(self, input_size, hidden_size, num_classes):
super().__init__()
self.lstm = torch.nn.LSTM(input_size, hidden_size, batch_first=True)
self.fc = torch.nn.Linear(hidden_size, num_classes)
def forward(self, x):
out, _ = self.lstm(x)
out = out[:, -1, :]
return self.fc(out)
model = RNNClassifier(input_size=10, hidden_size=32, num_classes=5)
x = torch.randn(4, 8, 10)
res = model(x)
print(res.shape)
Результат выполнения кода:
torch.Size([4, 5])
Смотрите также
-
класс
GRU,
который представляет собой упрощённый рекуррентный блок с вентилями -
класс
RNN,
который реализует базовый рекуррентный слой -
класс
LSTMCell,
который представляет собой одну ячейку LSTM для пошаговой обработки -
класс
Transformer,
который использует механизм внимания для обработки последовательностей