Классификация изображений. Потеря валидации застряла во время обучения с начальным этапом (v1)

Я создал небольшой набор данных для обучения / классификации изображений с 4 классами. Набор обучающих данных содержит ~ 110 000 изображений. Набор данных проверки содержит ~ 6.000 изображений.

Проблема, с которой я сталкиваюсь, заключается в том, что во время обучения как точность обучения (измеренная как средняя точность на последних обучающих выборках), так и потери при обучении улучшаются, в то время как точность проверки и потери остаются неизменными.

Это происходит только тогда, когда я использую начальные модели и модели повторной сети, если я использую модель alexnet для тех же данных обучения и проверки, потеря проверки и точность улучшаются.

В своих экспериментах я использую несколько сверточных архитектур, импортируя их из tensorflow.contrib.slim .nets

Код организован следующим образом:

...

images, labels = preprocessing(..., train=True)
val_images, val_labels = preprocessing(..., train=False)

...

# AlexNet model
with slim.arg_scope(alexnet.alexnet_v2_arg_scope()):
    logits, _ = alexnet.alexnet_v2(images, ..., is_training=True)
    tf.get_variable_scope().reuse_variables()
    val_logits, _ = alexnet.alexnet_v2(val_images, ..., is_training=False)

# Inception v1 model
with slim.arg_scope(inception_v1_arg_scope()):
    logits, _ = inception_v1(images, ..., is_training=True)
    val_logits, _ = inception_v1(val_images, ..., is_training=False, reuse=True)

loss = my_stuff.loss(logits, labels)
val_loss = my_stuff.loss(val_logits, val_labels)

training_accuracy_op = tf.nn.in_top_k(logits, labels, 1)
top_1_op = tf.nn.in_top_k(val_logits, val_labels, 1)
train_op = ...

...

Вместо использования отдельного сценария eval я запускаю этап проверки в конце каждой эпохи, а также для целей отладки я запускаю этап раннего val (перед обучением) и проверяю точность обучения путем усреднения прогнозы обучения на последних x шагах.

Когда я использую модель Inception v1 (комментируя модель alexnet), через 1 эпоху вывод логгера выглядит следующим образом:

early Validation Step
precision @ 1 = 0.2440 val loss = 1.39
Starting epoch 0
step 50, loss = 1.38, training_acc = 0.3250
...
step 1000, loss = 0.58, training_acc = 0.6725
...
step 3550, loss = 0.45, training_acc = 0.8063
Validation Step
precision @ 1 = 0.2473 val loss = 1.39

Как показано, точность обучения и потери значительно улучшаются после одной эпохи, но потери при проверке не меняются вообще. Это было проверено не менее 10 раз, результат всегда один и тот же. Я бы понял, если бы потеря валидации ухудшилась из-за переобучения, но в этом случае она вообще не меняется.

Чтобы исключить какие-либо проблемы с данными проверки, я также представляю результаты во время обучения с использованием реализации AlexNet в slim. Обучение с использованием модели alexnet дает следующий результат:

early Validation Step
precision @ 1 = 0.2448 val loss = 1.39
Starting epoch 0
step 50, loss = 1.39, training_acc = 0.2587
...
step 350, loss = 1.38, training_acc = 0.2919
...
step 850, loss = 1.28, training_acc = 0.3898
Validation Step
precision @ 1 = 0.4069 val loss = 1.25

Точность и потеря валидации, как в обучающих, так и в тестовых данных, корректно улучшаются при использовании модели alexnet, и они продолжают улучшаться в последующие эпохи.

Я не понимаю, в чем может быть причина проблемы и почему она возникает при использовании моделей inception / resnet, но не при обучении с alexnet.

Есть у кого-нибудь идеи?


person user3897060    schedule 04.08.2017    source источник


Ответы (2)


После поиска на форумах, чтения различных тем и экспериментов я нашел корень проблемы.

Проблема заключалась в использовании train_op, который был в основном переработан из другого примера, он хорошо работал с моделью alexnet, но не работал с другими моделями, поскольку в нем отсутствовали обновления пакетной нормализации.

Чтобы исправить это, мне пришлось использовать либо

optimizer = tf.train.GradientDescentOptimizer(0.005)
train_op = slim.learning.create_train_op(total_loss, optimizer)

or

train_op = tf.contrib.layers.optimize_loss(total_loss, global_step, .005, 'SGD')

Кажется, это позаботится о выполняемых обновлениях батчнорма.

Проблема все еще сохранялась для коротких тренировочных прогонов из-за медленных обновлений скользящих средних.

По умолчанию slim arg_scope имеет затухание, равное 0,9997, что является стабильным, но, очевидно, требует много шагов для схождения. Использование того же arg_scope, но с затуханием, установленным на 0,99 или 0,9, помогло в этом коротком сценарии обучения.

person user3897060    schedule 10.08.2017

Похоже, вы используете логиты для расчета потерь при проверке; используйте прогнозы, это может помочь.

val_logits, _ = inception_v1(val_images, ..., is_training=False, reuse=True)
val_logits = tf.nn.softmax(val_logits)
person Ishant Mrinal    schedule 04.08.2017
comment
Потери рассчитываются с помощью tf.nn.sparse_softmax_cross_entropy_with_logits, который использует немасштабированные логиты и выполняет softmax внутренне. - person user3897060; 04.08.2017