Обратное распространение ошибки (backpropagation) — это ключевой метод обучения нейронных сетей, включая свёрточные сети, реализованные в ConvNetJS. Он позволяет эффективно вычислять градиенты функции потерь по параметрам сети и корректировать веса для минимизации ошибки.
ConvNetJS реализует сети через последовательность слоев (layers). Каждый слой имеет входные и выходные данные:
Vol — основной объект для хранения значений нейронов и
градиентов. Он представляет собой многомерный массив с числовыми данными
(w) и соответствующими градиентами (dw).Каждый слой имеет методы:
forward(input): вычисляет выход слоя на основе входных
данных.backward(): рассчитывает градиенты относительно входов
и весов слоя.Прямое распространение (Forward pass) Каждое
входное изображение или вектор проходит через все слои сети. На этом
этапе сохраняются промежуточные значения (vol.w) для
дальнейшего вычисления градиентов.
Вычисление функции потерь После последнего слоя
вычисляется ошибка сети. В ConvNetJS обычно используется
SoftmaxLossLayer или RegressionLayer,
которые предоставляют метод loss для расчета ошибки и
backward для градиента.
Обратное распространение (Backward pass) Метод
backward вызывается в последнем слое для вычисления
градиента функции потерь по выходам слоя. Затем градиенты
последовательно передаются в предыдущие слои, вычисляя градиенты по
весам и входам каждого слоя.
Каждый слой хранит два ключевых свойства:
this.out_act: выходной Vol после прямого
распространения.this.in_act: входной Vol, необходимый для
вычисления производной.Пример работы fully connected слоя:
// Прямое распространение
this.out_act = new Vol(1, 1, this.num_outputs, 0);
for (var i = 0; i < this.num_outputs; i++) {
var a = this.biases.w[i];
for (var j = 0; j < this.num_inputs; j++) {
a += this.filters[i].w[j] * input.w[j];
}
this.out_act.w[i] = a;
}
// Обратное распространение
this.in_act.dw = new Array(this.num_inputs).fill(0);
for (var i = 0; i < this.num_outputs; i++) {
var chain_grad = this.out_act.dw[i];
for (var j = 0; j < this.num_inputs; j++) {
this.in_act.dw[j] += this.filters[i].w[j] * chain_grad;
this.filters[i].dw[j] += this.in_act.w[j] * chain_grad;
}
this.biases.dw[i] += chain_grad;
}
Ключевые моменты:
dw — градиенты весов и смещений, на основе которых
обновляются параметры.in_act.dw — градиенты по входам, передаваемые в
предыдущий слой.in_act.w) для корректного вычисления градиентов.Свёрточный слой выполняет линейное преобразование с использованием фильтров. Основные шаги обратного распространения:
Пример формулы градиента для веса фильтра:
[ = {x,y} {x,y,f} a_{x+i, y+j}]
где ( {x,y,f} ) — градиент выхода слоя по элементу ((x, y, f)), ( a{x+i, y+j} ) — соответствующая активация входного объёма.
for (var i = 0; i < n; i++) {
this.in_act.dw[i] = this.out_act.dw[i] * (this.in_act.w[i] > 0 ? 1 : 0);
}
MaxPooling: Градиенты передаются только к тем входам, которые были максимальными в прямом проходе.
Softmax: Градиент вычисляется как разность предсказанной вероятности и целевого класса для каждой позиции:
[ _i = p_i - t_i]
forward и backward,
что позволяет строить сети произвольной глубины.dw.forward → loss → backward →
update.