Массивный переодевания во время обучения передачи resnet50 - PullRequest
0 голосов
/ 16 мая 2018

Это моя первая попытка сделать что-то с CNN, поэтому я, вероятно, делаю что-то очень глупое - но не могу понять, в чем я не прав ...

Модель, кажется, учится хорошо,но точность проверки не улучшается (никогда - даже после первой эпохи), и потеря проверки со временем фактически увеличивается.Это не похоже на то, что я перегружаюсь (после 1 эпохи?) - мы должны отключиться каким-то другим способом.

типичное поведение сети

Я тренирую CNNсеть - у меня есть ~ 100 тыс. изображений различных растений (1000 классов), и я хочу настроить ResNet50 для создания классификатора муликласса.Изображения имеют разные размеры, я загружаю их так:

from keras.preprocessing import image                  

def path_to_tensor(img_path):
    # loads RGB image as PIL.Image.Image type
    img = image.load_img(img_path, target_size=(IMG_HEIGHT, IMG_HEIGHT))
    # convert PIL.Image.Image type to 3D tensor with shape (IMG_HEIGHT, IMG_HEIGHT, 3)
    x = image.img_to_array(img)
    # convert 3D tensor to 4D tensor with shape (1, IMG_HEIGHT, IMG_HEIGHT, 3) and return 4D tensor
    return np.expand_dims(x, axis=0)

def paths_to_tensor(img_paths):
    list_of_tensors = [path_to_tensor(img_path) for img_path in img_paths] #can use tqdm(img_paths) for data
    return np.vstack(list_of_tensors)enter code here

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

В приведенной ниже версии генератора пока не делается никаких дополнений - просто масштабируется:

def generate_batches_from_train_folder(images_to_read, labels, batchsize = BATCH_SIZE):    

    #Generator that returns batches of images ('xs') and labels ('ys') from the train folder
    #:param string filepath: Full filepath of files to read - this needs to be a list of image files
    #:param np.array: list of all labels for the images_to_read - those need to be one-hot-encoded
    #:param int batchsize: Size of the batches that should be generated.
    #:return: (ndarray, ndarray) (xs, ys): Yields a tuple which contains a full batch of images and labels. 

    dimensions = (BATCH_SIZE, IMG_HEIGHT, IMG_HEIGHT, 3)

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

    # needs to be on a infinite loop for the generator to work
    while 1:
        filesize = len(images_to_read)

        # count how many entries we have read
        n_entries = 0
        # as long as we haven't read all entries from the file: keep reading
        while n_entries < (filesize - batchsize):

            # start the next batch at index 0
            # create numpy arrays of input data (features) 
            # - this is already shaped as a tensor (output of the support function paths_to_tensor)
            xs = paths_to_tensor(images_to_read[n_entries : n_entries + batchsize])

            # and label info. Contains 1000 labels in my case for each possible plant species
            ys = labels[n_entries : n_entries + batchsize]

            # we have read one more batch from this file
            n_entries += batchsize

            #perform online augmentation on the xs and ys
            augmented_generator = train_datagen.flow(xs, ys, batch_size = batchsize)

        yield  next(augmented_generator)

Вот как я определяю свою модель:

def get_model():

    # define the model
    base_net = ResNet50(input_shape=DIMENSIONS, weights='imagenet', include_top=False)

    # Freeze the layers which you don't want to train. Here I am freezing all of them
    for layer in base_net.layers:
        layer.trainable = False

    x = base_net.output

    #for resnet50
    x = Flatten()(x)
    x = Dense(512, activation="relu")(x)
    x = Dropout(0.5)(x)
    x = Dense(1000, activation='softmax', name='predictions')(x)

    model = Model(inputs=base_net.input, outputs=x)

    # compile the model 
    model.compile(
        loss='categorical_crossentropy',
        optimizer=optimizers.Adam(1e-3),
        metrics=['acc'])

    return model

Итак, в результате у меня есть 1 562 088 обучаемых параметров для примерно 70 тыс. Изображений

Затем я использую5-кратная перекрестная проверка, но модель не работает ни в одном из сгибов, поэтому я не буду включать здесь полный код, уместно следующее:

trial_fold = temp_model.fit_generator(
                train_generator,
                steps_per_epoch = len(X_train_path) // BATCH_SIZE,
                epochs = 50,
                verbose = 1,
                validation_data = (xs_v,ys_v),#valid_generator,
                #validation_steps= len(X_valid_path) // BATCH_SIZE,
                callbacks = callbacks,
                shuffle=True)

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

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

Обновление 1:

Я решил прекратить переизобретать материал и сортировать по файлам для работы с .flow_from_directory () процедура.Чтобы убедиться, что я импортирую правильный формат (вызванный комментарием Ioannis Nasios ниже) - я позаботился о preprocessing_unit () из приложения keras resnet50.

Я также решил проверить, действительно ли модель производитчто-то полезное - я вычислил возможности Botleneck для своего набора данных, а затем использовал случайный лес для прогнозирования классов.Это сработало, и я получил точность около 0,4

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

Обновление 2:

Iдумаю, что проблема была с предварительной обработкой изображения.В итоге я не смог выполнить точную настройку, а просто извлек слой «ботлнек» и обучил linear_SVC () - получил точность около 60% поезда и около 45% наборов тестовых данных.

Ответы [ 5 ]

0 голосов
/ 23 октября 2018

Есть ли у вас решение вашей проблемы? Если нет, то это может быть проблема с уровнем пакетной нормы в вашей сети. Я также сталкивался с подобной проблемой, так как в пакетном слое keras поведение во время тренировок и тестов сильно отличалось. Таким образом, вы можете заморозить все слои bn:

BatchNorm()(training=False)

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

import keras.backend as K K.set_learning_phase(1)

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

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

Спасибо.

0 голосов
/ 04 июля 2018

Вам необходимо использовать аргумент preprocessing_function в ImageDataGenerator.

 train_datagen = ImageDataGenerator(preprocessing_function=keras.applications.resnet50.preprocess_input)

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

0 голосов
/ 19 мая 2018

Вот некоторые пояснения, касающиеся тонкой настройки и передачи обучения в соответствии со Стэнфордским университетом.

  1. Очень разные наборы данных и очень маленький набор данных из набора данных image-net - Попробуйте линейный классификатор из разных этапов

Итак, подведем итог.

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

0 голосов
/ 31 мая 2018

Я также работаю над очень маленьким набором данных и столкнулся с той же проблемой точности проверки, которая застряла в какой-то момент, хотя точность обучения продолжает расти. Я также заметил, что с течением времени моя потеря при проверке возрастала. К вашему сведению, я использую модели Resnet 50 и InceptionV3.

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

Github ссылка на запрос и обсуждение по запросу

0 голосов
/ 16 мая 2018

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...