Keras的`model.fit_generator()`与`model.fit()`的行为不同

weh*_*lae 7 python generator keras

我有一个巨大的数据集,我需要以生成器的形式提供给Keras,因为它不适合内存.但是,使用fit_generator,我不能复制我在常规训练中得到的结果model.fit.每个时代也持续相当长的时间.

我实现了一个最小的例子.也许有人可以告诉我问题所在.

import random
import numpy

from keras.layers import Dense
from keras.models import Sequential

random.seed(23465298)
numpy.random.seed(23465298)

no_features = 5
no_examples = 1000


def get_model():
    network = Sequential()
    network.add(Dense(8, input_dim=no_features, activation='relu'))
    network.add(Dense(1, activation='sigmoid'))
    network.compile(loss='binary_crossentropy', optimizer='adam')
    return network


def get_data():
    example_input = [[float(f_i == e_i % no_features) for f_i in range(no_features)] for e_i in range(no_examples)]
    example_target = [[float(t_i % 2)] for t_i in range(no_examples)]
    return example_input, example_target


def data_gen(all_inputs, all_targets, batch_size=10):
    input_batch = numpy.zeros((batch_size, no_features))
    target_batch = numpy.zeros((batch_size, 1))
    while True:
        for example_index, each_example in enumerate(zip(all_inputs, all_targets)):
            each_input, each_target = each_example
            wrapped = example_index % batch_size
            input_batch[wrapped] = each_input
            target_batch[wrapped] = each_target
            if wrapped == batch_size - 1:
                yield input_batch, target_batch


if __name__ == "__main__":
    input_data, target_data = get_data()
    g = data_gen(input_data, target_data, batch_size=10)
    model = get_model()
    model.fit(input_data, target_data, epochs=15, batch_size=10)  # 15 * (1000 / 10) * 10
    # model.fit_generator(g, no_examples // 10, epochs=15)        # 15 * (1000 / 10) * 10
Run Code Online (Sandbox Code Playgroud)

在我的电脑上,model.fit总是完成第10个时期,失去0.6939和之后.2-3秒.

model.fit_generator然而,该方法运行时间相当长,并以不同的损失(0.6931)结束最后一个时期.

我一般不明白为什么两种方法的结果都不同.这可能看起来不是很大的区别,但我需要确保具有相同网络的相同数据产生相同的结果,独立于传统培训或使用生成器.

更新:@Alex R.为部分原始问题提供了答案(一些性能问题以及每次运行时更改结果).然而,由于核心问题仍然存在,我只是相应地调整了问题和标题.

Ale*_* R. 4

我不明白如何随着批量大小的增加,损失会变得不稳定,因为较大批量的波动应该较小。然而,查看Keras 文档fit()例程如下所示:

fit(self, x, y, batch_size=32, epochs=10, verbose=1, callbacks=None, validation_split=0.0, 
    validation_data=None, shuffle=True, class_weight=None, sample_weight=None, 
    initial_epoch=0)
Run Code Online (Sandbox Code Playgroud)

其中有一个默认值batch_size=32epochs=10. 而fit_generator()看起来像:

fit_generator(self, generator, steps_per_epoch, epochs=1, verbose=1,
              callbacks=None, validation_data=None, validation_steps=None, 
              class_weight=None, max_queue_size=10, workers=1,
              use_multiprocessing=False, initial_epoch=0)
Run Code Online (Sandbox Code Playgroud)

具体来说,“step_per_epoch”由以下方式定义:

steps_per_epoch:在声明一个纪元完成并开始下一个纪元之前从生成器生成的总步骤数(样本批次)。它通常应等于数据集的唯一样本数除以批量大小。

因此,对于初学者来说,与 fit() 例程相比,听起来您的 fit_generator 正在获取更多数量的样本。请参阅此处了解更多详细信息。