【问题标题】:Keras - How are batches and epochs used in fit_generator()?Keras - fit_generator() 中如何使用批次和时期?
【发布时间】:2016-12-20 12:48:09
【问题描述】:

我有一个 8000 帧的视频,我想在每批 200 帧上训练一个 Keras 模型。我有一个帧生成器,它逐帧循环播放视频并将(3 x 480 x 640)帧累积到形状为(200, 3, 480, 640)的numpy矩阵(200, 3, 480, 640)——(批量大小,rgb,帧高度,帧width) -- 并且每 200 帧产生 XY

import cv2
...
def _frameGenerator(videoPath, dataPath, batchSize):
    """
    Yield X and Y data when the batch is filled.
    """
    camera = cv2.VideoCapture(videoPath)
    width = camera.get(3)
    height = camera.get(4)
    frameCount = int(camera.get(7))  # Number of frames in the video file.

    truthData = _prepData(dataPath, frameCount)

    X = np.zeros((batchSize, 3, height, width))
    Y = np.zeros((batchSize, 1))

    batch = 0
    for frameIdx, truth in enumerate(truthData):
        ret, frame = camera.read()
        if ret is False: continue

        batchIndex = frameIdx%batchSize

        X[batchIndex] = frame
        Y[batchIndex] = truth

        if batchIndex == 0 and frameIdx != 0:
            batch += 1
            print "now yielding batch", batch
            yield X, Y

这是fit_generator()的运行方式:

        batchSize = 200
        print "Starting training..."
        model.fit_generator(
            _frameGenerator(videoPath, dataPath, batchSize),
            samples_per_epoch=8000,
            nb_epoch=10,
            verbose=args.verbosity
        )

我的理解是当模型看到samples_per_epoch 样本并且samples_per_epoch = 批大小 * 批数 = 200 * 40 时,一个纪元结束。因此,在帧 0-7999 上训练一个纪元后,下一个 epoch 将从第 0 帧开始再次训练。这是正确的吗?

使用此设置我希望每个 epoch 有 40 个批次(每个 200 帧)从生成器传递到 fit_generator;这将是每个 epoch 总共 8000 帧——即samples_per_epoch=8000。然后对于后续的 epoch,fit_generator 将重新初始化生成器,以便我们从视频开始再次开始训练。然而事实并非如此。 在第一个 epoch 完成后(在模型记录批次 0-24 之后),生成器从中断处继续。新纪元不应该从训练数据集的开头重新开始吗?

如果我对fit_generator的理解有误,请解释。我浏览了文档,这个example 和这些related issues。我正在使用带有 TensorFlow 后端的 Keras v1.0.7。这个问题也发布在Keras repo

【问题讨论】:

标签: python tensorflow generator keras


【解决方案1】:

第一个 epoch 完成后(模型记录批次 0-24 之后),生成器从中断处继续

这是对所发生情况的准确描述。如果您想重置或倒带发电机,您必须在内部执行此操作。请注意,keras 的行为在许多情况下都非常有用。例如,您可以在查看 1/2 数据后结束一个 epoch,然后在另一半上执行一个 epoch,如果重置了生成器状态,这是不可能的(这对于更密切地监控验证很有用)。

【讨论】:

  • 嗯,这是一个有用的功能,谢谢你的详细信息。
【解决方案2】:

您可以通过添加while 1: 循环来强制您的生成器自行重置,我就是这样做的。因此,您的生成器可以为每个时期生成批处理数据。

【讨论】:

    【解决方案3】:

    因为Generator是一个完全独立的函数,所以无论何时再次调用它都会无限循环。

    我无法证明fit_generator() 会调用生成器,直到它有足够的样本。我找不到变量batch_size,但必须有一个标准来设置定义大小的内部变量。

    我在每个循环序列中打印状态时检查了这一点:

    def generator():
    
    while 1:
        for i in range(0,len(x_v)-1):
            if (i != predict_batch_nr):
                print("\n -> usting Datasett ", i+1 ," of ", len(x_v))
                x = x_v[i] #x_v has Batches of different length
                y = y_v[i] #y_v has Batches of different length
    
                yield x, y
    
    
    model.fit_generator(generator(),steps_per_epoch=5000,epochs=20, verbose=1)
    

    示例输出为:

    4914/5000 [============================>.] - ETA: 13s - loss: 2442.8587
    usting Datasett  77  of  92
    4915/5000 [============================>.] - ETA: 12s - loss: 2442.3785
    -> usting Datasett  78  of  92
    -> usting Datasett  79  of  92
    -> usting Datasett  80  of  92
    4918/5000 [============================>.] - ETA: 12s - loss: 2442.2111
    -> usting Datasett  81  of  92
    -> usting Datasett  82  of  92
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-17
      • 1970-01-01
      • 2019-10-27
      • 2019-10-07
      • 1970-01-01
      • 2019-08-21
      • 2018-02-09
      相关资源
      最近更新 更多