Transfer Learning - Val_loss странное поведение

Я пытаюсь использовать обучение переносу на MobileNetV2 из keras.application в фитоне. Мои изображения принадлежат 4 классам с количеством 8000, 7000, 8000 и 8000 изображений в первом, втором, третьем и последнем классе. Мои изображения серого цвета и имеют размеры от 1024x1024 до 128x128.

Я удалил плотные слои классификации из MobileNetV2 и добавил свои собственные плотные слои:

global_average_pooling2d_1 (Glo Shape = (None, 1280)         0 Parameters                            
______________________________________________________________________________
dense_1 (Dense)                 Shape=(None, 4)            5124 Parameters      
______________________________________________________________________________
dropout_1 (Dropout)             Shape=(None, 4)            0  Parameters                        
________________________________________________________________
dense_2 (Dense)                 Shape=(None, 4)            20 Parameters                         
__________________________________________________________________________
dense_3 (Dense)                 Shape=(None, 4)            20 Parameters                        

Total params: 2,263,148

Trainable params: 5,164

Non-trainable params: 2,257,984

Как видите, я добавил 2 плотных слоя с выпадением в качестве регуляризатора. Furhtermore, я использовал следующее

opt = optimizers.SGD(lr=0.001, decay=4e-5, momentum=0.9)

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

batch_size = 32

Мои результаты на тренировках очень странные...:

эпоха

1 потеря: 1,3378 - в соответствии с 0,3028; потеря в валу: 1,4629; потеря в валу: 0,2702

2 потери: 1,2807 - в соответствии с: 0,3351 - потери по величине: 1,3297 - значения по шкале: 0,3208

3 потери: 1,2641 - в соответствии с: 0,3486 - потери по величине: 1,4428 - значения по шкале: 0,3707

4 потери: 1,2178 - в соотв. 0,3916 - потери в долях: 1,4231 - валы: 0,3758

5 потерь: 1,2100 - в соответствии с: 0,3909 - потери по величине: 1,4009 - значения по величине: 0,3625

6 потерь: 1,1979 - в соответствии: 0,3976 - потери по стоимости: 1,5025 - значения по счету: 0,3116

7 проигрыша: 1,1943 - согласно: 0,3988 - val_loss: 1,4510 - val_acc: 0,2872

8 потери: 1,1926 - в соответствии с: 0,3965 - потери по стоимости: 1,5162 - значения по счету: 0,3072

9 потерь: 1,1888 - в соответствии с 0,4004 - потери по величине: 1,5659 - значения по счету: 0,3304

10 потерь: 1,1906 - в соответствии с: 0,3969 - потеря по величине: 1,5655 - допустимая ошибка: 0,3260

11 потерь: 1,1864 - в соответствии с: 0,3999 - потери по величине: 1,6286 - значения по счету: 0,2967

(...)

Подводя итог, потеря тренировок больше не уменьшается и все еще очень высока. Модель также подходит. Вы можете спросить, почему я добавил только 2 плотных слоя с 4 нейронами в каждом. В начале я пробовал разные конфигурации (например, 128 нейронов и 64 нейрона, а также разные регуляторы), затем переоснащение было огромной проблемой, то есть точность обучения была почти 1, а потери на тесте были еще далеки от 0.

Я немного запутался в происходящем, потому что здесь что-то невероятно не так.

Попытки тонкой настройки: различное количество нейронов в плотных слоях в части классификации, варьирующееся от 1024 до 4. Различные скорости обучения (0, 01, 0, 001, 0, 0001) Различные размеры партий (16,32, 64) Различные регуляторы L1 с 0, 001, 0, 0001

Результаты: всегда огромное переоснащение

base_model = MobileNetV2(input_shape=(128, 128, 3), weights='imagenet', include_top=False)

# define classificator
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(4, activation='relu')(x)
x = Dropout(0.8)(x)
x = Dense(4, activation='relu')(x)
preds = Dense(4, activation='softmax')(x) #final layer with softmax activation

model = Model(inputs=base_model.input, outputs=preds)

for layer in model.layers[:-4]:
    layer.trainable = False

opt = optimizers.SGD(lr=0.001, decay=4e-5, momentum=0.9)
model.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])

batch_size = 32
EPOCHS = int(trainY.size/batch_size)

H = model.fit(trainX, trainY, validation_data=(testX, testY), epochs=EPOCHS, batch_size=batch_size)

Результатом должно быть то, что нет переобучения и val_loss близко к 0. Я знаю, что из какой-то статьи, работающей над подобными наборами изображений.

ОБНОВЛЕНИЕ: Вот некоторые изображения val_loss, train_loss и точности: 2 плотных слоя с 16 и 8 нейронами, lr = 0, 001 с распадом 1e-6, размер пакета = 25

2 ответа

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

loss='sparse_categorical_crossentropy'

Здесь вы использовалиx = Dropout(0.8)(x)что означает падение на 80%, но я предполагаю, что вам нужно 20%, поэтому замените его на x = Dropout(0.2)(x)

Кроме того, при необходимости обратитесь к документации по этому продукту.

выписка из вышеуказанной документации

keras.layers.Dropout(rate, noise_shape=None, seed=None)

скорость: плавать между 0 и 1. Доля входных единиц, чтобы упасть.

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

Похоже, что MobileNetV2 изучает функции, которые нежелательны для моего набора данных. Мои наборы данных представляют собой радиолокационные изображения, которые выглядят очень искусственно (распределение сигналов LPI). С другой стороны, эти изображения очень просты (в основном они представляют собой просто грани в изображении в оттенках серого), поэтому мне до сих пор неизвестно, почему обучение переносу на основе моделей не работает для MobileNetV2).