我有一个巨大的数据集,我需要以生成器的形式提供给Keras,因为它不适合内存。但是,使用fit_generator
,我无法复制.black {
padding: 12px 20px;
margin: 0 auto;
box-sizing: border-box;
text-align: center;
display: inline-block;
background-color: black;
color: white;
border-style: solid;
}
.white {
padding: 12px 20px;
margin: 0 auto;
box-sizing: border-box;
text-align: center;
display: inline-block;
}
常规培训期间获得的结果。每个时代也要持续更长时间。
我实现了一个最小的例子。也许有人可以告诉我问题所在。
<div id="bet-and-chance-input-boxes">
<input class="black" value="text" autocomplete="off">
<input readonly value="text" class="black" placeholder="" name="bet" autocomplete="off">
</div>
<div id="bet-and-chance-input-boxes">
<input class="white" id="userbet" value="text" autocomplete="off">
<input readonly class="white" value="text" placeholder="" name="" autocomplete="off">
</div>
在我的计算机上,model.fit
总是在第10个纪元完成时失去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
而在此之后。 2-3秒。
然而,方法model.fit
的运行时间要长得多,并且在不同损失(0.6939
)的情况下完成上一个纪元。
我一般不明白为什么两种方法的结果都不同。这可能看起来不是很大差异,但我需要确保具有相同网络的相同数据产生相同的结果,独立于传统培训或使用生成器。
更新:@Alex R.为部分原始问题提供了答案(一些性能问题以及每次运行时更改结果)。然而,由于核心问题仍然存在,我只是相应地调整了问题和标题。
答案 0 :(得分:4)
我不明白批量较大时损失是如何不稳定的,因为较大批次的波动应该较小。但是,查看Keras documentation,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)
具有默认batch_size=32
和epochs=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)
特别是&#34; step_per_epoch&#34;定义如下:
steps_per_epoch:要产生的步骤(样本批次)的总数 来自发电机,然后宣布一个纪元完成并启动 下一个时代。它通常应该等于唯一的数量 数据集的样本除以批量大小。
因此对于初学者来说,与fit()例程相比,听起来你的fit_generator正在接收大量的样本。 See here for more details.
答案 1 :(得分:2)
批量大小
fit
中,您使用的是标准批量大小= 32. fit_generator
中,您使用批量大小= 10。Keras可能会在每批次之后运行重量更新,因此,如果您使用不同大小的批次,则两种方法之间可能会出现不同的渐变。一旦有不同的重量更新,两种型号都不会再次相遇。
尝试使用batch_size=10
,或使用batch_size=32
生成器。
种子问题?
您是否为每种情况创建了一个get_model()
的新模型?
如果是这样,两个模型中的权重都不同,当然两种模型的结果都不同。 (好的,你已经设定了种子,但如果你正在使用张量流,也许你正面临this issue)
但从长远来看,他们会有所收敛。两者之间的差异似乎并不大。
检查数据
如果您不确定您的生成器是否产生与您预期相同的数据,请对其进行简单循环并打印/比较/检查它产生的数据:
for i in range(numberOfBatches):
x,y = g.next() #or next(g)
#print or compare x,y here.
答案 2 :(得分:1)
请确保在发生器中对批次进行混洗。
此讨论建议您在迭代器https://github.com/keras-team/keras/issues/2389中启用随机播放。我遇到了同样的问题,这解决了。
答案 3 :(得分:0)
至于损失,这可能是由于已经讨论过的批量差异造成的。
至于培训时间的差异,model.fit_generator()
允许您指定&#34;工人&#34;的数量。此参数指的是同时在数据集中的不同区域上训练模型的实例数。如果您的计算机体系结构已正确优化,您应该能够将workers参数更改为4或8,并且可以大幅缩短培训时间。
答案 4 :(得分:0)
希望我参加聚会不晚。我要添加的最重要的内容:
在Keras中,对于可以加载到内存中的较小数据集,使用fit()
很好。但是实际上,对于大多数实际使用的情况,几乎所有数据集都很大,无法一次加载到内存中。
对于更大的数据集,我们必须使用fit_generator()
。
答案 5 :(得分:0)
fit
和fit.generator
之间的区别不只是让人眼前一亮。无论Keras团队希望您做什么,这两种功能都是可以互换的相信。他们更新梯度的方式可能是其行为不同的原因。
无论如何,由于神经网络现实生活中的问题的性质,fit()
的使用是徒劳的。如果可以使用fit()
解决您的问题,那么它要么属于教室,要么属于试运行。否则,您可能需要更多的数据收集。
答案 6 :(得分:0)
确保每次生成器实际上返回不同的批次。我的发电机遇到了这个问题。
当您在while
循环之前初始化批处理numpy占位符时,即使您可以在for
循环中更改这些变量,也有可能初始化的变量在第一个for循环中仅更改一次。我的问题就是这样。我有一个结构类似的生成器,但是我在for
循环之后返回了批次:Why is this python generator returning the same value everytime?
您可以使用以下代码段检查生成器是否正常工作:检查所有生成的批次是否确实不同:
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()')