Оптимизатор Адама становится более быстрым после 200 тыс. Партий, растет потеря обучения

Я наблюдаю очень странное поведение при обучении сети, где после нескольких 100-тысячных итераций (от 8 до 10 часов) обучения хорошо все ломается, а уроки обучения растут:

Потеря взрывается

Данные тренировки рандомизированы и распределены по многим файлам .tfrecord, содержащим примеры 1000, а затем снова перетасовываются на этапе ввода и сопоставляются с примерами 200.

Фон

Я проектирую сеть, которая одновременно выполняет четыре различные задачи регрессии, например. определяя вероятность появления объекта на изображении и одновременного определения его ориентации. Сеть начинается с нескольких сверточных слоев, некоторые с остаточными соединениями, а затем вступает в четыре полностью связанных сегмента.

Поскольку первая регрессия приводит к вероятности, я использую кросс-энтропию для потери, тогда как другие используют классическое расстояние L2. Однако из-за их природы вероятность потери составляет порядка 0..1, а потери на ориентацию могут быть намного больше, скажем 0..10. Я уже нормализовал как входные, так и выходные значения и использовал обрезку

normalized = tf.clip_by_average_norm(inferred.sin_cos, clip_norm=2.)

в случаях, когда ситуация может стать очень плохой.

Я (успешно) использовал оптимизатор Адама для оптимизации на тензоре, содержащем все различные потери (а не reduce_sum их), например:

reg_loss = tf.reduce_sum(tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES))
loss = tf.pack([loss_probability, sin_cos_mse, magnitude_mse, pos_mse, reg_loss])

optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate,
                                   epsilon=self.params.adam_epsilon)
op_minimize = optimizer.minimize(loss, global_step=global_step)

Чтобы отобразить результаты в TensorBoard, я тогда фактически делаю

loss_sum = tf.reduce_sum(loss)

для скалярной сводки.

Адам настроен на скорость обучения 1e-4 и epsilon 1e-4 (я вижу то же поведение со значением по умолчанию для эпизода, и он ломается еще быстрее, когда я сохраняю скорость обучения на 1e-3). Регуляризация также не оказывает никакого влияния на это, она делает этот вид - последовательно в какой-то момент.

Я также должен добавить, что остановка обучения и перезапуск с последней контрольной точки - подразумевая, что файлы ввода обучения снова перетасовываются - приводит к такому же поведению. Обучение всегда, похоже, ведет себя аналогично в этот момент.

Ответ 1

Да. Это известная проблема Адама.

Уравнения для Адама

t <- t + 1
lr_t <- learning_rate * sqrt(1 - beta2^t) / (1 - beta1^t)

m_t <- beta1 * m_{t-1} + (1 - beta1) * g
v_t <- beta2 * v_{t-1} + (1 - beta2) * g * g
variable <- variable - lr_t * m_t / (sqrt(v_t) + epsilon)

где m - экспоненциальное скользящее среднее среднего градиента, а v - экспоненциальное скользящее среднее квадратов градиентов. Проблема в том, что, когда вы тренируетесь в течение длительного времени и близки к оптимальному, тогда v может стать очень маленьким. Если тогда внезапно градиенты снова начнут расти, он будет разделен на очень небольшое число и взорвется.

По умолчанию beta1=0.9 и beta2=0.999. Поэтому m изменяется гораздо быстрее, чем v. Таким образом, m может снова стать большим, а v все еще мал и не может догнать.

Чтобы устранить эту проблему, вы можете увеличить epsilon, которая по умолчанию 10-8. Таким образом, останавливается проблема деления почти на 0. В зависимости от вашей сети значение epsilon в 0.1, 0.01 или 0.001 может быть хорошим.

Ответ 2

Да, это может быть какой-то сложный случай с неустойчивыми числами/уравнениями, но, скорее всего, ваша скорость обучения просто просто высока, так как ваша потеря быстро уменьшается до 25K, а затем осциллирует много на одном уровне. Попытайтесь уменьшить его в 0,1 раза и посмотреть, что произойдет. Вы должны иметь возможность достичь еще более низкой величины потерь.

Продолжайте изучать!:)