Устройство ячейки GRU

Глубокие рекуррентные нейронные сети (RNN) часто сталкиваются с проблемой затухающих и взрывающихся градиентов, что ограничивает их способность запоминать долгосрочные зависимости. Для решения этой задачи были разработаны специализированные механизмы памяти, среди которых GRU (Gated Recurrent Unit) занимает одно из ведущих мест благодаря простоте и эффективности.

Основная структура GRU

GRU — это модифицированная RNN-ячейка, в которой используется два типа гейтов (врат): обновляющий и сброса. Эти гейты управляют потоком информации через временные шаги сети:

  1. Гейт сброса (reset gate, r_t) Контролирует, какая часть предыдущего состояния ( h_{t-1} ) будет использована для вычисления нового кандидата состояния. Формула:

    [ r_t = (W_r x_t + U_r h_{t-1} + b_r)]

    • ( x_t ) — входной вектор на текущем временном шаге
    • ( h_{t-1} ) — предыдущее скрытое состояние
    • ( W_r, U_r, b_r ) — обучаемые параметры
    • ( ) — сигмоидальная функция активации

    Когда ( r_t ) близок к 0, предыдущее состояние почти не влияет на новое кандидата состояние, что позволяет сети “забывать” ненужную информацию.

  2. Гейт обновления (update gate, z_t) Определяет, насколько текущее состояние должно включать информацию из предыдущего состояния:

    [ z_t = (W_z x_t + U_z h_{t-1} + b_z)]

    Гейт обновления управляет балансом между сохранением старой информации и внедрением нового кандидата состояния ( _t ).

  3. **Кандидатное скрытое состояние ((_t))** Вычисляется с использованием гейта сброса, который фильтрует предыдущие значения состояния:

    [ t = (W x_t + U (r_t h{t-1}) + b)]

    Здесь ( ) обозначает поэлементное умножение. Гейт сброса позволяет контролировать, какие элементы старого состояния участвуют в создании кандидата.

  4. Новое скрытое состояние (h_t) Обновляется как взвешенная комбинация предыдущего состояния и кандидата:

    [ h_t = (1 - z_t) h_{t-1} + z_t _t]

    • Если ( z_t ) близок к 1, ячейка полностью принимает новое значение
    • Если ( z_t ) близок к 0, сохраняется старое состояние

Реализация GRU в Brain.js

В библиотеке Brain.js GRU реализован через класс recurrent.GRU, который предоставляет интерфейс для создания сети с поддержкой последовательных данных.

Пример инициализации:

const brain = require('brain.js');

const net = new brain.recurrent.GRU({
  inputSize: 10,
  hiddenLayers: [20, 20],
  outputSize: 5
});
  • inputSize — размерность входного вектора
  • hiddenLayers — массив, определяющий количество нейронов в скрытых слоях GRU
  • outputSize — размерность выходного вектора

Процесс обучения:

net.train([
  { input: [0,1,0,1,0], output: [1] },
  { input: [1,0,1,0,1], output: [0] }
], {
  iterations: 2000,
  learningRate: 0.01
});
  • Сеть автоматически управляет внутренними гейтами GRU
  • Обновление весов происходит с использованием обратного распространения через время (BPTT)

Особенности GRU по сравнению с LSTM

  • Меньше параметров, так как отсутствует отдельный выходной гейт
  • Быстрее в обучении при сопоставимой точности
  • Подходит для задач с ограниченным объемом данных и не слишком длинными последовательностями

Внутренние детали Brain.js

  • GRU в Brain.js представлена как последовательность скрытых слоев, каждый из которых обновляет состояние с учетом предыдущего шага
  • Функции активации и гейтов выполнены через тензорные операции, оптимизированные для JavaScript
  • Обратное распространение учитывает все временные шаги, что позволяет корректно корректировать веса всех гейтов

Практическое использование

GRU особенно эффективна для задач:

  • Обработки текстовых последовательностей и предсказания следующего символа
  • Прогнозирования временных рядов
  • Анализа сигналов и последовательных данных с умеренной длиной

Управление гейтами позволяет сети динамически адаптироваться к долгосрочным и краткосрочным зависимостям, что делает GRU предпочтительным выбором для многих приложений в Brain.js.