Передача обучения с плохой точностью

У меня есть задача классифицировать семена в зависимости от дефекта. У меня есть около 14k изображений в 7 классах (они не одинакового размера, в некоторых классах больше фотографий, в некоторых меньше). Я пытался тренировать Inception V3 с нуля, и у меня точность около 90%. Затем я попытался перенести обучение, используя предварительно обученную модель с весами ImageNet. Я импортировал inception_v3 от applications без верхних слоев fc, затем добавил свой собственный, как в документации. Я закончил со следующим кодом:

# Setting dimensions
img_width = 454
img_height = 227

###########################
# PART 1 - Creating Model #
###########################

# Creating InceptionV3 model without Fully-Connected layers
base_model = InceptionV3(weights='imagenet', include_top=False, input_shape = (img_height, img_width, 3))

# Adding layers which will be fine-tunned
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
predictions = Dense(7, activation='softmax')(x)

# Creating final model
model = Model(inputs=base_model.input, outputs=predictions)

# Plotting model
plot_model(model, to_file='inceptionV3.png')

# Freezing Convolutional layers
for layer in base_model.layers:
    layer.trainable = False

# Summarizing layers
print(model.summary())

# Compiling the CNN
model.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])

##############################################
# PART 2 - Images Preproccessing and Fitting #
##############################################

# Fitting the CNN to the images

train_datagen = ImageDataGenerator(rescale = 1./255,
                                   rotation_range=30,
                                   width_shift_range=0.2,
                                   height_shift_range=0.2,
                                   shear_range = 0.2,
                                   zoom_range = 0.2,
                                   horizontal_flip = True,
                                   preprocessing_function=preprocess_input,)

valid_datagen = ImageDataGenerator(rescale = 1./255,
                                   preprocessing_function=preprocess_input,)

train_generator = train_datagen.flow_from_directory("dataset/training_set",
                                                    target_size=(img_height, img_width),
                                                    batch_size = 4,
                                                    class_mode = "categorical",
                                                    shuffle = True,
                                                    seed = 42)

valid_generator = valid_datagen.flow_from_directory("dataset/validation_set",
                                                    target_size=(img_height, img_width),
                                                    batch_size = 4,
                                                    class_mode = "categorical",
                                                    shuffle = True,
                                                    seed = 42)

STEP_SIZE_TRAIN = train_generator.n//train_generator.batch_size
STEP_SIZE_VALID = valid_generator.n//valid_generator.batch_size

# Save the model according to the conditions  
checkpoint = ModelCheckpoint("inception_v3_1.h5", monitor='val_acc', verbose=1, save_best_only=True, save_weights_only=False, mode='auto', period=1)
early = EarlyStopping(monitor='val_acc', min_delta=0, patience=10, verbose=1, mode='auto')

#Training the model
history = model.fit_generator(generator=train_generator,
                         steps_per_epoch=STEP_SIZE_TRAIN,
                         validation_data=valid_generator,
                         validation_steps=STEP_SIZE_VALID,
                         epochs=25,
                         callbacks = [checkpoint, early])

Но у меня ужасные результаты: точность 45%. Я думал, что это должно быть лучше. У меня есть гипотеза, что может пойти не так:

  • Я тренировался с нуля на масштабированных изображениях (299x299) и на немасштабированных изображениях во время трансферного обучения (227x454), и что-то не получилось (или, может быть, я потерял порядок измерений).
  • Во время трансферного обучения я использовал preprocessing_function=preprocess_input (нашел статью в сети, что это чрезвычайно важно, поэтому я решил добавить это).
  • добавленной rotation_range=30, width_shift_range=0.2, height_shift_range=0.2, а также horizontal_flip = True в то время как передача обучения, чтобы увеличить данные еще больше.
  • Может быть, оптимизатор Adam - плохая идея? Должен ли я попробовать RMSprop например?
  • Должен ли я точно настроить некоторые конвекционные слои с SGD с небольшой скоростью обучения?

Или я провалил что-то еще?

РЕДАКТИРОВАТЬ: я публикую сюжет истории обучения. Может быть, он содержит ценную информацию:

История учебного сюжета

EDIT2: с изменением параметров InceptionV3:

InceptionV3 с измененными параметрами

VGG16 для сравнения:

VGG16 для сравнения

2 ответа

Решение

@ Сегодня я нашел проблему. Это происходит из-за некоторых изменений в слоях нормализации партии и их поведении при замораживании. Мистер Чоллет предложил обходной путь, но я использовал вилку Keras, сделанную datumbox, которая решила мою проблему. Основная проблема описана здесь:

https://github.com/keras-team/keras/pull/9965

Теперь я получаю точность ~85% и пытаюсь повысить ее.

Если вы хотите предварительно обработать ввод, используя preprocess_input метод из Keras, затем удалите rescale=1./255 аргумент. В противном случае сохраните rescale аргумент и удалить preprocessing_function аргумент. Кроме того, попробуйте более низкую скорость обучения, такую ​​как 1e-4 или 3e-5 или 1e-5 (по умолчанию скорость обучения оптимизатора Adam составляет 1e-3), если потери не уменьшаются:

from keras.optimizers import Adam

model.compile(optimizer = Adam(lr=learning_rate), ...)

Изменить: После добавления тренировочного графика, вы можете видеть, что это перегрузка на тренировочном наборе. Вы можете:

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