Почему пользовательский генератор изображений в keras выдает ошибку, объект не может быть интерпретирован как целое число?

Я использовал шаблон настраиваемого генератора изображений в keras, так что я могу использовать файлы hdf5 в качестве входных данных. Изначально код выдавал ошибку "shape", поэтому я включил from tensorflow.python.keras.utils.data_utils import Sequence только после этого сообщения. Теперь я использую его в этой форме, как вы также можете видеть в моем блокноте colab:

from numpy.random import uniform, randint
from tensorflow.python.keras.preprocessing.image import ImageDataGenerator
import numpy as np
from tensorflow.python.keras.utils.data_utils import Sequence

class CustomImagesGenerator(Sequence):
    def __init__(self, x, zoom_range, shear_range, rescale, horizontal_flip, batch_size):
        self.x = x
        self.zoom_range = zoom_range
        self.shear_range = shear_range
        self.rescale = rescale
        self.horizontal_flip = horizontal_flip
        self.batch_size = batch_size
        self.__img_gen = ImageDataGenerator()
        self.__batch_index = 0

    def __len__(self):
        # steps_per_epoch, if unspecified, will use the len(generator) as a number of steps.
        # hence this
        return np.floor(self.x.shape[0]/self.batch_size)

    # @property
    # def shape(self):
    #     return self.x.shape

    def next(self):
        return self.__next__()

    def __next__(self):
        start = self.__batch_index*self.batch_size
        stop = start + self.batch_size
        self.__batch_index += 1
        if stop > len(self.x):
            raise StopIteration
        transformed = np.array(self.x[start:stop])  # loads from hdf5
        for i in range(len(transformed)):
            zoom = uniform(self.zoom_range[0], self.zoom_range[1])
            transformations = {
                'zx': zoom,
                'zy': zoom,
                'shear': uniform(-self.shear_range, self.shear_range),
                'flip_horizontal': self.horizontal_flip and bool(randint(0,2))
            }
            transformed[i] = self.__img_gen.apply_transform(transformed[i], transformations)
        import pdb;pdb.set_trace()
        return transformed * self.rescale

И я вызываю генератор с:

import h5py
import tables 

in_hdf5_file = tables.open_file("gdrive/My Drive/Colab Notebooks/dataset.hdf5", mode='r')
images = in_hdf5_file.root.train_img

my_gen = CustomImagesGenerator(
    images,
    zoom_range=[0.8, 1],
    batch_size=32,
    shear_range=6, 
    rescale=1./255, 
    horizontal_flip=False
)

classifier.fit_generator(my_gen, steps_per_epoch=100, epochs=1, verbose=1)

Импорт Sequence устранил ошибку "формы", но теперь я получаю сообщение об ошибке:

Исключение в потоке Thread-5: Traceback (последний вызов последним):
Файл «/usr/lib/python3.6/threading.py», строка 916, в файле _bootstrap_inner self.run () «/ usr / lib /python3.6/threading.py ", строка 864, в процессе выполнения self._target (* self._args, ** self._kwargs) Файл" /usr/local/lib/python3.6/dist-packages/tensorflow/python /keras/utils/data_utils.py ", строка 742, в _run sequence = list (range (len (self.sequence))) TypeError: объект 'numpy.float64' не может быть интерпретирован как целое число

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


person NeStack    schedule 29.08.2019    source источник
comment
каковы dtype ваши данные?   -  person okawo    schedule 29.08.2019
comment
@okawo Из вышесказанного images, если я сделаю print(images.dtype), я получу dtype('uint8'). Это как-то помогает? Спасибо   -  person NeStack    schedule 29.08.2019
comment
извините за задержку, но попробуйте изменить dtype ваших изображений на np.float32 или np.float64. если ваши изображения np.arrays, вы можете сделать это: arr.astype(dtype)   -  person okawo    schedule 01.09.2019
comment
@okawo Я изменил dtype на разные типы (float32, float64, int) при создании файла изображения hdf5, но это не изменило сообщение об ошибке, каждый раз, когда в нем говорится о проблеме с 'numpy.float64'. Поэтому я думаю, что между некоторыми пакетами python существует конфликт. Вы также можете взглянуть на мой скрипт, который создает файлы изображений hdf5, которые я вставил внизу своего блокнота colab (ссылка в сообщении)   -  person NeStack    schedule 01.09.2019
comment
попробуйте удалить classifier.add(InputLayer(input_shape=data_shape)) из вашей модели, похоже, что у вас есть 2 слоя с входными данными в вашей последовательной модели   -  person okawo    schedule 01.09.2019
comment
@okawo Хорошо заметен, но это ничего не меняет, отображается то же сообщение об ошибке. Вы можете попробовать создать hdf5 самостоятельно, вам просто нужно указать скрипту в каталог, в котором у вас есть jpg-файл. а затем воспроизвести ошибку, запустив собственный генератор. Спасибо за ответы!   -  person NeStack    schedule 01.09.2019
comment
Хорошо, поэтому я провел несколько тестов, похоже, что проблема в вашем классе генератора, я могу запустить ваш код и обучить вашу модель, если я использую только model.fit(), а не model.fit_generator(). также ваш класс генератора не может выводить обучающие данные, он может выводить только изображения, но для обучения вашей модели вам нужно x=images, y=labels, плюс у вас уже есть ваши данные, сохраненные и обработанные, почему бы просто не использовать fit() с вашими данными, загруженными как есть с вашего hdf5 файл?   -  person okawo    schedule 01.09.2019


Ответы (1)


Пример использования с model.fit() в вашем случае:

from tensorflow.keras.utils import to_categorical
import tensorflow as tf
import tables

#define your model

...

#load your data from an hdf5 file
in_hdf5_file = tables.open_file("path/to/your/dataset.hdf5", mode='r')
x = in_hdf5_file.root.train_img[:]
y = in_hdf5_file.root.train_labels[:]

yourModel.fit(x, to_categorical(y, 3), epochs=2, batch_size=5)

Для получения дополнительной информации прочтите мои комментарии к вашему исходному сообщению или не стесняйтесь спрашивать.

РЕДАКТИРОВАТЬ: Я исправил ваш генератор, теперь ему нужен только путь к вашему файлу hdf5

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import *
from tensorflow.keras.utils import to_categorical

import numpy as np
from tensorflow.python.keras.utils.data_utils import Sequence
import tensorflow as tf

import tables

#define your model

...

#training
def h5data_generator(path, batch_size=1):
    batch_index = 0
    while 1:
        with tables.open_file(path, mdoe='r') as f:
            x = f.root.train_img[batch_index:batch_index + batch_size]
            y = f.root.train_labels[batch_index:batch_index + batch_size]

            if batch_index >= x.shape[0]:
                batch_index = 0

            batch_index += 1

            yield (x, to_categorical(y, 3))

            del x
            del y


my_gen = h5data_generator("path/to/your/dataset.hdf5")

yourModel.fit_generator(my_gen, steps_per_epoch=100, epochs=20, verbose=1)

Проблема с вашим генератором заключалась в том, что на этапе выводились неверные данные, он не выводил (x, y), не мог, он выводил x (изображение в вашем случае), также поскольку он использовал Sequential keras, пытался интерпретировать его как объект, который использовал его api (не в вашем генераторе). Кроме того, это не обязательно должен быть class, он должен быть генератором Python, поскольку указывается примером в самом keras (строка документа fit_generator()),

fit_generator.__doc__:

Fits the model on data yielded batch-by-batch by a Python generator.

    The generator is run in parallel to the model, for efficiency.
    For instance, this allows you to do real-time data augmentation
    on images on CPU in parallel to training your model on GPU.

    The use of `keras.utils.Sequence` guarantees the ordering
    and guarantees the single use of every input per epoch when
    using `use_multiprocessing=True`.

    Arguments:
        generator: A generator or an instance of `Sequence`
          (`keras.utils.Sequence`)
            object in order to avoid duplicate data
            when using multiprocessing.
            The output of the generator must be either
            - a tuple `(inputs, targets)`
            - a tuple `(inputs, targets, sample_weights)`.
            This tuple (a single output of the generator) makes a single batch.
            Therefore, all arrays in this tuple must have the same length (equal
            to the size of this batch). Different batches may have different
              sizes.
            For example, the last batch of the epoch is commonly smaller than
              the
            others, if the size of the dataset is not divisible by the batch
              size.
            The generator is expected to loop over its data
            indefinitely. An epoch finishes when `steps_per_epoch`
            batches have been seen by the model.
        steps_per_epoch: Total number of steps (batches of samples)
            to yield from `generator` before declaring one epoch
            finished and starting the next epoch. It should typically
            be equal to the number of samples of your dataset
            divided by the batch size.
            Optional for `Sequence`: if unspecified, will use
            the `len(generator)` as a number of steps.
        epochs: Integer, total number of iterations on the data.
        verbose: Verbosity mode, 0, 1, or 2.
        callbacks: List of callbacks to be called during training.
        validation_data: This can be either
            - a generator for the validation data
            - a tuple (inputs, targets)
            - a tuple (inputs, targets, sample_weights).
        validation_steps: Only relevant if `validation_data`
            is a generator. Total number of steps (batches of samples)
            to yield from `generator` before stopping.
            Optional for `Sequence`: if unspecified, will use
            the `len(validation_data)` as a number of steps.
        validation_freq: Only relevant if validation data is provided. Integer
            or `collections.Container` instance (e.g. list, tuple, etc.). If an
            integer, specifies how many training epochs to run before a new
            validation run is performed, e.g. `validation_freq=2` runs
            validation every 2 epochs. If a Container, specifies the epochs on
            which to run validation, e.g. `validation_freq=[1, 2, 10]` runs
            validation at the end of the 1st, 2nd, and 10th epochs.
        class_weight: Dictionary mapping class indices to a weight
            for the class.
        max_queue_size: Integer. Maximum size for the generator queue.
            If unspecified, `max_queue_size` will default to 10.
        workers: Integer. Maximum number of processes to spin up
            when using process-based threading.
            If unspecified, `workers` will default to 1. If 0, will
            execute the generator on the main thread.
        use_multiprocessing: Boolean.
            If `True`, use process-based threading.
            If unspecified, `use_multiprocessing` will default to `False`.
            Note that because this implementation relies on multiprocessing,
            you should not pass non-picklable arguments to the generator
            as they can't be passed easily to children processes.
        shuffle: Boolean. Whether to shuffle the order of the batches at
            the beginning of each epoch. Only used with instances
            of `Sequence` (`keras.utils.Sequence`).
            Has no effect when `steps_per_epoch` is not `None`.
        initial_epoch: Epoch at which to start training
            (useful for resuming a previous training run)

    Returns:
        A `History` object.

    Example:

    ```python
        def generate_arrays_from_file(path):
            while 1:
                f = open(path)
                for line in f:
                    # create numpy arrays of input data
                    # and labels, from each line in the file
                    x1, x2, y = process_line(line)
                    yield ({'input_1': x1, 'input_2': x2}, {'output': y})
                f.close()

        model.fit_generator(generate_arrays_from_file('/my_file.txt'),
                            steps_per_epoch=10000, epochs=10)
    ```
    Raises:
        ValueError: In case the generator yields data in an invalid format.

Для получения дополнительной информации посетите страницу github keras, fit_generator() если быть точным, или снова спросите.

РЕДАКТИРОВАТЬ 2: Вы также можете передать batch_size h5data_generator(), который установит размер пакета данных, извлекаемых из вашего набора данных за один шаг.

person okawo    schedule 01.09.2019
comment
Спасибо, похоже, ваше предложение работает! Я протестирую это и вернусь с более подробными отзывами - person NeStack; 02.09.2019
comment
хорошо, я тоже постараюсь починить ваш генератор, но это займет некоторое время, потому что жизнь - person okawo; 02.09.2019
comment
Большое спасибо! Я сделал несколько прогонов с вашим hdf5_generator, и действительно, эпохи намного короче. Хотя я заметил, что нейронная сеть на самом деле не обучается - потери остаются постоянными на уровне ~ 10, а точность не улучшается. Вы это тоже заметили, есть ли у вас объяснение? - person NeStack; 02.09.2019
comment
в своих тестах я использовал вашу модель, однако я также использовал случайные изображения, которые соответствовали входным данным вашей модели и случайным меткам, и у меня было только 6 из них, но я изменил оптимизатор на Адама. во время тестовых прогонов модель за несколько эпох перешла в loss=0 acc=1. но вы можете попробовать поиграть со скоростью обучения и / или добавить больше слоев к вашей модели. ой а если не секрет, что вы классифицируете? - person okawo; 02.09.2019
comment
мой оптимизатор во время тестирования: tf.train.AdamOptimizer(0.001), где 0.001 - скорость обучения, а tf - tensorflow - person okawo; 02.09.2019