Генератор «Ошибка типа: объект« генератор »не является итератором» - PullRequest
0 голосов
/ 08 февраля 2019

Из-за ограничений оперативной памяти я следовал этим инструкциям и построил генератор, который рисует небольшие партии и передает их в fit_generator Keras.Но Keras не может подготовить очередь с помощью многопроцессорной обработки, даже если я наследую последовательность.

Вот мой генератор для многопроцессорной обработки.

class My_Generator(Sequence):
    def __init__(self, image_filenames, labels, batch_size):
        self.image_filenames, self.labels = image_filenames, labels
        self.batch_size = batch_size

    def __len__(self):
        return np.ceil(len(self.image_filenames) / float(self.batch_size))

    def __getitem__(self, idx):
        batch_x = self.image_filenames[idx * self.batch_size:(idx + 1) * self.batch_size]
        batch_y = self.labels[idx * self.batch_size:(idx + 1) * self.batch_size]

    return np.array([
        resize(imread(file_name), (200, 200))
           for file_name in batch_x]), np.array(batch_y)

Основная функция:

batch_size = 100
num_epochs = 10
train_fnames = []
mask_training = []
val_fnames = [] 
mask_validation = []

Мне бы хотелось, чтобы генератор считывал пакеты в папках по отдельности в разных потоках по идентификаторам (где идентификаторы выглядят так: {число} .csv для необработанных изображений и {число} _label.csv для изображений масок).Сначала я создал еще один более элегантный класс, чтобы хранить все данные в одном файле .h5 вместо каталога.Но заблокирован той же проблемой.Таким образом, если у вас есть код для этого, я тоже беру.

for dirpath, _, fnames in os.walk('./train/'):
    for fname in fnames:
        if 'label' not in fname:
            training_filenames.append(os.path.abspath(os.path.join(dirpath, fname)))
        else:
            mask_training.append(os.path.abspath(os.path.join(dirpath, fname)))
for dirpath, _, fnames in os.walk('./validation/'):
    for fname in fnames:
        if 'label' not in fname:
            validation_filenames.append(os.path.abspath(os.path.join(dirpath, fname)))
        else:
            mask_validation.append(os.path.abspath(os.path.join(dirpath, fname)))


my_training_batch_generator = My_Generator(training_filenames, mask_training, batch_size)
my_validation_batch_generator = My_Generator(validation_filenames, mask_validation, batch_size)
num_training_samples = len(training_filenames)
num_validation_samples = len(validation_filenames)

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

mdl = model.compile(...)
mdl.fit_generator(generator=my_training_batch_generator,
              steps_per_epoch=(num_training_samples // batch_size),
              epochs=num_epochs,
              verbose=1,
              validation_data=None, #my_validation_batch_generator,
              # validation_steps=(num_validation_samples // batch_size),
              use_multiprocessing=True,
              workers=4,
              max_queue_size=2)

Ошибка показывает, что созданный мной класс не является итератором:

Traceback (most recent call last):
File "test.py", line 141, in <module> max_queue_size=2)
File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/keras/engine/training.py", line 2177, in fit_generator
initial_epoch=initial_epoch)
File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_generator.py", line 147, in fit_generator
generator_output = next(output_generator)
File "/anaconda3/lib/python3.6/site-packages/tensorflow/python/keras/utils/data_utils.py", line 831, in get six.reraise(value.__class__, value, value.__traceback__)
File "/anaconda3/lib/python3.6/site-packages/six.py", line 693, in reraise
raise value
TypeError: 'My_Generator' object is not an iterator

Ответы [ 2 ]

0 голосов
/ 26 августа 2019

Я понял это.Моя модель была from keras.models import Model Однако генератор был расширен с class DataGenerator(tf.keras.utils.Sequence): Это вызывает ошибку!Итак, просто измените Генератор class DataGenerator(tf.keras.utils.Sequence) на class DataGenerator(keras.utils.Sequence):

0 голосов
/ 18 июля 2019

У меня возникла та же проблема, мне удалось решить ее, определив метод __next__:

class My_Generator(Sequence):
    def __init__(self, image_filenames, labels, batch_size):
        self.image_filenames, self.labels = image_filenames, labels
        self.batch_size = batch_size
        self.n = 0
        self.max = self.__len__()


    def __len__(self):
        return np.ceil(len(self.image_filenames) / float(self.batch_size))

    def __getitem__(self, idx):
        batch_x = self.image_filenames[idx * self.batch_size:(idx + 1) * self.batch_size]
        batch_y = self.labels[idx * self.batch_size:(idx + 1) * self.batch_size]

        return np.array([
        resize(imread(file_name), (200, 200))
           for file_name in batch_x]), np.array(batch_y)

    def __next__(self):
        if self.n >= self.max:
           self.n = 0
        result = self.__getitem__(self.n)
        self.n += 1
        return result

Обратите внимание, что я объявил две новые переменные в функции __init__.

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