Прямое распространение

ConvNetJS — это библиотека на JavaScript, предназначенная для создания и обучения нейронных сетей, включая полносвязные и сверточные. Прямое распространение (forward propagation) является ключевым этапом работы сети: на его основе вычисляются выходные значения сети для заданного входного примера.

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

Нейронная сеть в ConvNetJS строится как последовательность слоёв (layers), каждый из которых реализует определённую функцию. Слои могут быть разных типов: полносвязные (fc), свёрточные (conv), субдискретизирующие (pool), нелинейные (relu, sigmoid, tanh) и выходные (softmax, regression). Каждый слой имеет свои параметры и состояние, которые хранятся в объекте слоя:

  • weights — матрица весов;
  • biases — вектор смещений;
  • out_act — результат прямого распространения (активация);
  • in_act — входные значения для слоя.

Процесс прямого распространения

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

  1. Входные данные передаются первому слою.
  2. Каждый слой вычисляет линейное преобразование: [ z = W x + b] где (W) — матрица весов слоя, (x) — входной вектор, (b) — вектор смещений.
  3. На результат линейного преобразования применяется активационная функция (ReLU, sigmoid, tanh и др.).
  4. Выход слоя передаётся на вход следующего слоя.
  5. На последнем слое формируется окончательный выход сети, используемый для предсказания или вычисления функции потерь.

Метод forward может принимать дополнительный аргумент is_training, который указывает, выполняется ли вычисление в режиме обучения. Для некоторых слоев (например, Dropout) это определяет поведение слоя: при обучении часть нейронов отключается, при тестировании используется полный набор.

Особенности слоёв

  • Полносвязный слой (fc) Все нейроны предыдущего слоя соединены с каждым нейроном текущего. Прямое распространение для слоя fc выполняется через матричное умножение и добавление смещения:

    this.out_act = this.in_act.w.map((x, i) => {
        return this.weights.w[i] * x + this.biases.w[i];
    });

    Затем применяется активация.

  • Сверточный слой (conv) Вычисляет свёртку входного объёма с фильтрами (kernels). Каждое ядро фильтра скользит по входной матрице, суммируя произведения элементов ядра и соответствующих входных значений, к результату добавляется смещение:

    z = sum(filters * input_patch) + bias

    На выход подается результат активации.

  • Субдискретизирующий слой (pool) Выполняет уменьшение размерности через max-pooling или average-pooling. Прямое распространение вычисляет максимум или среднее по заданной области окна:

    out_patch = max(input_patch)
  • Активационные слои (relu, sigmoid, tanh) Преобразуют линейный выход слоя в нелинейный сигнал. Прямое распространение для ReLU выглядит как:

    out_act = Math.max(0, z)

Организация вычислений

ConvNetJS использует объект Vol (volume) для хранения данных и градиентов. Каждый слой принимает на вход in_act типа Vol и возвращает out_act типа Vol. Это унифицирует обработку данных, независимо от размерности входа или типа слоя.

Важные особенности Vol:

  • w — массив значений нейронов;
  • dw — массив градиентов (используется при обратном распространении);
  • sx, sy, depth — размеры объёма.

Прямое распространение с несколькими входами

ConvNetJS поддерживает сети с несколькими параллельными потоками, объединяемыми на последующих слоях. Для этого каждый поток выполняет forward независимо, а объединение происходит через слой concat или softmax на выходе.

Оптимизация вычислений

  • Кэширование промежуточных значений: каждый слой сохраняет выходы out_act, чтобы их можно было использовать при обратном распространении без повторных вычислений.
  • Векторизация операций: большинство линейных операций реализовано с использованием одномерных массивов и матричных умножений, что ускоряет работу на JavaScript движках.

Примеры вызова прямого распространения

var net = new convnetjs.Net();
net.makeLayers([
  {type:'input', out_sx:28, out_sy:28, out_depth:1},
  {type:'conv', sx:5, filters:8, stride:1, pad:2, activation:'relu'},
  {type:'pool', sx:2, stride:2},
  {type:'fc', num_neurons:10, activation:'softmax'}
]);

var x = new convnetjs.Vol(28,28,1);
var output = net.forward(x);

В результате output содержит предсказанные вероятности классов после прямого распространения через все слои сети.

Ключевые моменты

  • Прямое распространение — последовательная обработка входа через слои.
  • Каждый слой хранит входные и выходные значения для последующего обратного распространения.
  • Активационные функции добавляют нелинейность и позволяют сети решать сложные задачи.
  • ConvNetJS унифицирует данные через объект Vol, упрощая работу с многомерными входами.
  • Поддерживается режим обучения и тестирования, что важно для слоев Dropout и BatchNorm.

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