Keras: точность снижается при начальной настройке - PullRequest
0 голосов
/ 11 сентября 2018

У меня проблемы с настройкой модели Inception с помощью Keras.

Мне удалось использовать учебные пособия и документацию для создания модели полностью подключенных верхних слоев, которая классифицирует мой набор данных по соответствующим категориям с точностью более 99% с использованием функций узкого места в Inception.

import numpy as np
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Dropout, Flatten, Dense
from keras import applications


# dimensions of our images.
img_width, img_height = 150, 150

#paths for saving weights and finding datasets
top_model_weights_path = 'Inception_fc_model_v0.h5'
train_data_dir = '../data/train2'
validation_data_dir = '../data/train2' 

#training related parameters?
inclusive_images = 1424
nb_train_samples = 1424
nb_validation_samples = 1424
epochs = 50
batch_size = 16


def save_bottlebeck_features():
    datagen = ImageDataGenerator(rescale=1. / 255)

    # build bottleneck features
    model = applications.inception_v3.InceptionV3(include_top=False, weights='imagenet', input_shape=(img_width,img_height,3))

    generator = datagen.flow_from_directory(
        train_data_dir,
        target_size=(img_width, img_height),
        batch_size=batch_size,
        class_mode='categorical',
        shuffle=False)

    bottleneck_features_train = model.predict_generator(
        generator, nb_train_samples // batch_size)

    np.save('bottleneck_features_train', bottleneck_features_train)

    generator = datagen.flow_from_directory(
        validation_data_dir,
        target_size=(img_width, img_height),
        batch_size=batch_size,
        class_mode='categorical',
        shuffle=False)

    bottleneck_features_validation = model.predict_generator(
        generator, nb_validation_samples // batch_size)

    np.save('bottleneck_features_validation', bottleneck_features_validation)

def train_top_model():
    train_data = np.load('bottleneck_features_train.npy')
    train_labels = np.array(range(inclusive_images))

    validation_data = np.load('bottleneck_features_validation.npy')
    validation_labels = np.array(range(inclusive_images))

    print('base size ', train_data.shape[1:])

    model = Sequential()
    model.add(Flatten(input_shape=train_data.shape[1:]))
    model.add(Dense(1000, activation='relu'))
    model.add(Dense(inclusive_images, activation='softmax'))
    model.compile(loss='sparse_categorical_crossentropy',
             optimizer='Adam',
             metrics=['accuracy'])

    proceed = True

    #model.load_weights(top_model_weights_path)

    while proceed:
        history = model.fit(train_data, train_labels,
              epochs=epochs,
              batch_size=batch_size)#,
              #validation_data=(validation_data, validation_labels), verbose=1)
        if history.history['acc'][-1] > .99:
            proceed = False

    model.save_weights(top_model_weights_path)


save_bottlebeck_features()
train_top_model()

Epoch 50/50 1424/1424 [====================================] - 17 с 12 мс / шаг -потеря: 0,0398 - в соотв. 0,90909

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

from keras import Model
from keras import optimizers
from keras.callbacks import EarlyStopping

img_width, img_height = 150, 150

top_model_weights_path = 'Inception_fc_model_v0.h5'
train_data_dir = '../data/train2'
validation_data_dir = '../data/train2' 

#how many inclusive examples do we have?
inclusive_images = 1424
nb_train_samples = 1424
nb_validation_samples = 1424
epochs = 50
batch_size = 16

# build the complete network for evaluation
base_model = applications.inception_v3.InceptionV3(weights='imagenet', include_top=False, input_shape=(img_width,img_height,3))

top_model = Sequential()
top_model.add(Flatten(input_shape=base_model.output_shape[1:]))
top_model.add(Dense(1000, activation='relu'))
top_model.add(Dense(inclusive_images, activation='softmax'))

top_model.load_weights(top_model_weights_path)

#combine base and top model
fullModel = Model(input= base_model.input, output= top_model(base_model.output))

#predict with the full training dataset
results = fullModel.predict_generator(ImageDataGenerator(rescale=1. / 255).flow_from_directory(
        train_data_dir,
        target_size=(img_width, img_height),
        batch_size=batch_size,
        class_mode='categorical',
        shuffle=False))

проверка результатов обработки на этой полной модели соответствует точности сгенерированного узкого места полностью подключенной модели.

import matplotlib.pyplot as plt
import operator

#retrieve what the softmax based class assignments would be from results
resultMaxClassIDs = [ max(enumerate(result), key=operator.itemgetter(1))[0] for result in results]

#resultMaxClassIDs should be equal to range(inclusive_images) so we subtract the two and plot the log of the absolute value 
#looking for spikes that indicate the values aren't equal 
plt.plot([np.log(np.abs(x)+10) for x in (np.array(resultMaxClassIDs) - np.array(range(inclusive_images)))])

results: spikes are misclassifications

Вот проблема: Когда я беру эту полную модель и пытаюсь обучить ее, точность падает до 0, даже если проверка остается выше 99%.

model2 = fullModel

for layer in model2.layers[:-2]:
    layer.trainable = False

# compile the model with a SGD/momentum optimizer
# and a very slow learning rate.
#model.compile(loss='binary_crossentropy', optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),  metrics=['accuracy'])

model2.compile(loss='categorical_crossentropy',
             optimizer=optimizers.SGD(lr=1e-4, momentum=0.9), 
             metrics=['accuracy'])

train_datagen = ImageDataGenerator(rescale=1. / 255)

test_datagen = ImageDataGenerator(rescale=1. / 255)

train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_height, img_width),
    batch_size=batch_size,
    class_mode='categorical')

validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_height, img_width),
    batch_size=batch_size,
    class_mode='categorical')

callback = [EarlyStopping(monitor='acc', min_delta=0, patience=3, verbose=0, mode='auto', baseline=None)]
# fine-tune the model
model2.fit_generator(
    #train_generator,
    validation_generator,
    steps_per_epoch=nb_train_samples//batch_size,
    validation_steps = nb_validation_samples//batch_size,
    epochs=epochs,
    validation_data=validation_generator)

Эпоха 1/50 89/89 [=============================] - 388 с 4 с / шаг - потеря: 13,5787 - в соотв. 0,0000e + 00 - val_loss: 0,0353 - val_acc: 0,9937

и ухудшается с развитием событий

Epoch 21/50 89/89 [====================================] - 372s 4s / step - потеря: 7.3850 - acc: 0.0035 - val_loss: 0.5813 - val_acc: 0.8272

Единственное, о чем я могу думать, это то, что ярлыки тренировок каким-то образом неправильно назначаются на этом последнем поезде, но я успешно сделал это с аналогичнымикод с использованием VGG16 ранее.

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

Информация о коде и среде:

Вещи, которые будут выделяться как странные, но должны быть такими:

  • В классе только 1 изображение.Этот NN предназначен для классификации объектов, условия окружающей среды и ориентации которых контролируются.Это только одно приемлемое изображение для каждого класса, соответствующее правильной окружающей среде и ротационной ситуации.
  • Набор для проверки и проверки одинаков.Этот NN предназначен только для тех классов, на которых он обучается.Изображения, которые он будет обрабатывать, будут точными копиями примеров классов.Я намерен приспособить модель к этим классам

Я использую:

  • Windows 10
  • Python 3.5.6 под Anaconda client 1.6.14
  • Keras 2.2.2
  • Tensorflow 1.10.0 в качестве бэкэнда
  • CUDA 9.0
  • CuDNN 8.0

Iпроверили:

  1. Несоответствие точности Keras в отлаженной модели
  2. VGG16 Точная настройка Keras: низкая точность
  3. Керас: точность модели падает после достижения 99% точности и потерь 0,01
  4. Ошибка при переподготовке и начальной настройке Keras v3
  5. Какузнать, какая версия TensorFlow установлена ​​в моей системе?

но они кажутся несвязанными.

Ответы [ 2 ]

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

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

Есть пара вещей, которые привлекли мое внимание (и, возможно, заслуживают рассмотрения). Примечание: некоторые из них должны были вызвать проблемы с отдельными моделями.

  • Поправьте, если я ошибаюсь, но, кажется, вы использовали sparse_categorical_crossentropy для первой тренировки, а categorical_crossentropy для второй. Это правильно? Потому что я полагаю, что они принимают метки по-разному (разреженный предполагает целые числа, а другой предполагает однозначный).
  • Вы пытались установить слои, которые вы добавили в конце, как trainable = True? Я знаю, что вы уже установили для других значение trainable = False, но, возможно, это тоже стоит проверить.
  • Похоже, что генератор данных не использует функцию предварительной обработки по умолчанию, используемую в Inception v3, которая использует канал среднего значения.
  • Вы пробовали какой-нибудь эксперимент с использованием Functional вместо Sequential API?

Надеюсь, это поможет.

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

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

Поскольку inception_V3 содержит BatchNormalization слоев, возможно, проблема связана с (каким-то неоднозначным или неожиданным) поведением этого слоякогда для параметра trainable установлено значение False ( 1 , 2 , 3 , 4 ).

Теперь давайте посмотрим, является ли это корнем проблемы: как предложено @ fchollet , установите этап обучения при определении модели для тонкой настройки:

from keras import backend as K

K.set_learning_phase(0)

base_model = applications.inception_v3.InceptionV3(weights='imagenet', include_top=False, input_shape=(img_width,img_height,3))

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

K.set_learning_phase(1)

top_model = Sequential()
top_model.add(Flatten(input_shape=base_model.output_shape[1:]))
top_model.add(Dense(1000, activation='relu'))
top_model.add(Dense(inclusive_images, activation='softmax'))

top_model.load_weights(top_model_weights_path)

#combine base and top model
fullModel = Model(input= base_model.input, output= top_model(base_model.output))

fullModel.compile(loss='categorical_crossentropy',
             optimizer=optimizers.SGD(lr=1e-4, momentum=0.9), 
             metrics=['accuracy'])


#####################################################################
# Here, define the generators and then fit the model same as before #
#####################################################################

Примечание: Это не вызывает никаких проблем в вашем случае, но имейте в виду, что при использовании top_model(base_model.output) вся Последовательная модель (т.е. top_model) сохраняется как один слой fullModel,Вы можете проверить это, используя fullModel.summary() или print(fullModel.layers[-1]).Следовательно, когда вы используете:

for layer in model2.layers[:-2]:
    layer.trainable = False 

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

...