我正在尝试在Keras中实现一个Siamese网络,我想使用Keras图像数据生成器将图像转换应用于2个输入图像。根据文档中的示例 - https://keras.io/preprocessing/image/,我试图像这样实现它 -
datagen_args = dict(rotation_range=10,
width_shift_range=0.1,
height_shift_range=0.1,
horizontal_flip=True)
in_gen1 = ImageDataGenerator(**datagen_args)
in_gen2 = ImageDataGenerator(**datagen_args)
train_generator = zip(in_gen1, in_gen2)
model.fit(train_generator.flow([pair_df[:, 0,::],pair_df[:, 1,::]],
y_train,batch_size=16), epochs, verbose = 1)
但是这段代码抛出了这个错误:
TypeError :zip参数#1必须支持迭代
我已按照Keras - Generator for large dataset of Images and Masks中的建议尝试使用itertools.izip
,但这会引发同样的错误。
如何解决此问题?
编辑:如果有人感兴趣,最终会有效 -
datagen_args = dict(
featurewise_center=False,
rotation_range=10,
width_shift_range=0.1,
height_shift_range=0.1,
horizontal_flip=True)
in_gen1 = ImageDataGenerator(**datagen_args)
in_gen2 = ImageDataGenerator(**datagen_args)
in_gen1 = in_gen1.flow(pair_df[:, 0,::], y_train, batch_size = 16, shuffle = False)
in_gen2 = in_gen2.flow(pair_df[:, 1,::], y_train, batch_size = 16, shuffle = False)
for e in range(epochs):
batches = 0
for x1, x2 in itertools.izip(in_gen1,in_gen2):
# x1, x2 are tuples returned by the generator, check whether targets match
assert sum(x1[1] != x2[1]) == 0
model.fit([x1[0], x2[0]], x1[1], verbose = 1)
batches +=1
if(batches >= len(pair_df)/16):
break
答案 0 :(得分:2)
您需要先使用flow方法将它们转换为可迭代的东西。
尝试以下方法:
datagen_args = dict(rotation_range=10,
width_shift_range=0.1,
height_shift_range=0.1,
horizontal_flip=True)
in_gen1 = ImageDataGenerator(**datagen_args)
in_gen2 = ImageDataGenerator(**datagen_args)
gen1_flow = in_gen1.flow(X_train[:,0, ::],y_train, batch_size=16)
gen2_flow = in_gen2.flow(X_train[:,1, ::],y_train, batch_size=16)
train_generator = zip(gen1_flow, gen2_flow)
model.fit_generator(train_generator,
steps_per_epoch=len(X_train)/16,
epochs=epochs)
答案 1 :(得分:0)
使用zip()
组合生成器会导致生成无限迭代器。
改用它:
def combine_generator(gen1, gen2):
while True:
yield(next(gen1), next(gen2))
修改后的代码如下:
datagen_args = dict(rotation_range=10,
width_shift_range=0.1,
height_shift_range=0.1,
horizontal_flip=True)
in_gen1 = ImageDataGenerator(**datagen_args)
in_gen2 = ImageDataGenerator(**datagen_args)
def combine_generator(gen1, gen2):
while True:
yield(next(gen1), next(gen2))
train_generator = combine_generator(in_gen1, in_gen2)
model.fit(train_generator.flow([pair_df[:, 0,::],pair_df[:, 1,::]],
y_train,batch_size=16), epochs, verbose = 1)
请参阅此thread,以获取更多参考。
答案 2 :(得分:0)
虽然提供的答案很好用,但是如果您想将自己置于线程安全的多处理配件中,则需要实现一个Sequence
来合并两个生成器。
from keras.utils import Sequence
class MergedGenerators(Sequence):
def __init__(self, *generators):
self.generators = generators
# TODO add a check to verify that all generators have the same length
def __len__(self):
return len(self.generators[0])
def __getitem__(self, index):
return [generator[index] for generator in self.generators]
datagen_args = dict(
featurewise_center=False,
rotation_range=10,
width_shift_range=0.1,
height_shift_range=0.1,
horizontal_flip=True)
in_gen1 = ImageDataGenerator(**datagen_args)
in_gen2 = ImageDataGenerator(**datagen_args)
in_gen1 = in_gen1.flow(pair_df[:, 0,::], y_train, batch_size = 16, shuffle = False)
in_gen2 = in_gen2.flow(pair_df[:, 1,::], y_train, batch_size = 16, shuffle = False)
train_merged_generator = MergedGenerators(in_gen1, in_gen2)
model.fit(train_merged_generator, epochs, verbose=1, use_multiprocessing=True)
我认为在这种情况下,由于数据已经在内存中,因此并没有太大的区别。这必须进行测试。