Точность валидации и тестирования при произвольной производительности, в то время как точность поезда очень высокая - PullRequest
0 голосов
/ 03 мая 2020

Я пытаюсь создать классификатор в TensorFlow2.1 для CIFAR10 , используя ResNet50 , предварительно обученный на imag enet из керас. приложение , а затем наложив поверх него небольшой FNN:

# Load ResNet50 pre-trained on imagenet
resn = applications.resnet50.ResNet50(weights='imagenet', input_shape=(IMG_SIZE, IMG_SIZE, 3), pooling='avg', include_top=False)

# Load CIFAR10 
(c10_train, c10_test), info = tfds.load(name='cifar10', split=['train', 'test'], with_info=True, as_supervised=True)

# Make sure all the layers are not trainable
for layer in resn.layers:
    layer.trainable = False

# Transfert Learning for CIFAR10: fine-tune the network by stacking a trainable FNN on top of Resnet
from tensorflow.keras import models, layers

def build_model():
  model = models.Sequential()
  # Feature extractor
  model.add(resn)
  # Small FNN
  model.add(layers.Dense(256, activation='relu'))
  model.add(layers.Dropout(0.4))
  model.add(layers.Dense(10, activation='softmax'))

  model.compile(loss='categorical_crossentropy',
                optimizer=tf.keras.optimizers.SGD(learning_rate=0.1),
                metrics=['accuracy'])

  return model

# Build the resulting net
resn50_c10 = build_model()

При проверке или проверке точности я сталкиваюсь со следующей проблемой:

history = resn50_c10.fit_generator(c10_train.shuffle(1000).batch(BATCH_SIZE), validation_data=c10_test.batch(BATCH_SIZE), epochs=20)

Epoch 1/20
25/25 [==============================] - 113s 5s/step - loss: 0.9659 - accuracy: 0.6634 - val_loss: 2.8157 - val_accuracy: 0.1000
Epoch 2/20
25/25 [==============================] - 109s 4s/step - loss: 0.8908 - accuracy: 0.6920 - val_loss: 2.8165 - val_accuracy: 0.1094
Epoch 3/20
25/25 [==============================] - 116s 5s/step - loss: 0.8743 - accuracy: 0.7038 - val_loss: 2.7555 - val_accuracy: 0.1016
Epoch 4/20
25/25 [==============================] - 132s 5s/step - loss: 0.8319 - accuracy: 0.7166 - val_loss: 2.8398 - val_accuracy: 0.1013
Epoch 5/20
25/25 [==============================] - 132s 5s/step - loss: 0.7903 - accuracy: 0.7253 - val_loss: 2.8624 - val_accuracy: 0.1000
Epoch 6/20
25/25 [==============================] - 132s 5s/step - loss: 0.7697 - accuracy: 0.7325 - val_loss: 2.8409 - val_accuracy: 0.1000
Epoch 7/20
25/25 [==============================] - 132s 5s/step - loss: 0.7515 - accuracy: 0.7406 - val_loss: 2.7697 - val_accuracy: 0.1000   
#... (same for the remaining epochs) 

Хотя модель, по-видимому, адекватно учится на тренировочном расколе, и точность, и потери для набора проверки вообще не улучшаются. Что вызывает такое поведение?

Я исключаю это переоснащение, так как я применяю Dropout и модель, кажется, никогда не улучшится в тестовом наборе.

Что я сделал до сих пор:

  • Проверьте маркировку одним щелчком согласован на протяжении всего обучения и тестирования
  • Пробовал разные конфигурации FNN
  • Пробовал метод fit_generator вместо fit
  • Предварительная обработка изображения, изменение размера изображения с различными input_shapes

и испытывал всегда одну и ту же проблему.

Любой намек был бы чрезвычайно признателен.

Ответы [ 2 ]

0 голосов
/ 05 мая 2020

Очевидно, что проблема была вызвана уникальным использованием ResNet50.

. В качестве обходного пути я скачал и использовал другие предварительно обученные глубокие сети, такие как keras.applications.vgg16.VGG16, keras.applications.densenet.DenseNet121 и точность на набор тестов увеличился, как и ожидалось.

ОБНОВЛЕНИЕ

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

Причина root может быть найдена в том, как Keras обрабатывает слой Batch Normalization:

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

Как объяснено более подробно здесь: https://github.com/keras-team/keras/pull/9965

Хотя правильный подход был реализован в TensorFlow 2 , когда мы используем tf.keras.applications, мы ссылаемся на поведение TensorFlow 1.0 для пакетной нормализации. Вот почему нам нужно явно вставить ссылку на TensorFlow 2 , добавив аргумент layers=tf.keras.layers при загрузке модулей. Так что в моем случае загрузка ResNet50 станет

history = resn50_c10.fit_generator(c10_train.shuffle(1000).batch(BATCH_SIZE), validation_data=c10_test.batch(BATCH_SIZE), epochs=20, layers=tf.keras.layers)

, и это поможет.

Кредиты для решения @rpeloff: https://github.com/keras-team/keras/pull/9965#issuecomment -549126009

0 голосов
/ 03 мая 2020

Вероятно, проблема связана с загрузкой данных с использованием tfds и последующей передачей в Keras .fit

Попробуйте загрузить данные с помощью

from keras.datasets import cifar10

(x_train, y_train), (x_test, y_test) = cifar10.load_data()

И затем

fit(x=x_train, y=y_train, batch_size=BATCH_SIZE, epochs=20, verbose=1, callbacks=None, validation_split=0.2, validation_data=None, shuffle=True)
...