Загружайте изображения и аннотации из CSV и используйте fit_generator с моделями с несколькими выходами - PullRequest
0 голосов
/ 14 мая 2018

После выпуска # 10120 я использую функциональный API Keras для построения модели с несколькими (пятью) выходами и одним и тем же входом, чтобы одновременно предсказать различные свойства данных (изображения в моем дело). Все метаданные набора данных хранятся в разных файлах CSV (один для обучения, один для проверки и один для данных испытаний).

aaa.png

Я уже написал код для разбора CSV и сохранения всех разных аннотаций в разные массивы (x_train.npy, emotions.npy и т. Д.), Которые позже загружаю, чтобы обучить свой CNN.


Вопросы, которые я хочу поднять, следующие:

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

Лучше ли читать аннотации на лету из файла CSV, а не сохранять их в numpy (или любом другом формате)?

Когда я загружаю сохраненные массивы NumPy (следующий пример содержит только изображения и отдельные метаданные)

 (x_train, y_train),(x_val, y_val)

тогда я делаю

train_generator = datagen.flow(x_train, y_train, batch_size=32)

и, наконец,

history = model.fit_generator(train_generator,
                        epochs=nb_of_epochs,
                        steps_per_epoch= steps_per_epoch,
                        validation_data=val_generator,
                        validation_steps=validation_steps,
                        callbacks=callbacks_list)

Кажется, моя программа потребляет до 20-25 ГБ ОЗУ на все время тренировочного процесса (что делается на GPU). Если я добавляю более одного вывода, моя программа падает из-за этой утечки памяти (максимальный объем ОЗУ у меня составляет 32 ГБ).

Каким будет правильный подход для загрузки проанализированных аннотаций вместе с необработанными изображениями?

Допустим, вышеуказанная проблема исправлена, что будет правильным подходом для использования ImageDataGenerator для нескольких выходов , как показано ниже (также обсуждается здесь)

Keras: как использовать fit_generator с несколькими выходами разного типа

Xi[0], [Yi1[1], Yi2[1],Yi3[1], Yi4[1],Yi5[1]]

Ответы [ 3 ]

0 голосов
/ 18 мая 2018
def multi_output_generator(hdf5_file, nb_data, batch_size):
    """ Generates batches of tensor image data in form of ==> x, [y1, y2, y3, y4, y5] for use in a multi-output Keras model.

        # Arguments
            hdf5_file: the hdf5 file which contains the images and the annotations.
            nb_data: total number of samples saved in the array.
            batch_size: size of the batch to generate tensor image data for.

        # Returns
            A five-output generator.
    """

    batches_list = list(range(int(ceil(float(nb_data) / batch_size))))

    while True:

        # loop over batches
        for n, i in enumerate(batches_list):
            i_s = i * batch_size  # index of the first image in this batch
            i_e = min([(i + 1) * batch_size, nb_data])  # index of the last image in this batch

            x = hdf5_file["x_train"][i_s:i_e, ...]

            # read labels
            y1 = hdf5_file["y1"][i_s:i_e]
            y2 = hdf5_file["y2"][i_s:i_e]
            y3 = hdf5_file["y3"][i_s:i_e]
            y4 = hdf5_file["y4"][i_s:i_e]
            y5 = hdf5_file["y5"][i_s:i_e]

        yield x, [y1, y2, y3, y4 ,y5]
0 голосов
/ 23 сентября 2018

Столкнулся с той же проблемой, сначала мне удалось написать один генератор, такой как https://gist.github.com/timehaven/257eef5b0e2d9e2625a9eb812ca2226b,, но он не может с легкостью использовать многопроцессорность, и позже я обнаружил, что существует объект keras.utils.Sequence() (я пропустил его, потому что Я думал, что это была Sequential модель) в Керасе, которая предназначена только для этой цели, Google или посмотреть https://github.com/sdcubber/Keras-Sequence-boilerplate/blob/master/Keras-Sequence.ipynb для одного рабочего демо.

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

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

Вот пользовательский генератор, который я написал (необходимо заполнить необходимые части):

import numpy as np
from keras.preprocessing import image

def generator(csv_path, batch_size, img_height, img_width, channels, augment=False):

    ########################################################################
    # The code for parsing the CSV (or loading the data files) should goes here
    # We assume there should be two arrays after this:
    #   img_path --> contains the path of images
    #   annotations ---> contains the parsed annotaions
    ########################################################################

    n_samples = len(img_path)
    batch_img = np.zeros((batch_size, img_width, img_height, channels))
    idx = 0
    while True:
        batch_img_path = img_path[idx:idx+batch_size]
        for i, p in zip(range(batch_size), batch_img_path):
            img = image.load_img(p, target_size=(img_height, img_width))
            img = image.img_to_array(img)
            batch_img[i] = img

        if augment:
            ############################################################
            # Here you can feed the batch_img to an instance of 
            # ImageDataGenerator if you would like to augment the images.
            # Note that you need to generate images using that instance as well
            ############################################################

        # Here we assume that the each column in annotations array
        # corresponds to one of the outputs of our neural net
        # i.e. annotations[:,0] to output1, annotations[:,1] to output2, etc. 
        target = annotations[idx:idx+batch_size]
        batch_target = []
        for i in range(annotations.shape[1]):
            batch_target.append(target[:,i])

        idx += batch_size
        if idx > n_samples - batch_size:
            idx = 0

        yield batch_img, batch_target

train_gen = generator(train_csv_path, train_batch_size, 256, 256, 3)
val_gen = generator(val_csv_path, val_batch_size, 256, 256, 3)
test_gen = generator(test_csv_path, test_batch_size, 256, 256, 3)

model.fit_generator(train_gen,
                    steps_per_epoch= , # should be set to num_train_samples / train_batch_size 
                    epochs= , # your desired number of epochs,
                    validation_data= val_gen,
                    validation_steps= # should be set to num_val_samples / val_batch_size)

Поскольку я точно не знаю формат и типы аннотаций, возможно, вам придется внести изменения в этот код, чтобы он работал на вас. Кроме того, учитывая текущий способ обновления idx, если n_sample не делится на batch_size, некоторые из семплов в конце могут вообще не использоваться. Так что это можно сделать намного лучше. Одним из быстрых решений будет:

idx += batch_size
if idx == n_samples:
    idx = 0
else if idx > n_samples - batch_size:
    idx = n_samples - batch_size

Однако, независимо от того, как вы обновляете idx, если вы используете fit_generator и учитывая, что n_samples не делится на batch_size, то в каждую эпоху либо некоторые из выборок могут не генерироваться, либо некоторые из образцов может быть сгенерировано более одного раза в зависимости от значения аргумента steps_per_epoch (что, я думаю, не является существенной проблемой).

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