【问题标题】:How do I combine two keras generator functions如何组合两个 keras 生成器功能
【发布时间】:2018-03-01 00:16:25
【问题描述】:

我正在尝试在 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

【问题讨论】:

    标签: python neural-network computer-vision keras


    【解决方案1】:

    使用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】:

      您需要首先使用流方法将它们转换为可迭代的东西。

      尝试以下方法:

      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)
      

      【讨论】:

        【解决方案3】:

        虽然提供的答案效果很好,但如果您想将自己置于线程安全的多处理装置中,您需要实现一个 Sequence 来合并 2 个生成器。

        
        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)
        

        我认为在这种情况下它并没有太大的区别,因为数据已经在内存中。这必须经过测试。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-24
          • 2019-04-04
          • 1970-01-01
          • 2013-03-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多