如何为 keras fit_generator 编写生成器?

数据挖掘 Python 深度学习 喀拉斯 机器学习模型
2022-02-20 01:31:02

这个问题是这个问题的进一步步骤

我的数据输入是数十个.csv 文件,我已经读取了 csv 输入数据,直到以下格式:

# train_x is data, train_y is label
print(train_x.shape)       # (2000000,10,100)  3D array
print(train_y.shape)       # (2000000,)    labels

我已经可以使用以下方法拟合和评估它们:

model.fit(train_x, train_y, batch_size=32, epochs=10)
model.evaluate(train_x, train_y)

如果数据集小于 RAM 大小,则效果很好。但是如果数据集太大,那么“大数据集不适合内存”。大多数在线建议是使用fit_generator( )而不是fit( ) (也从 keras 网站建议)

fit_generator(generator, steps_per_epoch=None, epochs=1, verbose=1, callbacks=None, validation_data=None, validation_steps=None, validation_freq=1, class_weight=None, max_queue_size=10, workers=1, use_multiprocessing=False, shuffle=True, initial_epoch=0)

如何编写生成器函数(fit_generator 的第一个参数)?

  • 我只知道生成器功能旨在逐批提供数据。

    顾名思义,.fit_generator 函数假定有一个底层函数为其生成数据。

  • 这个生成器函数应该包括什么?应该退回什么?有没有相关的例子?

Mark:我已经阅读了几个在线示例(例如thisthis)。他们以图像为例,这不是我的情况(仅限 csv 数据),而且不容易理解。

2个回答

我将提供我第一次开始使用 fit_generator 时使用的两个教程。话虽这么说,首先要记住的是,生成器本质上与您编写的任何其他函数一样,它返回一些东西,但该函数运行一个旨在不退出的连续循环。例如,在普通函数中,每次调用该函数时,您将使用 return 来返回一些数据块。在生成器中,函数以块的形式连续返回数据,直到没有数据返回。这就是 yield 语句的作用。在我的项目中,我有几 TB 的信号数据。即使在功能强大的服务器上,对于我使用的硬件来说数据量也有点多。因此生成器函数分批提供数据块,它也可以并行运行以提高速度。这种方法还大大减少了您的内存使用量,通常,您的系统内存会达到某个点,并且在所有数据都输入 DNN 之前不会真正改变。我为糟糕的解释道歉,但我对此也很陌生:-)我相信其他人会提供更好的答案,但这应该让你开始。

这是一个很好的教程https://www.pyimagesearch.com/2018/12/24/how-to-use-keras-fit-and-fit_generator-a-hands-on-tutorial/

还有一个很短的https://medium.com/@fromtheast/implement-fit-generator-in-keras-61aa2786ce98

另外,请查看文档 https://keras.io/models/sequential/

最后这是我在当前项目中使用的一个。它不是很漂亮,但效果很好

def batch_generator(X_train, Y_train):  

    while True:
         # samples_counter = 0
        for fl, lb in zip(X_train, Y_train):
            sam, lam = get_IQsamples(fl, lb)
            max_iter = sam.shape[0]
            sample = []  # store all the generated data batches
            label = [] # store all the generated label batches
            i = 0
            for d, l in zip(sam, lam):
                sample.append(d)
                label.append(l)
                i += 1
                if i == max_iter:
                    break
            sample = np.asarray(sample)        
            label = np.asarray(label)
            yield sample, label

现在在我的手机上,但您应该将批量大小设置为特定大小。生成器将继续传递批次。假设您的批量大小是 32,但您的样本几乎用完了,只剩下 20 个。生成器将传回一个部分已满的批次,这很好。其他人将不得不回答每个批次都不同的问题,但我想不出你想要什么。