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