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

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

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

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

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

6 ответов

Решение

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


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

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

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

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


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

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

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

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

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


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

Причина: иногда вычисления потерь в слоях потерь вызывают nan s, чтобы появиться. Например, гостиницы 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 печатать, чтобы записывать больше информации об отладке (включая величины градиента и значения активации) во время обучения: эта информация может помочь в выявлении выбросов градиента и других проблем в процессе обучения.

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

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

bias_filler {type: "constant" value: 0}

Еще одно решение для тех, кто застрял, как я только что был-

Я получал потери nan или inf в сети, которую я настроил с помощью float16 dtype по слоям и входным данным. После того, как все остальное потерпело неудачу, мне пришло в голову вернуться к float32, и потери nan были решены!

Итак, суть в том, что если вы переключили dtype на float16, измените его обратно на float32.

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

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

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

Другие вопросы по тегам