Batch normalization

Batch Normalization (BN) — метод нормализации активаций слоёв нейронной сети, позволяющий ускорить обучение и повысить стабильность глубоких моделей. В ConvNetJS BN реализуется как отдельный слой, который можно вставлять между слоями свёрточной или полносвязной сети.

Основная идея

BN заключается в том, чтобы привести входы слоя к стандартному виду с нулевым средним и единичной дисперсией для каждого мини-батча. Это уменьшает внутреннее смещение распределений (Internal Covariate Shift), которое возникает при обучении глубоких сетей. Формально, для активаций (x_i) в батче размера (m):

[ B = {i=1}^{m} x_i, B^2 = {i=1}^{m} (x_i - _B)^2]

Нормализованные значения вычисляются как:

[ _i = ]

Здесь () — малое значение для численной стабильности. После нормализации вводятся обучаемые параметры () и (), которые позволяют модели восстанавливать необходимые масштабы и смещения:

[ y_i = _i + ]

Реализация в ConvNetJS

В ConvNetJS слой BatchNorm создаётся с помощью convnetjs.BNLayer для полносвязных слоёв и convnetjs.BNConvLayer для свёрточных слоёв. Конструктор слоя принимает параметры:

  • out_sx, out_sy, out_depth — размерность выхода.
  • epsilon — числовая стабилизация (обычно 1e-5).
  • momentum — коэффициент для экспоненциального скользящего среднего статистик батча (обычно 0.9–0.99).

Пример создания слоя для полносвязного слоя с 100 нейронами:

var layer = new convnetjs.BNLayer({num_neurons: 100, epsilon: 1e-5, momentum: 0.9});

Для свёрточного слоя:

var layer = new convnetjs.BNConvLayer({
    sx: 1,
    filters: 32,
    stride: 1,
    pad: 0,
    epsilon: 1e-5,
    momentum: 0.9
});

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

Во время обучения BN вычисляет среднее и дисперсию текущего батча и нормализует входные активации. ConvNetJS хранит статистику в объектах running_mean и running_var для использования при тестировании. Формулы:

x_hat = (x - mu_B) / Math.sqrt(var_B + epsilon)
y = gamma * x_hat + beta

gamma и beta обновляются методом обратного распространения градиентов вместе с остальными параметрами сети.

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

y_test = gamma * (x - running_mean) / Math.sqrt(running_var + epsilon) + beta

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

Градиенты для BN вычисляются с учётом нормализации и обучаемых параметров. Для каждого слоя BN градиенты рассчитываются по трём компонентам:

  1. Градиенты по входу — учитывают производные от нормализации.
  2. Градиенты по gamma — сумма произведений градиента выхода на нормализованные входы.
  3. Градиенты по beta — сумма градиентов выхода.

ConvNetJS автоматизирует эти вычисления в методе backward, возвращая градиент по входу и обновляя внутренние градиенты для параметров gamma и beta.

Плюсы использования BatchNorm

  • Ускорение обучения: можно использовать более высокие learning rate без риска расходимости.
  • Стабильность градиентов: уменьшение внутренних смещений распределений активаций.
  • Регуляризация: BN частично снижает необходимость в Dropout, так как шум от батч-статистики действует как легкая регуляризация.
  • Универсальность: подходит как для полносвязных, так и для свёрточных слоёв.

Практические рекомендации

  • momentum для скользящего среднего обычно выбирается 0.9–0.99.
  • epsilon берется малым (1e-5), чтобы избежать деления на ноль.
  • BN эффективен при размерах батча ≥ 16–32. Очень маленькие батчи могут привести к неточным статистикам.
  • После добавления BN, learning rate можно увеличить на порядок для ускорения сходимости.

Взаимодействие с другими слоями

  • BN обычно ставят после свёртки или полносвязного слоя, до активации ReLU или sigmoid.
  • Для сложных сетей можно комбинировать BN с Dropout, хотя порядок и выбор параметров требует аккуратной настройки.
  • В ConvNetJS можно гибко комбинировать BN с любыми слоями, используя стандартный список слоёв в Net:
var net = new convnetjs.Net();
net.makeLayers([
  {type: 'input', out_sx: 28, out_sy: 28, out_depth: 1},
  {type: 'conv', sx: 5, filters: 16, stride: 1, pad: 2},
  {type: 'bn'},
  {type: 'relu'},
  {type: 'pool', sx: 2, stride: 2},
  {type: 'fc', num_neurons: 100},
  {type: 'bn'},
  {type: 'relu'},
  {type: 'softmax', num_classes: 10}
]);

Этот пример демонстрирует стандартную практику: BN вставляется перед активацией, ускоряя обучение и повышая стабильность модели.

Batch Normalization в ConvNetJS обеспечивает мощный инструмент для построения глубоких сетей с улучшенной сходимостью и минимальными дополнительными усилиями по настройке гиперпараметров.