Python 克拉斯'`model.fit_generator()`的行为与model.fit()不同`
我有一个巨大的数据集,我需要以生成器的形式提供给Keras,因为它不适合内存。但是,使用时,我无法复制使用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
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_生成器接收的样本数量要多得多 批量大小
- 在
中,您使用的是标准批量大小=32李>fit
- 在
中,您使用的批大小为10李>fit_generator
批次大小=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的方法的话