Подтвердить что ты не робот

Общие причины неанса во время обучения

Я заметил, что частое появление во время обучения составляет NAN.

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

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

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

4b9b3361

Ответ 1

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


Включение градиента

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

Что вы ожидаете:. Посмотрев на журнал выполнения, вы должны посмотреть на значения потерь для каждой итерации. Вы заметите, что потеря начинает значительно возрастать от итерации до итерации, в конце концов потеря будет слишком большой, чтобы быть представленной переменной с плавающей запятой, и она станет 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...
Для получения дополнительной информации о скорости обучения в кафе см. эту тему.


Функция Faulty Loss

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

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

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

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


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

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

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

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


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

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

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

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


Неустойчивости в "BatchNorm"

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


В последнее время мне стало известно о debug_info: установка debug_info: true в 'solver.prototxt' сделает печать caffe для записи дополнительной информации об отладке (включая градиентные величины и значения активации) во время обучения: эта информация может помочь в выявлении градиентных раздутий и других проблем в процессе обучения.

Ответ 2

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

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

bias_filler {     type: "constant"     Значение: 0   }

Ответ 3

Этот ответ не о причине для nan s, а скорее предлагает способ его отладки. У вас может быть этот слой 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
  }
}

Ответ 4

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