Введение в рекуррентные архитектуры

ConvNetJS — это библиотека для построения нейронных сетей на чистом JavaScript. Она поддерживает как сверточные сети, так и полносвязные (dense) слои, а также рекуррентные нейронные сети (RNN). Особенность ConvNetJS заключается в том, что она полностью работает на стороне клиента, не требуя серверной инфраструктуры или установки дополнительных пакетов. Основной объект для работы — convnetjs.Net, который хранит архитектуру сети, веса и методы обучения.

Создание сети

Для создания сети используется объект convnetjs.Net(), после чего к нему последовательно добавляются слои через метод addLayer. Каждый слой описывается объектом с указанием типа и параметров. Например, полносвязный слой задаётся как:

var layer = {type:'fc', num_neurons: 128, activation:'relu'};
  • type — тип слоя (fc для полносвязного, conv для сверточного, pool для подвыборки, regression или softmax для выхода).
  • num_neurons — количество нейронов в слое (для полносвязного).
  • activation — функция активации (relu, sigmoid, tanh и другие).

После добавления всех слоев сеть необходимо инициализировать, что создаёт внутренние структуры для хранения весов и градиентов:

net.makeLayers();

Рекуррентные сети в ConvNetJS

Рекуррентные нейронные сети (RNN) используются для обработки последовательных данных, таких как текст, временные ряды или аудиосигналы. В ConvNetJS рекуррентная архитектура задаётся через слой типа rnn или комбинацию input -> recurrent -> fc.

Основные компоненты RNN

  • Входной слой (input): принимает данные последовательности по одной временной отметке. Размерность задаётся в параметре num_inputs.

  • Рекуррентный слой (rnn): содержит скрытое состояние, которое передаётся по временной оси. Основные параметры:

    • num_neurons — размер скрытого слоя;
    • activation — функция активации скрытых состояний (tanh чаще всего используется для RNN);
    • gate — если указано, реализуется LSTM или GRU-подобная функциональность (ConvNetJS поддерживает базовые варианты).
  • Выходной слой (fc или softmax): формирует предсказание на текущем временном шаге или на последнем шаге последовательности.

Пример создания простой RNN для обработки последовательности чисел:

var net = new convnetjs.Net();
net.addLayer({type:'input', out_sx:1, out_sy:1, out_depth:1});
net.addLayer({type:'rnn', num_neurons:50, activation:'tanh'});
net.addLayer({type:'fc', num_neurons:10, activation:'softmax'});
net.makeLayers();

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

ConvNetJS поддерживает стохастический градиентный спуск (SGD) и его варианты. Для рекуррентных сетей используется BPTT (Backpropagation Through Time), которая позволяет корректировать веса с учётом временной зависимости. Основные шаги обучения:

  1. Формирование набора последовательностей: каждая последовательность представляет собой массив входных векторов.

  2. Передача данных в сеть пошагово через метод forward:

    net.forward(x_t);

    где x_t — вход в текущий временной шаг.

  3. Вычисление градиентов через backward с учётом ошибки на текущем шаге:

    net.backward(dloss);
  4. Обновление весов с использованием оптимизатора:

    trainer.train(x, y);

    где trainer — объект convnetjs.SGDTrainer, который управляет скоростью обучения, моментумом и регуляризацией.

Форматы данных для RNN

ConvNetJS оперирует объектами Vol (тензорами). Для последовательности длиной T создаётся массив Vol объектов:

var sequence = [];
for (var t=0; t<T; t++) {
    sequence.push(new convnetjs.Vol([value_t]));
}

Каждый элемент Vol хранит входное значение и градиенты. Это позволяет рекуррентному слою аккумулировать скрытое состояние и корректно рассчитывать BPTT.

Основные функции и методы

  • forward(V) — пропуск данных через сеть для текущего шага.
  • backward(dout) — обратное распространение ошибки по сети.
  • getParamsAndGrads() — получение всех весов и соответствующих градиентов.
  • toJSON() и fromJSON() — сохранение и восстановление архитектуры и весов.

Практические особенности

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

Сравнение с другими подходами

В отличие от TensorFlow.js или PyTorch, ConvNetJS:

  • Не имеет GPU-ускорения, все вычисления на CPU.
  • Предназначен для образовательных и прототипных задач, но демонстрирует фундаментальные принципы RNN.
  • Позволяет наглядно видеть процесс обучения и строить собственные эксперименты без сложной инфраструктуры.

Расширение RNN

  • Stacked RNN: несколько рекуррентных слоев подряд для увеличения выразительности.
  • Sequence-to-sequence: можно реализовать путем создания двух RNN — кодера и декодера.
  • Регуляризация: поддержка dropout для скрытых слоев через параметр drop_prob.

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