Ошибка памяти при использовании Keras ImageDataGenerator

Я пытаюсь предсказать особенности в изображениях, используя keras с поддержкой TensorFlow. В частности, я ImageDataGenerator использовать keras ImageDataGenerator. Модель рассчитана на 4 эпохи и работает до 4-й эпохи, когда она терпит неудачу с MemoryError.

Я запускаю эту модель на экземпляре AWS g2.2xlarge, работающем под управлением Ubuntu Server 16.04 LTS (HVM), SSD Volume Type.

Образовательные изображения представляют собой 256x256 RGB пиксельные плитки (8 бит без знака), а обучающая маска - 256x256 однополосных (8-битных неподписанных) данных, где 255 == интересующая функция и 0 == все остальное.

Следующие три функции относятся к этой ошибке.

Как я могу устранить этот MemoryError?


def train_model():
        batch_size = 1
        training_imgs = np.lib.format.open_memmap(filename=os.path.join(data_path, 'data.npy'),mode='r+')
        training_masks = np.lib.format.open_memmap(filename=os.path.join(data_path, 'mask.npy'),mode='r+')
        dl_model = create_model()
        print(dl_model.summary())
        model_checkpoint = ModelCheckpoint(os.path.join(data_path,'mod_weight.hdf5'), monitor='loss',verbose=1, save_best_only=True)
        dl_model.fit_generator(generator(training_imgs, training_masks, batch_size), steps_per_epoch=(len(training_imgs)/batch_size), epochs=4,verbose=1,callbacks=[model_checkpoint])

def generator(train_imgs, train_masks=None, batch_size=None):

# Create empty arrays to contain batch of features and labels#

        if train_masks is not None:
                train_imgs_batch = np.zeros((batch_size,y_to_res,x_to_res,bands))
                train_masks_batch = np.zeros((batch_size,y_to_res,x_to_res,1))

                while True:
                        for i in range(batch_size):
                                # choose random index in features
                                index= random.choice(range(len(train_imgs)))
                                train_imgs_batch[i] = train_imgs[index]
                                train_masks_batch[i] = train_masks[index]
                        yield train_imgs_batch, train_masks_batch
        else:
                rec_imgs_batch = np.zeros((batch_size,y_to_res,x_to_res,bands))
                while True:
                        for i in range(batch_size):
                                # choose random index in features
                                index= random.choice(range(len(train_imgs)))
                                rec_imgs_batch[i] = train_imgs[index]
                        yield rec_imgs_batch

def train_generator(train_images,train_masks,batch_size):
        data_gen_args=dict(rotation_range=90.,horizontal_flip=True,vertical_flip=True,rescale=1./255)
        image_datagen = ImageDataGenerator()
        mask_datagen = ImageDataGenerator()
# # Provide the same seed and keyword arguments to the fit and flow methods
        seed = 1
        image_datagen.fit(train_images, augment=True, seed=seed)
        mask_datagen.fit(train_masks, augment=True, seed=seed)
        image_generator = image_datagen.flow(train_images,batch_size=batch_size)
        mask_generator = mask_datagen.flow(train_masks,batch_size=batch_size)
        return zip(image_generator, mask_generator)

Следующие данные выводятся из модели, детализирующей эпохи, и сообщения об ошибке:

Epoch 00001: loss improved from inf to 0.01683, saving model to /home/ubuntu/deep_learn/client_data/mod_weight.hdf5
Epoch 2/4
7569/7569 [==============================] - 3394s 448ms/step - loss: 0.0049 - binary_crossentropy: 0.0027 - jaccard_coef_int: 0.9983  

Epoch 00002: loss improved from 0.01683 to 0.00492, saving model to /home/ubuntu/deep_learn/client_data/mod_weight.hdf5
Epoch 3/4
7569/7569 [==============================] - 3394s 448ms/step - loss: 0.0049 - binary_crossentropy: 0.0026 - jaccard_coef_int: 0.9982  

Epoch 00003: loss improved from 0.00492 to 0.00488, saving model to /home/ubuntu/deep_learn/client_data/mod_weight.hdf5
Epoch 4/4
7569/7569 [==============================] - 3394s 448ms/step - loss: 0.0074 - binary_crossentropy: 0.0042 - jaccard_coef_int: 0.9975  

Epoch 00004: loss did not improve
Traceback (most recent call last):
  File "image_rec.py", line 291, in <module>
    train_model()
  File "image_rec.py", line 208, in train_model
    dl_model.fit_generator(train_generator(training_imgs,training_masks,batch_size),steps_per_epoch=1,epochs=1,workers=1)
  File "image_rec.py", line 274, in train_generator
    image_datagen.fit(train_images, augment=True, seed=seed)
  File "/home/ubuntu/pyvirt_test/local/lib/python2.7/site-packages/keras/preprocessing/image.py", line 753, in fit
    x = np.copy(x)
  File "/home/ubuntu/pyvirt_test/local/lib/python2.7/site-packages/numpy/lib/function_base.py", line 1505, in copy
    return array(a, order=order, copy=True)
MemoryError

Ответы

Ответ 1

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

Второй, который я считаю жизнеспособным. Я бы обрезал данные, и я бы попробовал портировать модель постепенно. Мы можем сделать это с помощью Dask. Эта библиотека может обрезать данные и сохранять объекты, которые затем можно извлечь с диска, только в той части, которую вы хотите.

Если у вас есть изображение, размер которого является матрицей 100x100, мы можем получить каждый массив без необходимости загрузки 100 массивов в память. Мы можем загрузить массив по массиву в памяти (высвобождая предыдущий), который будет использоваться в вашей нейронной сети.

Для этого вы можете преобразовать ваш np.array в массив dask и назначить разделы. Например:

>>> k = np.random.randn(10,10) # Matrix 10x10
>>> import dask.array as da
>>> k2 = da.from_array(k,chunks = 3)
dask.array<array, shape=(10, 10), dtype=float64, chunksize=(3, 3)>
>>> k2.to_delayed()
array([[Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 0, 0)),
    Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 0, 1)),
    Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 0, 2)),
    Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 0, 3))],
   [Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 1, 0)),
    Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 1, 1)),
    Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 1, 2)),
    Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 1, 3))],
   [Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 2, 0)),
    Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 2, 1)),
    Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 2, 2)),
    Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 2, 3))],
   [Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 3, 0)),
    Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 3, 1)),
    Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 3, 2)),
    Delayed(('array-a08c1d25b900d497cdcd233a7c5aa108', 3, 3))]],
  dtype=object)

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

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

Для получения дополнительной информации см. Документацию Dask

Ответ 2

Вы предоставили довольно запутанный код (на мой взгляд), т.е. не видно вызова в train_generator. Я не уверен, что это проблема недостаточного запоминания из-за больших данных, поскольку для этого вы используете memmap, но предположим, что на данный момент это так.

  • Если данные довольно велики, и поскольку вы все равно загружаете изображения из каталога, может быть ImageDataGenerator flow_from_directory метод ImageDataGenerator flow_from_directory. Это потребует небольшого изменения дизайна, которое, возможно, не так, как вы хотите.

Вы можете загрузить его следующим образом:

train_datagen = ImageDataGenerator()
train_generator = train_datagen.flow_from_directory(
        'data/train',
        target_size=(256, 256),
        batch_size=batch_size,
        ...  # other configurations)

Подробнее об этом в документации Keras.

  • Также обратите внимание, что если у вас 32bit, memmap не позволяет больше 2 ГБ.

  • Используете ли вы tensorflow-gpu, случайно? Возможно, вашего gpu недостаточно, вы можете попробовать это с tensorflow пакета tensorflow.

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


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


Наконец, последняя заметка здесь. Хорошей практикой является загрузка memmap учебных данных как read-only, так как вы не хотите случайно испортить данные.

ОБНОВЛЕНИЕ. Я вижу, что вы обновили сообщение и предоставили код для метода train_generator, но в этом вызове по-прежнему нет вызова этого метода.

Если я предполагаю, что у вас есть опечатка в вызове - train_generator вместо метода generator в вашем методе d1_model.fit_generator, возможно, что метод fit_generator не работает с партией данных, но на самом деле в целом training_imgs и он копирует по всему набору в np.copy(x).

Кроме того, как уже упоминалось, действительно есть (вы можете найти некоторые из них, например, открытые), некоторые проблемы с утечкой памяти fit_generator при использовании методов fit и fit_generator.

Ответ 3

Обычно Keras/Tensorflow очень хорош в использовании ресурсов, но есть известная утечка памяти, которая в прошлом вызывала проблемы. Чтобы убедиться, что не тот, который вызывает ваши проблемы, попробуйте включить эти две строки кода в учебный скрипт:

# load the backend
from keras import backend as K

# prevent Tensorflow memory leakage
K.clear_session()

Ответ 4

Это часто встречается при работе с 32-разрядным, если точность поплавка слишком высока. Вы используете 32bit? Вы также можете рассмотреть возможность литья или округления массива.

Ответ 5

Я недавно встретил ту же проблему. Как-то код FCN-8 может успешно работать на моем компьютере tensorflow1.2 + keras2.0.9 + 8G RAM +1060, но произошла ошибка памяти при использовании точки модели на моем tf1.4 + keras2.1.5 + 16g ram +1080ti computer,