Dropout

Dropout — это техника регуляризации, предназначенная для предотвращения переобучения нейронных сетей. Основная идея заключается в случайном «выключении» части нейронов на этапе обучения, что заставляет сеть развивать более устойчивые и обобщающие признаки.


Принцип работы Dropout

Во время обучения, для каждого мини-батча случайным образом выбирается подмножество нейронов, которые временно игнорируются. Игнорирование реализуется путем умножения активаций на случайный бинарный маскирующий вектор, где значения 0 означают «выключено», а 1 — «включено». Этот процесс можно формально описать так:

  • Пусть (x_i) — активация i-го нейрона в слое.
  • Пусть (r_i) — случайная переменная, принимающая значение 1 с вероятностью (p) и 0 с вероятностью (1-p).
  • На этапе прямого прохода новая активация вычисляется как:

[ = r_i x_i]

  • На этапе обратного распространения градиенты передаются только через включённые нейроны.

Параметр (p) называется keep probability и определяет долю нейронов, которые остаются активными.


Dropout в ConvNetJS

ConvNetJS — это библиотека на JavaScript, предоставляющая средства для построения и обучения нейронных сетей, включая свёрточные и полносвязные слои. Dropout реализуется в виде слоя DropoutLayer.

Пример создания слоя Dropout:

var layer = new convnetjs.DropoutLayer({drop_prob: 0.5});

Здесь drop_prob определяет вероятность выключения нейронов, то есть (1 - p). Для большинства задач используют значения от 0.2 до 0.5, в зависимости от сложности модели и объёма данных.


Структура DropoutLayer

Основные свойства слоя:

  • drop_prob — вероятность отключения нейронов.
  • out_sx, out_sy, out_depth — размерность выходного тензора, совпадает с входной.
  • drop_mask — массив, сохраняющий маску для каждого обучения, используется при обратном распространении.

Методы:

  • forward(V, is_training) — выполняет прямой проход. На этапе обучения генерируется маска и применяется к активациям. На этапе тестирования активации масштабируются на (1 - drop_prob) для сохранения среднего значения.
  • backward() — распространяет градиенты только через включённые нейроны, игнорируя отключённые.
  • getParams() — Dropout не имеет обучаемых параметров, поэтому возвращает пустой массив.

Использование Dropout в сети

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

var layer_defs = [];
layer_defs.push({type:'input', out_sx:1, out_sy:1, out_depth:784});
layer_defs.push({type:'fc', num_neurons:100, activation:'relu'});
layer_defs.push({type:'dropout', drop_prob:0.5});
layer_defs.push({type:'fc', num_neurons:10, activation:'softmax'});

var net = new convnetjs.Net();
net.makeLayers(layer_defs);

Здесь Dropout слой отключает половину нейронов первого полносвязного слоя на каждой итерации обучения. Это снижает переобучение и заставляет сеть учиться более обобщённым признакам.


Влияние на обучение и тестирование

  • Обучение: Dropout уменьшает способность сети слишком сильно подстраиваться под тренировочные данные. Каждый прямой проход случайным образом меняет конфигурацию сети, что делает обучение более разнообразным.
  • Тестирование: На этапе предсказания все нейроны активны, но их выходы масштабируются на (1 - drop_prob) для компенсации эффекта отключения.

Практические рекомендации

  • Dropout эффективен для глубоких сетей с большим количеством параметров.
  • Для свёрточных слоёв рекомендуется меньшая вероятность отключения (например, 0.2), так как свёрточные слои уже обладают свойством регуляризации через локальные фильтры.
  • Использовать Dropout не обязательно на всех слоях. Обычно достаточно применять его к последним полносвязным слоям.
  • Комбинирование Dropout с другими методами регуляризации (L2, Data Augmentation) улучшает обобщающую способность модели.

Внутреннее устройство

DropoutLayer хранит маску в виде объекта vol (тензора ConvNetJS). На каждом прямом проходе генерируется случайная маска:

for(var i=0;i<V.w.length;i++){
    if(Math.random()<this.drop_prob){
        this.drop_mask.w[i] = 0;
    } else {
        this.drop_mask.w[i] = 1;
    }
    this.out_act.w[i] = V.w[i]*this.drop_mask.w[i];
}

На обратном проходе градиенты умножаются на ту же маску:

for(var i=0;i<this.out_act.w.length;i++){
    V.dw[i] = this.drop_mask.w[i] * this.out_act.dw[i];
}

Это гарантирует, что градиенты учитывают только активные нейроны.


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