Keras - fit_generator()中如何使用批次和时期?

时间:2016-08-13 19:01:10

标签: python tensorflow generator keras

我有一个8000帧的视频,我想在每个200帧的批次上训练一个Keras模型。我有一个帧生成器,逐帧循环遍历视频,并将(3 x 480 x 640)帧累积成形状为X的numpy矩阵(200, 3, 480, 640) - (批量大小,rgb,帧高,帧宽) - 每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,下一个纪元将从第0帧开始再次训练。这是正确的吗?

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

如果我对fit_generator的理解不正确,请解释。我已经阅读了文档,example和这些related issues。我正在使用带有TensorFlow后端的Keras v1.0.7。此问题也发布在Keras repo

3 个答案:

答案 0 :(得分:9)

  

第一个纪元完成后(模型记录批次0-24之后),生成器从中断处开始

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

答案 1 :(得分:6)

您可以通过添加while 1:循环来强制您的生成器重置自己,这就是我如何继续。因此,您的生成器可以为每个历元生成批处理数据。

答案 2 :(得分:0)

由于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