Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 克拉斯'`model.fit_generator()`的行为与model.fit()不同`_Python_Keras_Generator - Fatal编程技术网

Python 克拉斯'`model.fit_generator()`的行为与model.fit()不同`

Python 克拉斯'`model.fit_generator()`的行为与model.fit()不同`,python,keras,generator,Python,Keras,Generator,我有一个巨大的数据集,我需要以生成器的形式提供给Keras,因为它不适合内存。但是,使用时,我无法复制使用model.fit进行常规培训时得到的结果。而且,每个时代持续的时间相当长 我实现了一个最小的示例。也许有人能告诉我问题出在哪里 import random import numpy from keras.layers import Dense from keras.models import Sequential random.seed(23465298) numpy.random.s

我有一个巨大的数据集,我需要以生成器的形式提供给Keras,因为它不适合内存。但是,使用时,我无法复制使用
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
在我的电脑上,
model.fit
总是以
0.6939
的损耗完成第十个纪元,大约2-3秒后

然而,方法
model.fit_generator
运行的时间要长得多,最后一个历元的损耗也不同(
0.6931

我不明白为什么两种方法的结果都不同。这看起来可能没有多大区别,但我需要确保使用相同网络的相同数据产生相同的结果,独立于常规训练或使用生成器。


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

我不明白批量越大,损失越不稳定,因为批量越大,波动越小。但是,看看下面的
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)
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)
它具有默认的
batch_size=32
epochs=10
。当
fit\u generator()
看起来像:

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)
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)
具体而言,“每一个历元的步长”定义如下:

每_历元的步骤数:要产生的步骤总数(样本批次) 在宣布一个历元结束并启动 下一个时代。它通常应等于唯一的 数据集的样本数除以批量大小


对于初学者来说,与fit()例程相比,fit_生成器接收的样本数量要多得多

批量大小

  • fit
    中,您使用的是标准批量大小=32
  • fit_generator
    中,您使用的批大小为10
Keras可能会在每个批次之后运行权重更新,因此,如果您使用的批次大小不同,则有可能在两种方法之间获得不同的梯度。一旦有了不同的重量更新,这两种型号将永远不会再见面

尝试将fit与
批次大小=10
配合使用,或使用
批次大小=32
的生成器


种子问题?

您是否正在为每种情况创建一个新模型,并使用
get\u model()

如果是这样的话,两个模型中的权重是不同的,当然,两个模型的结果也会不同。(好的,您已经设定了一个种子,但是如果您使用tensorflow,可能您面临的是)

不过,从长远来看,它们会有点趋同。两者之间的差别似乎不大


检查数据

如果您不确定生成器生成的数据是否与预期的相同,请对其进行简单循环,然后打印/比较/检查生成的数据:

for i in range(numberOfBatches):
    x,y = g.next() #or next(g)
    #print or compare x,y here. 


至于损失,这可能是由于已经讨论过的批量差异造成的


至于培训时间的差异,
model.fit\u generator()
允许您指定“工人”的数量。此参数表示同时在数据集中的不同区域中训练的模型实例数量。如果您的计算机体系结构得到了正确的优化,您应该能够将workers参数更改为4或8,并可以看到培训时间的大幅减少

希望我参加聚会没有迟到。我要补充的最重要的一点是:

在Keras中,对于可以加载到内存中的较小数据集,可以使用。对于大多数实际用例,几乎所有的数据集都很大,不能一次加载到内存中


对于较大的数据集,我们必须使用
fit_generator()

确保在生成器中对批进行无序排列


此讨论建议您在迭代器中启用shuffle:。我也遇到了同样的问题,这就解决了。

fit和
fit.generator
之间的区别远远超出了人们的想象。
无论如何,这两个功能都是可以互换的,不管Keras团队希望你相信什么。它们更新渐变的方式可能是其不同行为的原因


无论如何,由于神经网络的本质现实生活中的问题,使用
fit()
是徒劳的。如果您的问题可以使用
fit()
解决,那么它要么属于教室,要么属于测试运行。否则,您可能需要更多的数据收集。

确保生成器每次实际返回不同的批。我的发电机遇到了这个问题。 当您在
while
循环之前初始化批处理numpy占位符时,即使您可能在
for
循环中更改这些变量,初始化的变量也可能在第一个for循环中只更改一次。我的问题就是这样。我有一个结构类似的生成器,但我在
for
循环之后返回批次:

您可以使用此代码段检查生成器是否工作,该代码段检查生成的所有批次是否确实不同:

g = data_gen(input_data, target_data, batch_size=10)
input_list = []
target_list = []
for _ in range(100):
    input, target = next(g)
    input_list.append(input)
    target_list.append(target)
inputs = np.concatenate(input_list, axis=0)   
targets = np.concatenate(target_list, axis=0)

all_different = True
for i in range(1, inputs.shape[0]):
    if np.array_equal(inputs[0], inputs[i]):
        all_different = False
print('All batches different') if all_different else print('Generator broken. Initialize your numpy arrays inside the while loop or yield input.copy, target.copy()')

我认为你在一个面向Python编程的网站上可能会更好。你的培训数据集有多大?如果在fit generator中增加批大小,会发生什么情况?@AlexR。我有大约250万个例子。如果我增加批处理大小,那么损失仍然不稳定,并且仍然不同于我使用
model.fit()
@mdewey得到的损失,如果您知道在不使用Python I的情况下使用Keras的方法的话