Как настроить InceptionV3 в Керасе

Я пытаюсь обучить классификатор на основе архитектуры InceptionV3 в Керасе. Для этого я загрузил предварительно обученную модель InceptionV3 без вершины и добавил последний полностью связанный слой для классов моей задачи классификации. В первом обучении я заморозил базовую модель InceptionV3 и обучил только последний полностью связанный слой.

На втором этапе я хочу точно настроить сеть, разморозив часть модели InceptionV3. Теперь я знаю, что модель InceptionV3 широко использует слои BatchNorm. Рекомендуется (ссылка на документацию), когда слои BatchNorm размораживаются для точной настройки при передаче обучения, чтобы сохранить фиксированными среднее значение и отклонения, вычисленные слоями BatchNorm. Это должно быть сделано путем установки слоев BatchNorm в режим вывода вместо режима обучения. См. Также: В чем разница между аргументом обучения в call () и атрибутом обучаемого?

Теперь мой главный вопрос: как установить ТОЛЬКО слои BatchNorm модели InceptionV3 в режим вывода?

В настоящее время я установил всю базовую модель InceptionV3 в режим вывода, установив аргумент обучения при сборке сети:

inputs = keras.Input(shape=input_shape)
# Scale the 0-255 RGB values to 0.0-1.0 RGB values
x = layers.experimental.preprocessing.Rescaling(1./255)(inputs)
# Set include_top to False so that the final fully connected (with pre-loaded weights) layer is not included.
# We will add our own fully connected layer for our own set of classes to the network.
base_model = keras.applications.InceptionV3(input_shape=input_shape, weights='imagenet', include_top=False)
x = base_model(x, training=False)
# Classification block
x = layers.GlobalAveragePooling2D(name='avg_pool')(x)
x = layers.Dense(num_classes, activation='softmax', name='predictions')(x)
model = keras.Model(inputs=inputs, outputs=x)

Что мне не нравится в этом, так это то, что таким образом я установил всю модель в режим вывода, который может установить некоторые слои в режим вывода, которого не должно быть.

Вот часть кода, которая загружает веса из начального обучения, которое я сделал, и код, который замораживает первые 150 слоев и размораживает остальные слои части InceptionV3:

model.load_weights(load_model_weight_file_name)
for layer in base_model.layers[: 150]:
    layer.trainable = False
for layer in base_model.layers[ 150:]:
    layer.trainable = True

Остальная часть моего кода (здесь не показана) представляет собой обычные вызовы компиляции и подгонки.

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

Еще я заметил, что когда я делаю всю часть InceptionV3 обучаемой

base_model.trainable = True

что обучение начинается с серверной точностью на порядки меньшей, чем была завершена моя первая тренировка (и, конечно, с гораздо более высокими потерями). Может кто-то объяснить это мне? Я бы по крайней мере ожидал, что тренировка продолжится, если бы она была прервана с точки зрения точности и потерь.


person user1158795    schedule 01.04.2021    source источник


Ответы (1)


Вы можете сделать что-то вроде:

for layer in base_model.layers:
    if isinstance(layer ,tf.keras.layers.BatchNormalization):
        layer.trainable=False

Это будет проходить по каждому слою и проверять тип, устанавливая режим вывода, если слой - BatchNorm.

Что касается низкой начальной точности во время обучения передачи, вы загружаете только веса, а не состояние оптимизатора (как это происходит с полным model.load(), который загружает архитектуру, веса, состояние оптимизатора и т. Д.).

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

person ML_Engine    schedule 01.04.2021
comment
Спасибо за подсказку, но я думаю, это не то, что я ищу. Поскольку я действительно хочу, чтобы эти слои учились (потому что они должны изучать гамма- и бета-веса, верно?), Я только не хочу, чтобы они находились в режиме обучения, чтобы избежать того, что слой будет вычислять среднее значение и дисперсию для пакета . - person user1158795; 01.04.2021
comment
Я не совсем понимаю ваше объяснение точности. Когда я загружаю веса, то в начале тренировки сеть будет примерно такой же, как и раньше, и поэтому результат классификации будет примерно таким же. Даже на первых шагах первой эпохи я вижу гораздо меньшую точность (и более высокие потери), чем раньше. - person user1158795; 01.04.2021
comment
Ваш вопрос заключался в том, как установить ТОЛЬКО слои BatchNorm модели InceptionV3 в режим вывода, и именно так вы бы это сделали. Я думаю, здесь может быть некоторая путаница в терминологии - если вы хотите, чтобы слои обучались (layer.trainable=True), то они по определению находятся в режиме обучения. Установка trainable = false - это определение режима вывода, и это то, что keras / tf делает автоматически, когда вы вызываете base_model.predict. Вы не можете заставить слой учиться и не находиться в режиме обучения. - person ML_Engine; 02.04.2021
comment
Просто для пояснения. Рекомендуется, когда слои BatchNorm разморожены для точной настройки при передаче обучения - здесь разморозить означает установить layer.trainable = True, с предположением, что вы заморозите / установите trainable = False для всех остальных слоев. Вы можете либо заморозить всю модель и добавить несколько дополнительных слоев поверх, либо разморозить все / некоторые слои и выбрать низкую скорость обучения, чтобы немного изменить веса всей модели. - person ML_Engine; 02.04.2021
comment
В комментарии к точности - когда вы загружаете только веса (а не оптимизатор и т. Д.), Тогда да, веса модели будут идентичны, но оптимизатор также сохраняет состояние, когда вы обучаете модель, и поэтому, если вы не загружаете оптимизатор с первого раунда обучения (т.е. состояние оптимизатора сбрасывается), то ему потребуется несколько начальных пакетов для повторного вычисления своего состояния, поэтому ваша точность намного ниже, чем в начале. Вы позволили ему поработать, чтобы посмотреть, улучшится ли точность? - person ML_Engine; 02.04.2021
comment
Согласно документации Keras, обучаемый и работающий в режиме обучения уровень - это две ортогональные концепции: keras.io/getting_started/faq/ Я хочу, чтобы некоторые слои BatchNorm были разморожены, но находились в режиме вывода, как предлагается в документации Keras о трансферном обучении: keras.io/guides/transfer_learning/#finetuning - person user1158795; 06.04.2021