Keras 方法 image_dataset_from_directory() 如何区分 X 和 Y 数据?

Posted

技术标签:

【中文标题】Keras 方法 image_dataset_from_directory() 如何区分 X 和 Y 数据?【英文标题】:How does the Keras method image_dataset_from_directory() distinguish X and Y data? 【发布时间】:2022-01-18 20:51:21 【问题描述】:

我正在使用 ADE20K 数据集来训练一个类似 Unet 的模型,以便在 Keras 中进行分割。

数据集有超过 1000 个类。我正在尝试使用 Keras 方法image_dataset_from_directory() 将数据集加载到tf.dataset 对象中。

以下文档向您展示了如何加载此数据集对象并将其传递到您的模型中:https://keras.io/api/preprocessing/

# directory for training data
training_data/
...class_a/
......a_image_1.jpg
......a_image_2.jpg
...class_b/
......b_image_1.jpg
......b_image_2.jpg
etc.


from tensorflow import keras
from tensorflow.keras.preprocessing import image_dataset_from_directory

train_ds = image_dataset_from_directory(
    directory='training_data/',
    labels='inferred',
    label_mode='categorical',
    batch_size=32,
    image_size=(256, 256))
validation_ds = image_dataset_from_directory(
    directory='validation_data/',
    labels='inferred',
    label_mode='categorical',
    batch_size=32,
    image_size=(256, 256))

model = keras.applications.Xception(weights=None, input_shape=(256, 256, 3), classes=10)
model.compile(optimizer='rmsprop', loss='categorical_crossentropy')
model.fit(train_ds, epochs=10, validation_data=validation_ds)

在上面的示例中,它基于提供的文件夹结构构建了一个数据集对象,其中每个类都是目录中的一个文件夹。就我而言,我有一个这样的目录:

ADE20k_Data/
...cars/
......image_1.jpg
......image_1_segmentation.png
......image_2.jpg
......image_2_segmentation.png
...resteraunt/
......image_1.jpg
......image_1_segmentation.png
......image_2.jpg
......image_2_segmentation.png
etc.

在每个类文件夹中,我都有 X 和 Y(或原始图像和分段图像)。

如果我按照上面的例子加载我的数据集,并将其传递给.fit()方法,X和Y是如何区分的?

我想这就是我的困惑所在。如何正确安排图像分割的数据目录结构。

【问题讨论】:

【参考方案1】:

您使用它的方式将准备数据用于分类,而不是用于分割。它将使用图像作为 X 和“resteraunt”、“汽车”作为标签在 Y 中进行分类。

我建议你创建自己的 tf.Dataset

考虑到您的文件夹结构并假设您的所有图像都是“*.jpg”并且每个图像都有一个“*_segmentation.png”对,您可以使用以下代码查找所有图像和相应的分割掩码。

import glob
jpgs = glob.glob('ADE20k_Data/*/*.jpg')
pngs = [f.split('.jpg')[0] + "_segmentation" + ".png" for f in jpgs]

然后您可以根据这些数据创建您的数据集

import tensorflow as tf
dataset = tf.data.Dataset.from_tensor_slices((jpgs, pngs))

此时如果你想做类似的事情

for pair in dataset.take(1):
    print(pair)

它会给你一对张量,第一个包含图像的路径,第二个包含对应分割掩码的路径。

您还可以从路径中读取图像,例如这样

def read_images(img_path, segmentation_mask_path):
    img_data = tf.io.read_file(img_path)
    img = tf.io.decode_jpeg(img_data)
    
    segm_data = tf.io.read_file(segmentation_mask_path)
    segm_mask = tf.io.decode_png(segm_data)
    
    return img, segm_mask

dataset = dataset.map(read_images)

接下来你可以为你的模型做一些预处理

HEIGHT = 256
WIDTH = 256

def prepare_images(img, semg_mask):
    img = tf.image.resize(img, [HEIGHT, WIDTH])
    semg_mask = tf.image.resize(semg_mask, [HEIGHT, WIDTH], method='nearest')
    return img, semg_mask


dataset = dataset.map(prepare_images)

此时,如果您要从数据集中获取一个实例

for pair in dataset.take(1):
    print(pair)

它会给你一对张量,第一个包含输入图像,第二个包含分割掩码作为你的输出。

显然,您还需要很多其他的东西,例如选择正确的网络架构、标准化输入图像(只需将 img 除以 255)、将数据集拆分为训练/验证/测试、打乱训练数据、批处理。但是您可以使用 tf.data api 来实现这一点,例如 dataset = dataset.batch(batch_size) 将根据您的模型需要批量生成 X 和 Y。 https://www.tensorflow.org/api_docs/python/tf/data/Dataset

然后就像你已经做的那样将你的数据集传递给 fit 方法 model.fit(daseset, epoches=10)

【讨论】:

以上是关于Keras 方法 image_dataset_from_directory() 如何区分 X 和 Y 数据?的主要内容,如果未能解决你的问题,请参考以下文章

Tensorflow+Keras用Tensorflow.keras的方法替代keras.layers.merge

在keras上使用gpu的方法

keras 中的 preprocess_input() 方法

keras中的keras.utils.to_categorical方法

Keras - 没有停止和恢复训练的好方法?

《Keras:》