Распространенные причины нанов во время тренировок

86

Я заметил, что во время тренировок вводится частое явление NAN.

Часто кажется, что это происходит из-за того, что веса во внутреннем продукте / полностью связанных или сверточных слоях взрываются.

Это происходит потому, что вычисление градиента резко увеличивается? Или это из-за инициализации веса (если да, то почему инициализация веса имеет такой эффект)? Или это, вероятно, вызвано характером входных данных?

Общий вопрос здесь прост: какова наиболее частая причина возникновения NAN во время обучения? А во-вторых, какие есть методы борьбы с этим (и почему они работают)?

Эйдан Гомес
источник
Вы вызываете определенные функции MATLAB? Это все ваш собственный код?
Мэтью Ганн
2
@MatthewGunn Я не думаю, что этот вопрос специфичен для Matlab, а скорее caffeсвязан с ним.
Шай

Ответы:

137

Хороший вопрос.
Я сталкивался с этим явлением несколько раз. Вот мои наблюдения:


Градиент взорвать

Причина: большие градиенты сбивают процесс обучения с пути.

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

Что вы можете сделать: Уменьшите base_lr(в solver.prototxt) на порядок (как минимум). Если у вас несколько слоев потерь, вы должны проверить журнал, чтобы увидеть, какой слой отвечает за увеличение градиента, и уменьшить loss_weight(в train_val.prototxt) для этого конкретного слоя, а не для общего base_lr.


Плохая политика скорости обучения и параметры

Причина: caffe не может вычислить допустимую скорость обучения и получает 'inf'или 'nan'вместо этого эта недопустимая скорость умножает все обновления и, таким образом, делает недействительными все параметры.

Чего следует ожидать: глядя в журнал выполнения, вы должны увидеть, что сама скорость обучения составляет 'nan', например:

... sgd_solver.cpp:106] Iteration 0, lr = -nan

Что вы можете сделать: исправить все параметры, влияющие на скорость обучения, в вашем 'solver.prototxt'файле.
Например, если вы используете lr_policy: "poly"и забыли определить max_iterпараметр, вы получите lr = nan...
Подробнее о скорости обучения в кафе см. В этой ветке .


Неисправная функция потери

Причина: Иногда при вычислении потерь в слоях потерь nanпоявляется s. Например, InfogainLossслой подачи с ненормализованными значениями , с использованием настраиваемого слоя потерь с ошибками и т. Д.

Чего следует ожидать: глядя в журнал выполнения, вы, вероятно, не заметите ничего необычного: потери постепенно уменьшаются, и внезапно nanпоявляется значок.

Что вы можете сделать: посмотрите, сможете ли вы воспроизвести ошибку, добавить распечатку к слою потерь и отладить ошибку.

Например: однажды я использовал потерю, которая нормализовала штраф на частоту появления меток в пакете. Так уж получилось, что если одна из обучающих меток вообще не появилась в партии - вычисляемые потери производили nans. В этом случае достаточно было работать с достаточно большими партиями (по количеству этикеток в наборе), чтобы избежать этой ошибки.


Неправильный ввод

Причина: у вас есть вход nanв него!

Чего и следовало ожидать: как только процесс обучения "попадает" в этот ошибочный ввод, становится выходом nan. Глядя на журнал выполнения, вы, вероятно, не заметите ничего необычного: потери постепенно уменьшаются, и вдруг nanпоявляется значок.

Что вы можете сделать: пересоберите свои входные наборы данных (lmdb / leveldn / hdf5 ...), убедитесь, что у вас нет плохих файлов изображений в вашем наборе для обучения / проверки. Для отладки вы можете построить простую сеть, которая считывает входной слой, имеет фиктивную потерю поверх нее и проходит через все входы: если один из них неисправен, эта фиктивная сеть также должна работать nan.


шаг больше, чем размер ядра в "Pooling"слое

По какой-то причине выбор stride> kernel_sizeдля объединения может привести к nans. Например:

layer {
  name: "faulty_pooling"
  type: "Pooling"
  bottom: "x"
  top: "y"
  pooling_param {
    pool: AVE
    stride: 5
    kernel: 3
  }
}

результаты с nans в y.


Нестабильности в "BatchNorm"

Сообщалось, что при некоторых настройках "BatchNorm"слой может выводить nans из-за числовой нестабильности.
Эта проблема возникла в bvlc / caffe, и PR № 5136 пытается ее исправить.


Недавно я узнал о debug_infoфлаге: установка debug_info: trueв 'solver.prototxt'заставит Caffe печать войти больше отладочной информации ( в том числе градиентные величин и значений активации) во время тренировки: Эта информация может помочь в пятнистость градиентные раздутия и другие проблемы в процессе обучения .

Шай
источник
Спасибо, как интерпретировать эти числа? Что это за числа? pastebin.com/DLYgXK5v, почему для каждого слоя выводится только одно число !? как должны выглядеть эти числа, чтобы кто-то знал, что есть проблема или нет !?
Rika
@Hossein, это именно то, о чем этот пост .
Шай
Спасибо за этот ответ. Я получаю потерю NAN для приложения сегментации изображений, обученного с помощью потери DICE (даже после добавления небольшой постоянной эпсилон / гладкости). В моем наборе данных есть некоторые изображения, соответствующие истины которых не содержат меток переднего плана, и когда я удалил эти изображения из обучения, потери были стабилизированы. Я не уверен, почему это так?
samra irshad
@samrairshad вы пытались увеличить эпсилон в проигрыше DICE?
Шай
Да, я сделал. Я открыл пост при переполнении стека и вставил эволюцию потерь для некоторых эпох. Вот ссылка: stackoverflow.com/questions/62259112/…
samra irshad
5

В моем случае причиной было отсутствие смещения в слоях свертки / деконволюции.

Решение: добавьте следующее к параметрам сверточного слоя.

bias_filler {тип: "постоянное" значение: 0}

изады
источник
как это будет выглядеть в matconvnet? Есть что-то вроде biases .init_bias * ones (1,4, single)
h612
4

Этот ответ не касается причины nans, а скорее предлагает способ ее отладки. У вас может быть этот слой Python:

class checkFiniteLayer(caffe.Layer):
  def setup(self, bottom, top):
    self.prefix = self.param_str
  def reshape(self, bottom, top):
    pass
  def forward(self, bottom, top):
    for i in xrange(len(bottom)):
      isbad = np.sum(1-np.isfinite(bottom[i].data[...]))
      if isbad>0:
        raise Exception("checkFiniteLayer: %s forward pass bottom %d has %.2f%% non-finite elements" %
                        (self.prefix,i,100*float(isbad)/bottom[i].count))
  def backward(self, top, propagate_down, bottom):
    for i in xrange(len(top)):
      if not propagate_down[i]:
        continue
      isf = np.sum(1-np.isfinite(top[i].diff[...]))
        if isf>0:
          raise Exception("checkFiniteLayer: %s backward pass top %d has %.2f%% non-finite elements" %
                          (self.prefix,i,100*float(isf)/top[i].count))

Добавление этого слоя в train_val.prototxtопределенные моменты, которые вы подозреваете, может вызвать проблемы:

layer {
  type: "Python"
  name: "check_loss"
  bottom: "fc2"
  top: "fc2"  # "in-place" layer
  python_param {
    module: "/path/to/python/file/check_finite_layer.py" # must be in $PYTHONPATH
    layer: "checkFiniteLayer"
    param_str: "prefix-check_loss" # string for printouts
  }
}
Шай
источник
1

Learning_rate высока и должна быть уменьшена Точность в коде RNN была nan, с выбором низкого значения для скорости обучения, которую он исправляет

Мохаммад Расул танхаталаб
источник
-1

Я пытался создать автоэнкодер с разреженным кодом и имел в нем несколько слоев, чтобы добиться разреженности. Во время работы в сети я наткнулся на NaN. При удалении некоторых слоев (в моем случае мне действительно пришлось удалить 1) я обнаружил, что NaN исчезли. Итак, я полагаю, что слишком большая разреженность также может привести к NaN (могли быть вызваны вычисления 0/0 !?)

LKB
источник
можешь быть более конкретным? Можете ли вы предоставить подробную информацию о конфигурации, в которой были nans, и фиксированной конфигурации? какой тип слоев? какие параметры?
Shai
1
@shai Я использовал несколько слоев InnerProduct (lr_mult 1, decay_mult 1, lr_mult 2, decay_mult 0, xavier, std: 0.01), за каждым из которых следует ReLU (кроме последнего). Я работал с MNIST, и, если я правильно помню, архитектура была 784 -> 1000 -> 500 -> 250 -> 100 -> 30 (и симметричная фаза декодера); удаление слоя 30 вместе с его ReLU привело к исчезновению NaN.
LKB