vgg16 тонкая настройка собак кошек не проходит тестирование данных - PullRequest
0 голосов
/ 17 сентября 2018

Таким образом, я пытался настроить VGG16, чтобы классифицировать созданный мной набор данных, который имеет 4 класса, но хотя точность как в обучающих, так и в проверочных наборах хорошо увеличилась, тестирование всегда приводило к точности 25%, независимо от того,что я сделал.Я решил начать с тонкой настройки VGG16 с набора данных о кошках и собаках из Kaggle, и я следовал различным урокам, которые давали хорошие результаты точности.Тем не менее, это та же проблема, с которой я столкнулся в первый раз.Теперь точность составляет 50% (так как это 2 класса).Я начинаю думать, что это проблема Keras VGG16.Я перепробовал различные предложения онлайн, в том числе похожие в похожих вопросах в stackoverflow, но, похоже, ничего не работает.Кажется, что вся предварительная обработка, добавление и замораживание слоев выполняются надлежащим образом, и после нескольких недель пробных ошибок я вынужден обратиться к вашим предложениям / советам по этому вопросу.

Это весь код, который я использую:

from keras.models import Sequential, Model, load_model
from keras import applications
from keras import optimizers
from keras.layers import Dropout, Flatten, Dense
from keras.preprocessing.image import ImageDataGenerator
from sklearn.metrics import  classification_report,confusion_matrix
from keras.callbacks import ModelCheckpoint

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np

Далее я использую реализацию функции матрицы смешения.

def plot_confusion_matrix_two(cm,
                          target_names,
                          title='Confusion matrix',
                          cmap=None,
                          normalize=True):

import matplotlib.pyplot as plt
import numpy as np
import itertools

accuracy = np.trace(cm) / float(np.sum(cm))
misclass = 1 - accuracy

if cmap is None:
    cmap = plt.get_cmap('Blues')

plt.figure(figsize=(8, 6))
plt.imshow(cm, interpolation='nearest', cmap=cmap)
plt.title(title)
plt.colorbar()

if target_names is not None:
    tick_marks = np.arange(len(target_names))
    plt.xticks(tick_marks, target_names, rotation=45)
    plt.yticks(tick_marks, target_names)

if normalize:
    cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]


thresh = cm.max() / 1.5 if normalize else cm.max() / 2
for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
    if normalize:
        plt.text(j, i, "{:0.4f}".format(cm[i, j]),
                 horizontalalignment="center",
                 color="white" if cm[i, j] > thresh else "black")
    else:
        plt.text(j, i, "{:,}".format(cm[i, j]),
                 horizontalalignment="center",
                 color="white" if cm[i, j] > thresh else "black")


plt.tight_layout()
plt.ylabel('True label')
plt.xlabel('Predicted label\naccuracy={:0.4f}; misclass={:0.4f}'.format(accuracy, misclass))
plt.show()

Вызов VGG16 с весами imagenet и без верхнего слоя + заморозить нижние слои

img_rows, img_cols, img_channel = 224, 224, 3
base_model = applications.VGG16(weights='imagenet', include_top=False, input_shape=(img_rows, img_cols, img_channel))

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

# check the trainable status of the individual layers

for layer in base_model.layers:
    print(layer, layer.trainable)

Добавление последних слоев для классификации наших данных и компиляции модели:

add_model = Sequential()
add_model.add(Flatten(input_shape=base_model.output_shape[1:]))
add_model.add(Dense(256, activation='relu'))
add_model.add(Dropout(0.5))
add_model.add(Dense(2, activation='softmax'))
for layer in add_model.layers[:-3]:
    layer.trainable = False



model = Model(inputs=base_model.input, outputs=add_model(base_model.output))
model.compile(loss='categorical_crossentropy', optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
              metrics=['accuracy'])

model.summary()

Параметры обучения, пути и т.д ...

image_size = 224

epochs = 500

train_batch = 50
valid_batch = 30
test_batch = 20

train_dir = 'D:/PetImages/train'
valid_dir = 'D:/PetImages/valid'
test_dir = 'D:/PetImages/test'

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

train_datagen = ImageDataGenerator(
      rescale=1./255,
      rotation_range=20,
      width_shift_range=0.2,
      height_shift_range=0.2,
      horizontal_flip=True,
      #vertical_flip=True,
      fill_mode='nearest')

validation_datagen = ImageDataGenerator(rescale=1./255)

test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        train_dir,
        target_size=(image_size, image_size),
        batch_size=train_batch,
        class_mode='categorical',
        shuffle=True)

validation_generator = validation_datagen.flow_from_directory(
        valid_dir,
        target_size=(image_size, image_size),
        batch_size=valid_batch,
        class_mode='categorical',
        shuffle=True)

test_generator = test_datagen.flow_from_directory(
        test_dir,
        target_size=(image_size, image_size),
        batch_size=test_batch,
        class_mode='categorical',
        shuffle=True)

Обучение модели:

history = model.fit_generator(
    train_generator,
    steps_per_epoch=train_generator.samples // train_generator.batch_size,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=validation_generator.samples // validation_generator.batch_size,
    #callbacks=[ModelCheckpoint('VGG16-transferlearning.model', monitor='val_acc', save_best_only=True)]
    verbose=1
)

А затем прогнозирование на тестовом наборе для сравнения справдивость и точность и т. д .:

predictions = model.predict_generator(test_generator, steps=test_generator.samples//test_generator.batch_size, 
                                      verbose=0)

#Confution Matrix and Classification Report
predictions = np.argmax(predictions, axis=1)

print('Confusion Matrix')
cm = confusion_matrix(test_generator.classes, predictions)
#print(cm)

target_names =['cats', 'dogs']
#target_names =['Bark', 'Jump','Stand', 'Walk']
plot_confusion_matrix_two(cm, target_names, title='Confusion Matrix',cmap=None,normalize=False)

print('Classification Report')
print(classification_report(test_generator.classes, predictions, target_names=target_names))

print('Confusion Matrix')
print(cm)

Я действительно перепробовал все разные трюки, чтобы проверить.Я даже пытался проверить, как модель работает на самих тренировочных данных, а не на тестовых, и все равно дает 50% (что очень странно, учитывая, что точность обучения достигает почти 99%).Я пытался настроить гиперпараметры, разные алгоритмы, но ничего не изменилось.

Система: Windows 10, Anaconda, Keras 2.1.1 Tensorflow-gpu 1.4.0 Python 3.6.4

Используемый набор данных: https://files.fm/u/t6zdskc7

Я застрял уже несколько недель, и это действительно расстраивает.Если кто-нибудь может мне помочь, я буду вечно благодарен !!

Редактировать:

Так что, спросив вокруг, мне сказали, что модель на самом деле учится иЯ могу проверить точность прогноза, используя следующий фрагмент кода:

x, y = zip(*(test_generator[i] for i in range(len(test_generator))))
x_test, y_test = np.vstack(x), np.vstack(y)
loss, acc = model.evaluate(x_test, y_test, batch_size=64)

print("Accuracy: ", acc)
print("Loss: ",loss)

Оказывается, я получаю реальное значение, которое имеет смысл (около 70% в зависимости от настройки гиперпараметров).Так что теперь я предполагаю, что что-то идет не так, когда я пытаюсь проанализировать, используя confusion_matrix и функции отчета.Я все еще не могу найти проблему, хотя.

Ответы [ 2 ]

0 голосов
/ 19 сентября 2018

модель = Модель (входы = base_model.input, выходы = add_model (base_model.output)) Не удалось правильно добавить новые слои.Просто используйте функциональный API.

out = base_model.output
out = Flatten()(out)
out = Dense(256, activation='relu')(out)
out = Dropout(0.5)(out)
out = Dense(2, activation='softmax')(out)
for layer in add_model.layers[:-3]:
    layer.trainable = False
model = Model(inputs=base_model.input, outputs=out)
0 голосов
/ 17 сентября 2018

для классификации созданного мной набора данных, который имеет 4 класса

Для начала, ваша конфигурация сети кажется странной (если не сказать больше) для задачи классификации с 4 классами; Первые предложения:

  1. Измените на loss='categorical_crossentropy' в компиляции вашей модели

  2. Измените свой последний слой на

add_model.add(Dense(4, activation='softmax'))

так как из-за вашей строки predictions = np.argmax(predictions, axis=1) я предполагаю, что вы уже используете метки с горячим кодированием ...

...