Общие причины нанс во время обучения
Я заметил, что частое явление во время обучения 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!?)