如何检查 Keras 的flow_from_directory方法处理文件夹的顺序?



在进行迁移学习时,我首先通过VGG16网络的底层馈送图像。我正在使用生成器功能。

datagen = ImageDataGenerator(1./255)
generator = datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_width, img_height),
    batch_size = 32,
    class_mode=None,
    shuffle=False
)
model.predict_generator(generator, nb_train_samples)

我将类模式设置为 none,因为我只想要数据输出。我设置 shuffle = false,因为我想稍后在此处提供预测特征,并将它们与真实值类别变量匹配:

train_data = np.lead(open(file_name, 'rb'))
train_labels = np.array([0] * NUMBER_OF_ITEMS_FOR_ITEM1 +
                        [1] * NUMBER_OF_ITEMS_FOR_ITEM2 +...
                        [n-1] * NUMBER_OF_ITEMS_FOR_ITEMN

这里的问题是我不知道文件的读取顺序。我怎样才能找到它?或者更好的是,我怎样才能避免猜测正确的顺序?我之所以问,是因为我几乎可以肯定,低预测准确性与标签不匹配有关。

我查看了源代码。我应该注意,自从我发布这个问题以来,Keras 已更新到 2.0 版。所以答案是基于那个版本。

ImageDataGenerator 继承自 DirectoryGenerator。在其中,我找到了以下几行:

    if not classes:
        classes = []
        for subdir in sorted(os.listdir(directory)):
            if os.path.isdir(os.path.join(directory, subdir)):
                classes.append(subdir)
    self.num_class = len(classes)
    self.class_indices = dict(zip(classes, range(len(classes))))
    def _recursive_list(subpath):
        return sorted(os.walk(subpath, followlinks=follow_links), key=lambda tpl: tpl[0])
    for subdir in classes:
        subpath = os.path.join(directory, subdir)
        for root, _, files in _recursive_list(subpath):
            for fname in files:
                is_valid = False
                for extension in white_list_formats:
                    if fname.lower().endswith('.' + extension):
                        is_valid = True
                        break
                if is_valid:
                    self.samples += 1
    print('Found %d images belonging to %d classes.' % (self.samples, self.num_class))

请注意第 3 行,其中显示"sorted(os.listdir(direcectory, subdir(("。生成器按字母顺序遍历所有文件夹。

稍后,_recursive_list的定义也在子结构上使用相同的逻辑。

所以答案是:文件夹按字母顺序处理,这在某种程度上是有意义的。

好问题,在 DirectoryIterator 类内部的 next 方法中的keras/preprocessing/image.py中添加一个 print 语句: 下面是迭代文件名列表的相关代码。当然,您必须从源代码重建keras

for i, j in enumerate(index_array):
   fname = self.filenames[j]
   print(fname) # add this to see the current file being accessed
   img = load_img(os.path.join(self.directory, fname),
                  grayscale=grayscale,
                  target_size=self.target_size)
   x = img_to_array(img, data_format=self.data_format)
   x = self.image_data_generator.random_transform(x)

但是,为了避免所有这些痛苦,keras 文档页面上的此示例建议确保一致性,应遵循此模式。将同一模板的训练和验证生成器传递给model.fit_generator函数。

train_datagen = ImageDataGenerator(
        rescale=1./255,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
        'data/train',
        target_size=(150, 150),
        batch_size=32,
        class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
        'data/validation',
        target_size=(150, 150),
        batch_size=32,
        class_mode='binary')
model.fit_generator(
        train_generator,
        samples_per_epoch=2000,
        epochs=50,
        validation_data=validation_generator,
        num_val_samples=800)

最新更新