Основы рекуррентности в Synaptic

Библиотека Synaptic предоставляет мощный инструмент для построения нейронных сетей в JavaScript, включая поддержку рекуррентных сетей. Рекуррентные нейронные сети (RNN) отличаются от классических прямых сетей наличием циклических связей, которые позволяют моделировать последовательности и учитывать предыдущие состояния.

Архитектура рекуррентной сети

В Synaptic рекуррентные сети строятся с использованием классов Layer и Network. Ключевой принцип заключается в том, что выход одного слоя может быть возвращён на вход того же слоя или другого слоя. Это позволяет сохранять контекст предыдущих шагов и обрабатывать последовательности данных, таких как текст, временные ряды или аудиосигналы.

Простейшая рекуррентная сеть состоит из:

  • Входного слоя (Input Layer): принимает текущий элемент последовательности.
  • Скрытого слоя (Hidden Layer): содержит память о предыдущих состояниях.
  • Выходного слоя (Output Layer): формирует предсказание на текущем шаге.
  • Рекуррентных соединений (self-connection): связывают скрытые нейроны сами с собой, обеспечивая сохранение состояния.

Создание рекуррентного слоя

В Synaptic рекуррентность можно реализовать, используя метод project для создания циклических связей. Например:

const synaptic = require('synaptic');
const { Layer, Network } = synaptic;

const inputLayer = new Layer(3);
const hiddenLayer = new Layer(5);
const outputLayer = new Layer(2);

inputLayer.project(hiddenLayer);
hiddenLayer.project(hiddenLayer); // рекуррентная связь
hiddenLayer.project(outputLayer);

const myNetwork = new Network({
  input: inputLayer,
  hidden: [hiddenLayer],
  output: outputLayer
});

Ключевой момент: рекуррентная связь создаётся через hiddenLayer.project(hiddenLayer). Это позволяет скрытому слою аккумулировать информацию о предыдущих состояниях на каждом временном шаге.

Передача последовательности данных

Для обучения RNN данные необходимо подавать поэлементно, поддерживая временную последовательность. Метод activate скрытого слоя должен вызываться на каждом шаге, обновляя его состояние:

let sequence = [
  [1, 0, 0],
  [0, 1, 0],
  [0, 0, 1]
];

sequence.forEach(input => {
  let output = myNetwork.activate(input);
  console.log(output);
});

Каждый вызов activate учитывает предыдущие состояния скрытого слоя, что позволяет сети моделировать зависимость последовательности.

Обучение рекуррентной сети

Обучение выполняется с помощью метода propagate, который реализует обратное распространение ошибки по времени (Backpropagation Through Time, BPTT). Пример шага обучения:

let targetSequence = [
  [0, 1],
  [1, 0],
  [0, 1]
];

sequence.forEach((input, index) => {
  let output = myNetwork.activate(input);
  myNetwork.propagate(0.1, targetSequence[index]);
});

Замечание: в Synaptic BPTT реализован автоматически при последовательном вызове activate и propagate. Рекуррентные веса корректируются с учётом влияния прошлых состояний.

Типы рекуррентных связей

В Synaptic поддерживаются несколько типов рекуррентности:

  • Self-recurrent: скрытый слой соединён сам с собой, как в примере выше.
  • Layer-to-layer recurrent: выход одного слоя подаётся на предыдущий слой, создавая более сложные циклы.
  • Custom recurrent networks: возможна комбинация нескольких рекуррентных соединений для сложных архитектур.

Практические советы

  • Инициализация весов: при рекуррентных связях важно корректно инициализировать веса небольшими случайными значениями, чтобы избежать взрыва градиентов.
  • Нормализация входных данных: последовательности лучше масштабировать, чтобы нейроны оставались в области эффективной активации.
  • Контроль длины последовательности: длинные последовательности могут приводить к затухающим или взрывающимся градиентам, поэтому иногда применяют усечение BPTT или использование LSTM/GRU.

Расширенные возможности

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

const outputLayer2 = new Layer(3);
hiddenLayer.project(outputLayer2);

Такой подход позволяет создавать гибкие модели для анализа последовательностей, прогнозирования временных рядов и генерации текста.


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