【问题标题】:Use multiple directories for flow_from_directory in Keras在 Keras 中为 flow_from_directory 使用多个目录
【发布时间】:2018-07-16 06:09:28
【问题描述】:

我的场景是我们有多个具有自己数据的对等点,位于不同的目录中,具有相同的子目录结构。我想使用这些数据训练模型,但是如果我将它们全部复制到一个文件夹中,我无法跟踪哪些数据来自谁(偶尔也会创建新数据,因此不适合保留复制文件每次) 我的数据现在是这样存储的:

-user01
-user02
-user03
...

(都有类似的子目录结构)

我已经搜索过解决方案,但我只在herehere 中找到了多输入案例,它们将多个输入连接成一个单独的并行输入,这不是我的情况。

我知道flow_from_directory() 一次只能由 1 个目录提供,那么如何构建一个可以同时由多个目录提供的自定义呢?

如果我的问题是低质量的,请指教如何改进它,我也在keras的github上搜索过,但没有找到任何我可以适应的东西。

谢谢。

【问题讨论】:

    标签: python tensorflow keras


    【解决方案1】:

    Keras ImageDataGeneratorflow_from_directory 方法有一个follow_links 参数。

    也许您可以创建一个目录,其中包含指向所有其他目录中文件的符号链接。

    这个堆栈问题讨论了在 Keras ImageDataGenerator 中使用符号链接:Understanding 'follow_links' argument in Keras's ImageDataGenerator?

    【讨论】:

      【解决方案2】:

      经过这么多天,我希望您找到了问题的解决方案, 但我将在这里分享另一个想法,以便像我这样的新人 以后遇到同样的问题,求帮助。

      几天前我遇到了这种问题。正如 user3731622 所说,follow_links 将解决您的问题。另外,我认为合并两个数据生成器的想法会奏效。但是,在这种情况下,必须根据每个相关目录中的数据范围来确定相应数据生成器的批量大小。

      子生成器的批量大小

      Where,
      b = Batch Size Of Any Sub-generator
      B = Desired Batch Size Of The Merged Generator
      n = Number Of Images In That Directory Of Sub-generator
      the sum of n = Total Number Of Images In All Directories
      

      查看下面的代码,这可能会有所帮助:

      from keras.preprocessing.image import ImageDataGenerator
      from keras.utils import Sequence
      import matplotlib.pyplot as plt
      import numpy as np
      import os
      
      
      class MergedGenerators(Sequence):
      
          def __init__(self, batch_size, generators=[], sub_batch_size=[]):
              self.generators = generators
              self.sub_batch_size = sub_batch_size
              self.batch_size = batch_size
      
          def __len__(self):
              return int(
                  sum([(len(self.generators[idx]) * self.sub_batch_size[idx])
                       for idx in range(len(self.sub_batch_size))]) /
                  self.batch_size)
      
          def __getitem__(self, index):
              """Getting items from the generators and packing them"""
      
              X_batch = []
              Y_batch = []
              for generator in self.generators:
                  if generator.class_mode is None:
                      x1 = generator[index % len(generator)]
                      X_batch = [*X_batch, *x1]
      
                  else:
                      x1, y1 = generator[index % len(generator)]
                      X_batch = [*X_batch, *x1]
                      Y_batch = [*Y_batch, *y1]
      
              if self.generators[0].class_mode is None:
                  return np.array(X_batch)
              return np.array(X_batch), np.array(Y_batch)
      
      
      def build_datagenerator(dir1=None, dir2=None, batch_size=32):
          n_images_in_dir1 = sum([len(files) for r, d, files in os.walk(dir1)])
          n_images_in_dir2 = sum([len(files) for r, d, files in os.walk(dir2)])
      
          # Have to set different batch size for two generators as number of images
          # in those two directories are not same. As we have to equalize the image
          # share in the generators
          generator1_batch_size = int((n_images_in_dir1 * batch_size) /
                                      (n_images_in_dir1 + n_images_in_dir2))
      
          generator2_batch_size = batch_size - generator1_batch_size
      
          generator1 = ImageDataGenerator(
              rescale=1. / 255,
              shear_range=0.2,
              zoom_range=0.2,
              rotation_range=5.,
              horizontal_flip=True,
          )
      
          generator2 = ImageDataGenerator(
              rescale=1. / 255,
              zoom_range=0.2,
              horizontal_flip=False,
          )
      
          # generator2 has different image augmentation attributes than generaor1
          generator1 = generator1.flow_from_directory(
              dir1,
              target_size=(128, 128),
              color_mode='rgb',
              class_mode=None,
              batch_size=generator1_batch_size,
              shuffle=True,
              seed=42,
              interpolation="bicubic",
          )
      
          generator2 = generator2.flow_from_directory(
              dir2,
              target_size=(128, 128),
              color_mode='rgb',
              class_mode=None,
              batch_size=generator2_batch_size,
              shuffle=True,
              seed=42,
              interpolation="bicubic",
          )
      
          return MergedGenerators(
              batch_size,
              generators=[generator1, generator2],
              sub_batch_size=[generator1_batch_size, generator2_batch_size])
      
      
      def test_datagen(batch_size=32):
          datagen = build_datagenerator(dir1="./asdf",
                                        dir2="./asdf2",
                                        batch_size=batch_size)
      
          print("Datagenerator length (Batch count):", len(datagen))
      
          for batch_count, image_batch in enumerate(datagen):
              if batch_count == 1:
                  break
      
              print("Images: ", image_batch.shape)
      
              plt.figure(figsize=(10, 10))
              for i in range(image_batch.shape[0]):
                  plt.subplot(1, batch_size, i + 1)
                  plt.imshow(image_batch[i], interpolation='nearest')
                  plt.axis('off')
                  plt.tight_layout()
      
      
      test_datagen(4)
      
      

      【讨论】:

        猜你喜欢
        • 2018-08-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-20
        • 2018-06-30
        • 1970-01-01
        • 2019-12-20
        • 1970-01-01
        相关资源
        最近更新 更多