Переобучение (overfitting) возникает, когда нейронная сеть слишком точно подстраивается под обучающие данные, теряя способность обобщать информацию на новые примеры. В ConvNetJS, библиотеке для построения и обучения сверточных сетей на JavaScript, доступны несколько инструментов и методик для минимизации переобучения.
ConvNetJS поддерживает L1 и L2 регуляризацию, которые добавляются к функции потерь и штрафуют слишком большие веса.
Пример настройки регуляризации при создании сетки:
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'});
layer_defs.push({type:'fc', num_neurons:100, activation:'relu'});
var net = new convnetjs.Net();
net.makeLayers(layer_defs);
var trainer = new convnetjs.SGDTrainer(net, {
learning_rate:0.01, momentum:0.9, batch_size:20, l2_decay:0.001
});
В этом примере l2_decay определяет коэффициент L2
регуляризации. Для L1 используется l1_decay. Подбор
этих коэффициентов критичен: слишком высокая регуляризация
замедлит обучение, слишком низкая – не предотвратит переобучение.
Dropout — метод, при котором случайная часть нейронов временно отключается на каждом шаге обучения. Это препятствует зависимости нейронов друг от друга и улучшает обобщающую способность сети.
Пример добавления Dropout в ConvNetJS:
layer_defs.push({type:'dropout', p:0.5});
p — вероятность отключения нейронов.Эффект: уменьшение переобучения за счет создания “ансамбля” моделей в рамках одной сети.
Увеличение обучающего набора позволяет нейронной сети видеть больше вариаций данных, что снижает риск переобучения.
function randomShift(img, maxShift) {
var sx = Math.floor(Math.random() * (2*maxShift+1)) - maxShift;
var sy = Math.floor(Math.random() * (2*maxShift+1)) - maxShift;
return img.shift(sx, sy); // shift – метод обработки матрицы пикселей
}
Регулярное использование аугментации делает сеть более устойчивой к изменениям входных данных.
ConvNetJS не имеет встроенного механизма ранней остановки, но можно реализовать его самостоятельно:
Пример контроля ошибки:
var best_val_loss = Infinity;
var no_improve_epochs = 0;
var max_no_improve = 10;
for(var epoch=0; epoch<num_epochs; epoch++) {
trainer.trainBatch(trainX, trainY);
var val_loss = net.getLoss(valX, valY);
if(val_loss < best_val_loss) {
best_val_loss = val_loss;
no_improve_epochs = 0;
} else {
no_improve_epochs++;
}
if(no_improve_epochs >= max_no_improve) break;
}
Этот подход предотвращает обучение сети после того, как она начинает подстраиваться под шум в обучающих данных.
Слишком глубокие или широкие сети склонны к переобучению. В ConvNetJS можно регулировать:
filters);num_neurons);Оптимизация архитектуры под конкретную задачу часто важнее всего сочетания методов регуляризации.
На практике лучшие результаты достигаются сочетанием L2 регуляризации, Dropout, аугментации данных и раннего прекращения обучения. Важно отслеживать метрики на обучении и валидации, чтобы корректировать параметры обучения и структуры сети.
Если требуется, могу подготовить пошаговый пример полностью работающего проекта в ConvNetJS с защитой от переобучения, включая конфигурацию слоев, Dropout, регуляризацию и аугментацию данных. Это будет готовый учебный кейс.