Хороший вопрос.
Я сталкивался с этим явлением несколько раз. Вот мои наблюдения:
Градиент взорвать
Причина: большие градиенты сбивают процесс обучения с пути.
Чего следует ожидать: глядя на журнал выполнения, вы должны смотреть на значения потерь на итерацию. Вы заметите, что потери начинают значительно расти от итерации к итерации, в конечном итоге потеря будет слишком большой, чтобы ее можно было представить переменной с плавающей запятой, и она станет 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
появляется значок.
Что вы можете сделать: посмотрите, сможете ли вы воспроизвести ошибку, добавить распечатку к слою потерь и отладить ошибку.
Например: однажды я использовал потерю, которая нормализовала штраф на частоту появления меток в пакете. Так уж получилось, что если одна из обучающих меток вообще не появилась в партии - вычисляемые потери производили 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
s в y
.
Нестабильности в "BatchNorm"
Сообщалось, что при некоторых настройках "BatchNorm"
слой может выводить nan
s из-за числовой нестабильности.
Эта проблема возникла в bvlc / caffe, и PR № 5136 пытается ее исправить.
Недавно я узнал о debug_info
флаге: установка debug_info: true
в 'solver.prototxt'
заставит Caffe печать войти больше отладочной информации ( в том числе градиентные величин и значений активации) во время тренировки: Эта информация может помочь в пятнистость градиентные раздутия и другие проблемы в процессе обучения .