Общие причины nans во время обучения
Я заметил, что частым явлением во время тренировки является NAN
s вводится.
часто кажется, что он вводится весами во внутренних продуктах / полностью связанных или сверточных слоях.
это происходит потому, что вычисление градиента взрывается? Или это из-за инициализации веса (если да, то почему инициализация веса имеет этот эффект)? Или это, вероятно, вызвано характером входных данных?
в главный вопрос здесь просто:какова наиболее распространенная причина для NANs, происходящих во время обучения? а во-вторых, каковы некоторые методы борьбы с этим (и почему они работают)?
4 ответов
хороший вопрос.
Я сталкивался с этим явлением несколько раз. Вот мои наблюдения:--35-->
градиент взорвать
причина: большие градиенты выбивают процесс обучения из колеи.
что вас ждет: глядя на журнал выполнения, вы должны посмотреть на значения потерь за итерацию. Вы заметите, что потеря начинает расти значительно от итерации к итерации, в конце концов, потеря будет слишком большой, чтобы быть представленной переменной с плавающей запятой, и она станет nan
.
что делать: уменьшить base_lr
(в решатель.prototxt) на порядок (по крайней мере). Если у вас есть несколько слоев потери, вы должны проверить журнал, чтобы увидеть, какой слой отвечает за градиент взорвать и уменьшить loss_weight
(в train_val.prototxt) для этого конкретного слоя, а не общей base_lr
.
плохая политика скорости обучения и params
причина: caffe не удается вычислить допустимую скорость обучения и получает 'inf'
или 'nan'
вместо этого эта недопустимая скорость умножает все обновления и, таким образом, аннулирует все параметры.
что вас ждет: глядя на журнал выполнения, вы должны видеть, что сама скорость обучения становится 'nan'
, для пример:
... sgd_solver.cpp:106] Iteration 0, lr = -nan
что делать: исправить все параметры, влияющие на скорость обучения в .
Например, если вы используете lr_policy: "poly"
и вы забыли определить max_iter
параметр, вы в конечном итоге с lr = nan
...
Дополнительные сведения о скорости обучения в caffe см. В разделе этой теме.
неисправная функция потери
причина: иногда вычисления потерь в слоях потерь вызывает 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 для регистрации больше отладки информация (включая значения градиента и значения активации) во время обучения: эта информация может помощь в обнаружении градиентных взрывов и других проблем в учебном процессе.
в моем случае причиной была не установка смещения в слоях свертки/деконволюции.
устранение: добавьте к параметрам слоя свертки следующее.
bias_filler { тип: "константа" значение: 0 }
этот ответ не вызывает 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
}
}
Я пытался построить разреженный автоэнкодер и несколько слоев в нем, чтобы вызвать разреженности. Запустив сеть, я наткнулся на НАН. При удалении некоторых слоев (в моем случае мне действительно пришлось удалить 1) я обнаружил, что NaN исчез. Итак, я думаю, что слишком большая разреженность может привести и к NaN (возможно, были вызваны некоторые вычисления 0/0!?)