LSTM слои

Long Short-Term Memory (LSTM) — это разновидность рекуррентных нейронных сетей (RNN), предназначенная для работы с последовательными данными. В отличие от обычных RNN, LSTM способны эффективно запоминать информацию на длительных временных интервалах за счёт специально организованных ячеек памяти и управляющих ворот. В библиотеке ConvNetJS реализованы LSTM-слои, которые позволяют строить модели для обработки текста, временных рядов и других последовательностей.

Структура LSTM-слоя

LSTM-слой в ConvNetJS состоит из нескольких ключевых компонентов:

  • Ячейка состояния (cell state): основной контейнер для хранения информации, проходящей через временные шаги.
  • Входной ворота (input gate): контролирует, какая информация из текущего входа добавляется в ячейку состояния.
  • Забывающий ворота (forget gate): определяет, какая информация из предыдущего состояния ячейки должна быть удалена.
  • Выходной ворота (output gate): регулирует, какая часть информации из ячейки состояния передаётся на выход слоя.

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

Создание LSTM-слоя в ConvNetJS

Для создания LSTM-слоя используется объект LSTMLayer. Основные параметры:

var layer = new convnetjs.LSTMLayer({
    input_dim: 10,      // размерность входного вектора
    hidden_dim: 20,     // количество нейронов в скрытом состоянии
    output_dim: 5       // размерность выхода слоя
});
  • input_dim — количество признаков во входной последовательности.
  • hidden_dim — размерность вектора скрытого состояния; определяет объём памяти LSTM.
  • output_dim — размерность выходного вектора; может совпадать с hidden_dim для полных LSTM-сетей или быть меньше для проекционных LSTM.

Прямое распространение (Forward Pass)

Прямое распространение в LSTM выполняется через метод forward, принимающий на вход объект Vol (объект ConvNetJS, представляющий вектор или матрицу данных):

var output = layer.forward(inputVol);

На каждом временном шаге LSTM:

  1. Рассчитывается значение входного, забывающего и выходного ворот.
  2. Обновляется состояние ячейки: [ C_t = f_t C_{t-1} + i_t _t] где (f_t) — забывающий ворот, (i_t) — входной ворот, (_t) — кандидат состояния.
  3. Рассчитывается скрытое состояние: [ h_t = o_t (C_t)] где (o_t) — выходной ворот.

Все вычисления осуществляются в виде операций над объектами Vol, что позволяет использовать GPU-ускорение при необходимости.

Обратное распространение (Backward Pass)

Обучение LSTM в ConvNetJS реализуется через метод backward. Он автоматически учитывает зависимости через время и обновляет градиенты для всех весов ворот. Основные моменты:

  • Градиенты состояния ячейки аккумулируются через временные шаги, что предотвращает исчезновение градиента при длинных последовательностях.
  • Для каждого воротного механизма вычисляются частные производные по весам и смещениям.
  • ConvNetJS использует стандартный стохастический градиентный спуск (SGD) или его модификации для обновления параметров.

Пример использования:

layer.backward(dout); // dout — градиенты по выходу слоя

Инициализация и сброс состояния

Для корректной работы LSTM важно управлять состоянием ячейки между последовательностями. В ConvNetJS предусмотрен метод reset:

layer.reset(); // обнуляет состояния C и h

Это необходимо, когда начинается новая независимая последовательность данных, чтобы предыдущие состояния не влияли на текущую.

Применение LSTM-слоев

LSTM в ConvNetJS используются для:

  • Прогнозирования временных рядов.
  • Генерации текста на основе предыдущих символов или слов.
  • Анализа последовательных данных в задачах классификации или регрессии.

Для построения более сложных моделей LSTM можно объединять несколько слоев последовательно, например:

var layer1 = new convnetjs.LSTMLayer({input_dim: 10, hidden_dim: 20});
var layer2 = new convnetjs.LSTMLayer({input_dim: 20, hidden_dim: 15, output_dim: 5});

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

Оптимизация и гиперпараметры

Эффективность LSTM зависит от выбора:

  • hidden_dim: слишком малое значение приводит к потере информации, слишком большое — к переобучению.
  • Скорости обучения и метода оптимизации (SGD, Adam, RMSProp).
  • Длины последовательности в обучающем батче: слишком длинные последовательности увеличивают вычислительную нагрузку и вероятность взрыва градиента.

ConvNetJS поддерживает контроль градиентов через clip_gradients для предотвращения взрыва градиентов.

Особенности реализации в ConvNetJS

  • Все операции выполняются над объектами Vol, что унифицирует обработку тензоров.
  • LSTM-слой не зависит от конкретного размера входа, кроме указанного input_dim.
  • Поддерживается режим “stateful”, когда состояние ячейки сохраняется между последовательными вызовами forward.
  • Простая интеграция с другими типами слоев: fully connected, softmax, dropout.