Трансферное обучение работает только с обучаемым значением false - PullRequest
0 голосов
/ 18 апреля 2020

У меня две инициализированные модели, подобные этой

vgg19 = keras.applications.vgg19.VGG19(
  weights='imagenet',
  include_top=False,
  input_shape=(img_height, img_width, img_channels))

for layer in vgg19.layers:
  layer.trainable = False

model = Sequential(layers=vgg19.layers)
model.add(Flatten())
model.add(Dense(1024, activation='relu'))
model.add(Dense(512, activation='relu'))
model.add(Dense(10, activation='softmax'))

opt = Adam(learning_rate=0.001, beta_1=0.9)
model.compile(
    loss='categorical_crossentropy',
    optimizer=opt,
    metrics=['accuracy'])

и

vgg19_2 = keras.applications.vgg19.VGG19(
    weights='imagenet',
    include_top=False,
    input_shape=(img_height, img_width, img_channels))

model2 = Sequential(layers=vgg19_2.layers)
model2.add(Dense(1024, activation='relu'))
model2.add(Dense(512, activation='relu'))
model2.add(Dense(10, activation='softmax'))

opt = Adam(learning_rate=0.001, beta_1=0.9)
model2.compile(
    loss='categorical_crossentropy',
    optimizer=opt,
    metrics=['accuracy'])

Другими словами, единственное отличие состоит в том, что вторая модель не устанавливает обучаемый параметр слоев vgg19 в значение false , К сожалению, модель с обучаемым значением true не запоминает данные.

Когда я использую model.fit, я получаю

Trainable set to false:
Epoch 1/51
2500/2500 [==============================] - 49s 20ms/step - loss: 1.4319 - accuracy: 0.5466 - val_loss: 1.3951 - val_accuracy: 0.5693
Epoch 2/51
2500/2500 [==============================] - 47s 19ms/step - loss: 1.1508 - accuracy: 0.6009 - val_loss: 0.7832 - val_accuracy: 0.6023
Epoch 3/51
2500/2500 [==============================] - 48s 19ms/step - loss: 1.0816 - accuracy: 0.6256 - val_loss: 0.6782 - val_accuracy: 0.6153
Epoch 4/51
2500/2500 [==============================] - 47s 19ms/step - loss: 1.0396 - accuracy: 0.6450 - val_loss: 1.3045 - val_accuracy: 0.6103

Модель обучается с точностью до 65% в течение нескольких эпох. Однако, используя модель 2, которая должна быть способна делать еще лучшие прогнозы (поскольку есть более обучаемые параметры), я получаю:

Epoch 1/5
2500/2500 [==============================] - 226s 90ms/step - loss: 2.3028 - accuracy: 0.0980 - val_loss: 2.3038 - val_accuracy: 0.1008
Epoch 2/5
2500/2500 [==============================] - 311s 124ms/step - loss: 2.3029 - accuracy: 0.0980 - val_loss: 2.2988 - val_accuracy: 0.1017
Epoch 3/5
2500/2500 [==============================] - 306s 123ms/step - loss: 2.3029 - accuracy: 0.0980 - val_loss: 2.3052 - val_accuracy: 0.0997
Epoch 4/5
2500/2500 [==============================] - 321s 129ms/step - loss: 2.3029 - accuracy: 0.0972 - val_loss: 2.3028 - val_accuracy: 0.0997
Epoch 5/5
2500/2500 [==============================] - 300s 120ms/step - loss: 2.3028 - accuracy: 0.0988 - val_loss: 2.3027 - val_accuracy: 0.1007

Когда я тогда пытаюсь вычислить весовые градиенты на моих данных, я получаю только нули. Я понимаю, что может потребоваться много времени, чтобы обучить такую ​​большую нейронную net, как vgg, оптимальной, но, учитывая, что рассчитанные градиенты для последних 3 слоев должны быть очень похожими в обоих случаях, почему точность такая низкая? Тренировка на большее время не дает никаких улучшений.

1 Ответ

1 голос
/ 18 апреля 2020

Попробуйте:

  1. Обучите первую модель, которая устанавливает trainable в False. Вам не нужно тренировать его до насыщения, поэтому я бы начал с ваших 5 эпох.
  2. Go назад и установите trainable в True для всех параметров vgg19. Затем, согласно документации , вы можете перестроить и перекомпилировать модель, чтобы эти изменения вступили в силу.
  3. Продолжить обучение по перестроенной модели, которая теперь имеет все параметры, доступные для настройки.

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

Собрав все это вместе в некоторый код, это будет выглядеть примерно так this.

# Original code. Transfer VGG and freeze the weights.
vgg19 = keras.applications.vgg19.VGG19(
  weights='imagenet',
  include_top=False,
  input_shape=(img_height, img_width, img_channels))

for layer in vgg19.layers:
  layer.trainable = False

model = Sequential(layers=vgg19.layers)
model.add(Flatten())
model.add(Dense(1024, activation='relu'))
model.add(Dense(512, activation='relu'))
model.add(Dense(10, activation='softmax'))

opt = Adam(learning_rate=0.001, beta_1=0.9)
model.compile(
    loss='categorical_crossentropy',
    optimizer=opt,
    metrics=['accuracy'])

model.fit()

# New second stage: unfreeze and continue training.
for layer in vgg19.layers:
  layer.trainable = True

full_model = Sequential(layers=model.layers)
full_model.compile(
    loss='categorical_crossentropy',
    optimizer=opt,
    metrics=['accuracy'])

full_model.fit()

Вы можете настроить скорость обучения для этапа точной настройки. Начать не обязательно, просто нужно помнить.


Третий вариант - использовать дискриминационные скорости обучения, о которых рассказали Джереми Ховард и Себастьян Рудер в статье ULMFiT, Идея состоит в том, что в Transfer Learning вы обычно хотите, чтобы более поздние слои учились быстрее, чем более ранние, перенесенные слои. Таким образом, вы на самом деле устанавливаете скорость обучения разной для разных наборов слоев. Библиотека fastai имеет реализацию PyTorch , которая работает, разделяя модель на «группы слоев» и предоставляя различные параметры для каждого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...