【问题标题】:what raises StopIteration in mine Keras Model.fit_generator是什么在我的 Keras Model.fit_generator 中引发了 StopIteration
【发布时间】:2018-02-28 09:14:14
【问题描述】:

我有下一个代码:

from sklearn.model_selection import train_test_split
from scipy.misc import imresize

def _chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]


def _batch_generator(data, batch_size):
    indexes = range(len(data))
    index_chunks = _chunks(indexes, batch_size)
    for i, indexes in enumerate(index_chunks):
        print("\nLoaded batch {0}\n".format(i + 1))
        batch_X = []
        batch_y = []
        for index in indexes:
            record = data[index]
            image = _read_train_image(record["id"], record["index"])
            mask = _read_train_mask(record["id"], record["index"])
            mask_resized = imresize(mask, (1276, 1916)) >= 123
            mask_reshaped = mask_resized.reshape((1276, 1916, 1))
            batch_X.append(image)
            batch_y.append(mask_reshaped)
        np_batch_X = np.array(batch_X)
        np_batch_y = np.array(batch_y)
        yield np_batch_X, np_batch_y


def train(data, model, batch_size, epochs):
    train_data, test_data = train_test_split(data)
    samples_per_epoch = len(train_data)
    steps_per_epoch = samples_per_epoch // batch_size
    print("Train on {0} records ({1} batches)".format(samples_per_epoch, steps_per_epoch))
    train_generator = _batch_generator(train_data, batch_size)
    model.fit_generator(train_generator, 
                        steps_per_epoch=steps_per_epoch, 
                        nb_epoch=epochs, 
                        verbose=1)

train(train_indexes[:30], autoencoder,
    batch_size=2,
    epochs=1)

看来它必须在下一个方式工作:

  • 从数据集中获取 30 个(仅作为示例)索引
  • 将其吐出到 22 个火车记录和 8 个验证索引(尚未使用)
  • 将训练索引拆分为生成器中 2 个索引的批次(所以 - 11 个批次)并且它有效 - len(list(_batch_generator(train_indexes[:22], 2))) 确实返回 11
  • 适合型号:
    • train_generator 生成的批次(在我的情况下 - 11 个批次,每个批次 - 2 个图像)
    • epoch 有 11 个批次 (steps_per_epoch=steps_per_epoch)
    • 和 1 个 epoch (nb_epochs=epochs, epochs=1)

但输出有下一个视图:

Train on 22 records (11 batches)
Epoch 1/1

Loaded batch 1

C:\Users\user\venv\machinelearning\lib\site-packages\ipykernel_launcher.py:39: UserWarning: The semantics of the Keras 2 argument `steps_per_epoch` is not the same as the Keras 1 argument `samples_per_epoch`. `steps_per_epoch` is the number of batches to draw from the generator at each epoch. Basically steps_per_epoch = samples_per_epoch/batch_size. Similarly `nb_val_samples`->`validation_steps` and `val_samples`->`steps` arguments have changed. Update your method calls accordingly.
C:\Users\user\venv\machinelearning\lib\site-packages\ipykernel_launcher.py:39: UserWarning: Update your `fit_generator` call to the Keras 2 API: `fit_generator(<generator..., steps_per_epoch=11, verbose=1, epochs=1)`

Loaded batch 2

1/11 [=>............................] - ETA: 11s - loss: 0.7471
Loaded batch 3


Loaded batch 4


Loaded batch 5


Loaded batch 6

2/11 [====>.........................] - ETA: 17s - loss: 0.7116
Loaded batch 7


Loaded batch 8


Loaded batch 9


Loaded batch 10

3/11 [=======>......................] - ETA: 18s - loss: 0.6931
Loaded batch 11

Exception in thread Thread-50:
Traceback (most recent call last):
File "C:\Anaconda3\Lib\threading.py", line 916, in _bootstrap_inner
    self.run()
File "C:\Anaconda3\Lib\threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
File "C:\Users\user\venv\machinelearning\lib\site-packages\keras\utils\data_utils.py", line 560, in data_generator_task
    generator_output = next(self._generator)
StopIteration

4/11 [=========>....................] - ETA: 18s - loss: 0.6663
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-16-092ba6eb51d2> in <module>()
    1 train(train_indexes[:30], autoencoder,
    2       batch_size=2,
----> 3       epochs=1)

<ipython-input-15-f2fec4e53382> in train(data, model, batch_size, epochs)
    37                         steps_per_epoch=steps_per_epoch,
    38                         nb_epoch=epochs,
---> 39                         verbose=1)

C:\Users\user\venv\machinelearning\lib\site-packages\keras\legacy\interfaces.py in wrapper(*args, **kwargs)
    85                 warnings.warn('Update your `' + object_name +
    86                               '` call to the Keras 2 API: ' + signature, stacklevel=2)
---> 87             return func(*args, **kwargs)
    88         wrapper._original_function = func
    89         return wrapper

C:\Users\user\venv\machinelearning\lib\site-packages\keras\engine\training.py in fit_generator(self, generator, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, class_weight, max_queue_size, workers, use_multiprocessing, initial_epoch)
1807                 batch_index = 0
1808                 while steps_done < steps_per_epoch:
-> 1809                     generator_output = next(output_generator)
1810 
1811                     if not hasattr(generator_output, '__len__'):

StopIteration: 

所以我可以看到 - 所有批次都被成功读取(请参阅“加载的批次”)

但是在处理 epoch 1 的第 3 批期间,keras 提出了 StopIteration。

【问题讨论】:

  • 如果您对 model.fit_generator 的调用每次都以相同的样本计数提高 StopIteration,然后仔细检查您传递给 fit_generator 方法的生成器是否产生与“中指定的相同数量的样本” steps_per_epoch”参数。这就是我这边出现这个错误的原因。

标签: keras


【解决方案1】:

我也遇到了这个问题,我找到了一个方法是你可以在数据生成器函数中插入“while True”块。但我无法获得来源。你可以参考我的代码如下:

while True:
     assert len(inputs) == len(targets)
     indices = np.arange(len(inputs))
     if shuffle:
        np.random.shuffle(indices)
     if batchsize > len(indices):
        sys.stderr.write('BatchSize out of index size')
     batchsize = len(indices)
     for start_idx in range(0, len(inputs) - batchsize + 1, batchsize):
         if shuffle:
            excerpt = indices[start_idx:start_idx + batchsize]
         else:
            excerpt = slice(start_idx, start_idx + batchsize)
         yield inputs[excerpt], targets[excerpt]

【讨论】:

  • 这个答案对我很有帮助。对于那些后来得到这个答案的人,在 Keras 中,fit_generator 中的生成器需要无限迭代。这个想法是创建生成器的函数需要负责根据需要多次循环您的数据。 (或许你可以编辑添加进去)
【解决方案2】:

关于此问题的说明,以防其他人来到此页面追逐它。 StopIteration 错误是 keras 中的一个已知问题,有时可以通过确保将批量大小设置为样本数的整数倍来修复。如果这不能解决问题,我发现的一件事是数据生成器无法读取的时髦文件格式有时也会导致 stopIteration 错误。为了解决这个问题,我在训练文件夹上运行了一个脚本,在训练之前将所有图像转换为标准文件类型(jpg 或 png)。它看起来像这样。

import glob
from PIL import Image
import os
d=1
for sample in glob.glob(r'C:\Users\Jeremiah\Pictures\training\classLabel_unformatted\*'):
    im = Image.open(sample)
    im.save(r'C:\Users\Jeremiah\Pictures\training\classLabel_formatted\%s.png' %d)
    d=d+1

我发现运行这个脚本或类似的东西大大降低了我出现这类错误的频率,尤其是当我的训练数据来自谷歌图片搜索等地方时。

【讨论】:

    【解决方案3】:

    我找到了问题的根源。 首先 - 在拟合结束之前完全读取数据集,因此它会引发

    Exception in thread Thread-50:
    Traceback (most recent call last):
    File "C:\Anaconda3\Lib\threading.py", line 916, in _bootstrap_inner
    self.run()
    File "C:\Anaconda3\Lib\threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
    File "C:\Users\user\venv\machinelearning\lib\site-packages\keras\utils\data_utils.py", line 560, in data_generator_task
    generator_output = next(self._generator)
    StopIteration
    

    异常处理程序设置 stop_event 并重新引发异常

    但是:

    def get(self):
        """Creates a generator to extract data from the queue.
    
        Skip the data if it is `None`.
    
        # Returns
            A generator
        """
        while self.is_running():
            if not self.queue.empty():
                inputs = self.queue.get()
                if inputs is not None:
                    yield inputs
            else:
                time.sleep(self.wait_time)
    

    所以当设置停止事件时 - 它可以从队列中加载数据

    所以我将 max_queue_size 限制为 1。

    【讨论】:

    • 源问题来自生成器。在 Keras 中,fit_generator 中的生成器需要无限迭代。 time.sleep 解决了您的问题吗?我不会打赌,但我很好奇?
    猜你喜欢
    • 2020-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 2019-07-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多