PyTorch LSTM – Формы входа, скрытого состояния, состояния ячейки и выхода

PyTorch LSTM - Вход, скрытое состояние, состояние ячейки и выход

В Pytorch, чтобы использовать LSTM (с помощью nn.LSTM()), нам нужно понять, как должны быть организованы тензоры, представляющие входные временные ряды, скрытый состояний вектор и вектор состояния ячейки. В этой статье предположим, что вы работаете с многомерными временными рядами. Каждый многомерный временной ряд в наборе данных содержит несколько одномерных временных рядов.

Следующие различия относятся к LSTMCell в pytorch, которые обсуждаются по ссылке ниже:

Pytorch LSTMCell — формы входа, скрытого состояния и состояния ячейки

В pytorch, чтобы использовать LSTMCell, нам нужно понять, как организованы тензоры, представляющие входной временной ряд, скрытое состояние…

VoAGI.com

  1. С помощью nn.LSTM можно создать несколько слоев LSTM, объединив их в стопку, чтобы сформировать стопку LSTM. Второй LSTM берет выход первого LSTM в качестве входа и так далее.

2. В класс nn.LSTM можно добавить dropout.

3. nn.LSTM можно передать неупорядоченные входы.

Есть еще одно значительное отличие, о котором будет рассказано позже в этой статье.

В этой статье мы используем следующую терминологию:

batch = количество многомерных временных рядов в одной партии из набора данных

input_features = количество одномерных временных рядов в одном многомерном временном ряду

time steps = количество временных шагов в каждом многомерном временном ряду

Пакет многомерных временных рядов, который будет использоваться в качестве входных данных для LSTM, должен быть тензором формы (time_steps, batch, input_features)

Следующая картинка поможет понять эту форму входных данных:

Однако, в LSTM есть еще один способ организации входных данных. Об этом будет рассказано ниже.

При инициализации объекта LSTM, необходимо указать аргументы input_features и hidden_size.

Здесь,

input_features = количество одномерных временных рядов в одном многомерном временном ряду (такое же значение, как и упомянутое выше)

hidden_size = количество измерений вектора скрытого состояния.

Другие аргументы, которые может принимать класс LSTM:

num_layers = количество LSTM слоев, объединенных друг на друга. Когда несколько слоев объединены друг на друга, это называется стопкой LSTM. По умолчанию, количество слоев = 1

dropout = если не равно нулю, к выходу каждого LSTM слоя будет добавлен слой dropout с вероятностью отсева, равной этому значению. По умолчанию это значение равно 0, что означает, что отсева нет.

batch_first = если установлено значение True, тензоры ввода и вывода будут иметь размерности (batch, time_steps, input_features) вместо (time_steps, batch, input_features). По умолчанию, это значение равно False.

proj_size = размер проекции. Если proj_size > 0, будет использоваться LSTM с проекциями.

Для прямого распространения входа, начального скрытого состояния и начального состояния ячейки через объект LSTM, требуется следующий формат:

LSTM(input_time_series, (h_0, c_0))

Давайте посмотрим, как организовать вектор скрытого состояния и вектор состояния ячейки перед передачей их в LSTM для прямого распространения.

h_0 — (num_layers, batch, h_out). Здесь h_out = proj_size, если proj_size > 0, иначе hidden_size

c_0 — (num_layers, batch, hidden_size)

Следующая картинка помогает понять форму скрытых векторов.

Аналогичная картинка применима и к векторам состояния ячейки.

Из картинки можно понять, что размерность скрытых и состояния ячейки для всех слоев одинакова.

Рассмотрим следующий фрагмент кода:

import torchimport torch.nn as nn lstm_0 = nn.LSTM(10, 20, 2) # (input_features, hidden_size, num_layers)inp = torch.randn(4, 3, 10) # (time_steps, batch, input_features) -> входные временные рядыh0 = torch.randn(2, 3, 20) # (num_layers, batch, hidden_size) -> начальное значение скрытого состоянияc0 = torch.randn(2, 3, 20) # (num_layers, batch, hidden_size) -> начальное значение состояния ячейкиoutput, (hn, cn) = lstm_0(input, (h0, c0)) # прямой проход входных данных через LSTM

Вызов nn.LSTM() вызовет метод __init__() и создаст объект LSTM. В приведенном выше коде этот объект обозначается как lstm_0.

В общем случае для RNN (LSTM является типом RNN) каждый временной шаг входного временного ряда должен быть передан в RNN по одному в последовательном порядке для обработки RNN.

Чтобы обработать многомерные временные ряды пакетом с использованием LSTM, каждый временной шаг во всех временных рядах в пакете должен последовательно проходить через LSTM.

Один вызов прохода вперед LSTM обрабатывает всю последовательность, последовательно обрабатывая каждый временной шаг. Это отличается от LSTMCell, в котором один вызов обрабатывает только один временной шаг, а не всю последовательность.

Вывод кода выше:

tensor([[[ 3.8995e-02,  1.1831e-01,  1.1922e-01,  1.3734e-01,  1.6157e-02,           3.3094e-02,  2.8738e-01, -6.9250e-02, -1.8313e-01, -1.2594e-01,           1.4951e-01, -3.2489e-01,  2.1723e-01, -1.1722e-01, -2.5523e-01,          -6.5740e-02, -5.2556e-02, -2.7092e-01,  3.0432e-01,  1.4228e-01],         [ 9.2476e-02,  1.1557e-02, -9.3600e-03, -5.2662e-02,  5.5299e-03,          -6.2017e-02, -1.9826e-01, -2.7072e-01, -5.5575e-02, -2.3024e-03,          -2.6832e-01, -5.8481e-01, -8.3415e-03, -2.8817e-01,  4.6101e-03,           3.5043e-02, -6.2501e-01,  4.2930

В этом выводе есть 4 массива, соответствующих 4 временным шагам. Каждый из этих временных шагов содержит 3 массива, соответствующих 3 MTS в пакете. Каждый из этих 3 массивов содержит 20 элементов - это скрытое состояние. Таким образом, для каждого вектора x_t в каждом временном шаге в каждом MTS выводится скрытое состояние. Это скрытые состояния в последнем слое стекового LSTM.

Вывод: (output_multivariate_time_series, (h_n, c_n))

Если вы выведете hn, который присутствует в приведенном выше коде, получите следующий вывод:

tensor([[[-0.3046, -0.1601, -0.0024, -0.0138, -0.1810, -0.1406, -0.1181,           0.0634,  0.0936, -0.1094, -0.2822, -0.2263, -0.1090,  0.2933,           0.0760, -0.1877, -0.0877, -0.0813,  0.0848,  0.0121],         [ 0.0349, -0.2068,  0.1353,  0.1121,  0.1940, -0.0663, -0.0031,          -0.2047, -0.0008, -0.0439, -0.0249,  0.0679, -0.0530,  0.1078,          -0.0631,  0.0430,  0.0873, -0.1087,  0.3161, -0.1618],         [-0.0528, -0.2693,  0.1001, -0.1097,  0.0097, -0.0677, -0.0048,           0.0509,  0.0655,  0.0075, -0.1127, -0.0641,  0.0050,  0.1991,           0.0370, -0.0923,  0.0629,  0.0122,  0.0688, -0.2374]],        [[ 0.0273, -0.1082,  0.0243, -0.0924,  0.0077,  0.0359,  0.1209,           0.0545, -0.0838,  0.0139,  0.0086, -0.2110,  0.0880, -0.1371,          -0.0171,  0.0332,  0.0509, -0.1481,  0.2044, -0.1747],         [ 0.0087, -0.0943,  0.0111, -0.0618, -0.0376, -0.1297,  0.0497,           0.0071, -0.0905,  0.0700, -0.1282, -0.2104,  0.1350, -0.1672,           0.0697,  0.0679,  0.0512,  0.0183,  0.1531, -0.2602],         [-0.0705, -0.1263,  0.0099, -0.0797, -0.1074, -0.0752,  0.1020,           0.0254, -0.1382, -0.0007, -0.0787, -0.1934,  0.1283, -0.0721,           0.1132,  0.0252,  0.0765,  0.0238,  0.1846, -0.2379]]],       grad_fn=<StackBackward0>)

Этот код содержит векторы скрытого состояния в первом и втором слоях стекового LSTM для последнего временного шага в каждом из 3 MTS в пакете. Если вы обратите внимание, скрытое состояние второго слоя (последнего слоя) совпадает с скрытым состоянием последнего временного шага, упомянутого ранее.

Итак, размерность выхода MTS составляет (time_steps, batch, hidden_size).

Эту размерность выхода можно понять по изображению ниже:

Размерность h_n: (num_layers, batch, h_out)

Размерность c_n: (num_layers, batch, hidden_size)