Диагностика плохой сходимости

Плохая сходимость нейронной сети возникает, когда обучение не приводит к уменьшению ошибки на обучающем наборе данных или процесс обучения крайне медленный. В ConvNetJS эта проблема проявляется через медленное снижение функции потерь или резкие колебания точности. Основные причины:

  • Неподходящая архитектура сети: слишком глубокая или слишком мелкая сеть для поставленной задачи.
  • Неверно подобранные гиперпараметры: скорость обучения (learning rate), коэффициенты регуляризации, параметры оптимизатора.
  • Проблемы с масштабированием данных: входные значения не нормализованы.
  • Внутренние проблемы сети: затухающие или взрывающиеся градиенты, особенно в глубоких сверточных слоях.

Анализ функции потерь и точности

Для диагностики сходимости важна визуализация и мониторинг:

var stats = trainer.getStats();
console.log(stats); // {loss: ..., gradMax: ..., gradMean: ..., trainAcc: ..., valAcc: ...}
  • loss — значение функции потерь на последней итерации. Если оно не уменьшается, вероятна слишком высокая скорость обучения или неподходящая архитектура.
  • gradMax и gradMean — максимальное и среднее значения градиентов. Слишком большие значения указывают на взрывающиеся градиенты, слишком маленькие — на затухающие.
  • trainAcc и valAcc — точность на обучающем и валидационном наборе. Расхождение этих значений сигнализирует о переобучении или недообучении.

Регулировка скорости обучения

ConvNetJS использует оптимизаторы с градиентным спуском, например trainer = new convnetjs.SGDTrainer(net, {learning_rate:0.01, momentum:0.9, batch_size:20}). Скорость обучения напрямую влияет на сходимость:

  • Слишком высокая (learning_rate > 0.1) приводит к колебаниям функции потерь и нестабильности.
  • Слишком низкая (learning_rate < 0.001) делает обучение медленным, сеть может застрять в локальном минимуме.

Стратегии корректировки:

  1. Постепенное уменьшение скорости обучения в процессе обучения (learning rate decay).
  2. Использование метода momentum для сглаживания колебаний градиента.
  3. Проверка изменения градиентов через gradMax и gradMean.

Нормализация входных данных

Для стабильной сходимости данные должны иметь среднее 0 и стандартное отклонение 1:

function normalizeData(data) {
    var mean = data.reduce((sum, val) => sum + val) / data.length;
    var std = Math.sqrt(data.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / data.length);
    return data.map(val => (val - mean) / std);
}

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

Диагностика градиентов

В ConvNetJS можно отслеживать распределение градиентов:

var gradStats = net.getGradientStats();
console.log(gradStats); // {mean: ..., max: ..., min: ...}
  • gradStats.max > 100 или gradStats.min < -100 — сигнал о взрывающихся градиентах.
  • gradStats.mean близок к нулю при стабильной сети. Значительное отклонение требует уменьшения learning rate или изменения инициализации весов.

Настройка архитектуры сети

Плохая сходимость может быть следствием неподходящей архитектуры:

  • Глубокие сети требуют больше данных и правильной инициализации весов.
  • Малые сети могут недообучаться, особенно на сложных задачах.
  • Использование слоев ReLU вместо сигмоидальных функций снижает эффект затухающих градиентов.
  • Добавление Dropout помогает бороться с переобучением, но может замедлить обучение.

Пример конфигурации слоя с ReLU и Dropout:

var layerDefs = [];
layerDefs.push({type:'input', out_sx:32, out_sy:32, out_depth:3});
layerDefs.push({type:'conv', sx:5, filters:16, stride:1, pad:2, activation:'relu'});
layerDefs.push({type:'pool', sx:2, stride:2});
layerDefs.push({type:'dropout', p:0.5});
layerDefs.push({type:'softmax', num_classes:10});
var net = new convnetjs.Net();
net.makeLayers(layerDefs);

Использование регуляризации

Регуляризация снижает переобучение и может ускорить сходимость на валидационном наборе:

  • L2-регуляризация добавляется через параметр l2_decay в SGDTrainer.
  • Dropout случайно отключает нейроны на тренировке, улучшая обобщающую способность.
var trainer = new convnetjs.SGDTrainer(net, {
    learning_rate: 0.01,
    momentum: 0.9,
    batch_size: 20,
    l2_decay: 0.001
});

Мониторинг сходимости на практике

Для анализа сходимости создается лог функции потерь и точности:

var losses = [];
for(var i=0;i<1000;i++) {
    trainer.train(xBatch, yBatch);
    if(i % 10 === 0) losses.push(trainer.getStats().loss);
}
console.log(losses);
  • Плавное снижение кривой потерь с небольшими колебаниями — индикатор правильной сходимости.
  • Застревание на высокой потере — сигнал для уменьшения learning rate или проверки архитектуры.
  • Резкие скачки потерь — признак слишком высокой скорости обучения или нестабильности градиентов.

Практика отладки

  1. Проверка простейшего случая: обучить сеть на небольшой подвыборке. Если сеть не обучается на малых данных, проблема в архитектуре или гиперпараметрах.
  2. Визуализация активаций: можно отслеживать выходные значения сверточных слоев для проверки насыщенности нейронов.
  3. Пошаговое увеличение сложности: начинать с небольшой сети, постепенно добавляя слои и фильтры, одновременно корректируя learning rate и регуляризацию.

Эти методы позволяют выявить узкие места сходимости, корректировать параметры обучения и архитектуру, обеспечивая стабильное и эффективное обучение с использованием ConvNetJS.