ConvNetJS, будучи чисто JavaScript-библиотекой для реализации нейронных сетей и свёрточных сетей, использует стохастический градиентный спуск (SGD) и его модификации для оптимизации весов. При этом возникают типичные проблемы с градиентами, которые характерны для глубоких сетей:
Затухание градиентов (Vanishing Gradients) Проявляется в том, что значения градиентов становятся чрезвычайно малыми на ранних слоях сети. Это особенно заметно при использовании активационных функций с ограниченным диапазоном (например, сигмоиды), где производная стремится к нулю при больших по модулю значениях входа. Последствия затухания градиентов:
Взрыв градиентов (Exploding Gradients) Обратная ситуация, когда значения градиентов становятся чрезмерно большими. Обычно возникает при глубокой сети и больших начальных весах. Последствия взрыва градиентов:
ConvNetJS предоставляет несколько механизмов, позволяющих бороться с вышеописанными проблемами:
Нормализация весов Для свёрточных слоев и
полносвязных слоёв важно правильно инициализировать веса. В ConvNetJS
используется случайная инициализация из диапазона, зависящего от числа
входов и выходов слоя (Math.random() * scale). Для
предотвращения взрыва градиентов рекомендуется уменьшать масштаб
начальных весов.
Регуляризация градиентов SGD в ConvNetJS
поддерживает L2-регуляризацию, которая автоматически снижает амплитуду
обновлений. В коде это реализуется через параметр decay,
который уменьшает веса после каждой итерации, предотвращая резкий рост
градиентов.
Клиппинг градиентов (Gradient Clipping) Для
предотвращения взрыва градиентов используется ограничение максимальной
нормы градиента. В ConvNetJS это реализуется через проверку
if (gradNorm > maxNorm) { scale *= maxNorm / gradNorm }.
Такой подход гарантирует, что ни один градиент не превысит заданный
порог.
Использование подходящих активаций Для глубоких
сетей предпочтительно применять ReLU или его варианты
(LeakyReLU), так как их производные не стремятся к нулю для
положительных входов. Это снижает вероятность затухания
градиентов.
ConvNetJS позволяет анализировать градиенты на каждом слое:
net.getParamsAndGrads() возвращает массив объектов, где
каждый содержит веса слоя, их градиенты и размерность.mean,
max, min) помогает выявить аномалии: слишком
маленькие значения — признак затухания, слишком большие — взрыва.Пример анализа градиентов на каждой итерации:
var pg = net.getParamsAndGrads();
for(var i=0;i<pg.length;i++) {
var g = pg[i].grad;
console.log("Layer " + i + " grad max: " + Math.max.apply(null,g));
}
scale = 0.01)
для глубоких сетей.learning_rate и decay в SGD
для постепенного обучения.clipval или аналогичные параметры для контроля
градиентов.getParamsAndGrads.Инициализация с малым масштабом и ReLU активацией:
var layer_defs = [];
layer_defs.push({type:'input', out_sx:32, out_sy:32, out_depth:3});
layer_defs.push({type:'conv', sx:5, filters:16, stride:1, pad:2, activation:'relu', weight_decay:0.001});
layer_defs.push({type:'pool', sx:2, stride:2});
layer_defs.push({type:'fc', num_neurons:64, activation:'relu', weight_decay:0.001});
layer_defs.push({type:'softmax', num_classes:10});
var net = new convnetjs.Net();
net.makeLayers(layer_defs);
var trainer = new convnetjs.SGDTrainer(net, {learning_rate:0.01, momentum:0.9, batch_size:64, l2_decay:0.001, clipval:5.0});
Этот подход обеспечивает устойчивость обучения и минимизирует эффекты затухания и взрыва градиентов.