使用 CNN 进行语义分割的训练数据维度

Training data dimensions for semantic segmentation using CNN

我在 Python.

中尝试将 CNN (U-Net) 拟合到我的 tif 训练图像时遇到了很多困难

我的数据结构如下:

从这些数据开始,我定义了 ImageDataGenerators:

import tensorflow as tf
from tensorflow import keras as ks

    from matplotlib import pyplot as plt
    import numpy as np
    
    bs = 10 # batch size
    args_col = {"data_format" : "channels_last",
                "brightness_range" : [0.5, 1.5]
                }
    args_aug = {"rotation_range" : 365,
                "width_shift_range" : 0.05,
                "height_shift_range" : 0.05,
                "horizontal_flip" : True,
                "vertical_flip" : True,
                "fill_mode" : "constant",
                "featurewise_std_normalization" : False,
                "featurewise_center" : False
                }
    args_flow = {"color_mode" : "rgb",
                 "class_mode" : "sparse",
                 "batch_size" : bs,
                 "target_size" : (128, 128),
                 "seed" : 42
                 }
    # train generator
    X_generator = ks.preprocessing.image.ImageDataGenerator(rescale = 1.0/255.0,
                                                            **args_aug,
                                                            **args_col)
    X_gen = X_generator.flow_from_directory(directory = "my/directory/X",
                             **args_flow)
    
    y_generator = ks.preprocessing.image.ImageDataGenerator(**args_aug,
                                                            cval = NoDataValue)
    y_gen = y_generator.flow_from_directory(directory = "my/directory/y",
                             **args_flow, color_mode = "grayscale")
    
    train_generator = zip(X_gen, y_gen)
    # val generator
    X_val_generator = ks.preprocessing.image.ImageDataGenerator(rescale = 1.0/255.0)
    X_val_gen = X_generator.flow_from_directory(directory = "my/directory/X_val"),
                                 **args_flow)
    
    y_val_generator = ks.preprocessing.image.ImageDataGenerator()
    y_val_gen = y_generator.flow_from_directory(directory = "my/directory/y_val"),
                                 **args_flow, color_mode = "grayscale")
    
    val_generator = zip(X_val_gen, y_val_gen)

使用这个生成器,我可以创建成对的训练图像和相应的蒙版,并像这样可视化它们:

    X, y = next(train_generator)
    X_test = X[0][0]
    y_test = y[0][0]
    
    plt.subplot(1, 2, 1)
    plt.imshow(np.array(X_test))
    plt.subplot(1, 2, 2)
    plt.imshow(np.array(y_test))

导致:

但是,我无法按预期训练 U-Net:

当我将基于来自 Internet 的 example 的 U-Net(或基本上我发现的任何其他 U-Net 示例)定义为 model 时,然后执行以下操作:

model.compile(optimizer = "adam", loss = "sparse_categorical_crossentropy", metrics = ["accuracy"])
model.fit(train_generator, epochs = 5, steps_per_epoch = 10, validation_data = val_generator)

它将失败并出现错误:

ValueError: Layer model expects 1 input(s), but it received 2 input tensors. Inputs received: [<tf.Tensor 'IteratorGetNext:0' shape=(None, None, None, None) dtype=float32>, <tf.Tensor 'ExpandDims:0' shape=(None, 1) dtype=float32>]

我尝试了其他损失函数和其他 class_mode 参数,但它总是失败,并出现一些与输入数据的维度或层间传递的数据相关的错误。另一个例子(当设置 class_mode = None:

InvalidArgumentError:  logits and labels must have the same first dimension, got logits shape [16384,1] and labels shape [49152]

我刚开始接触 CNN 和 Python,所以我不知道该进一步尝试什么或如何解决这些错误。我很确定我使用了正确的损失函数,这似乎是发生类似错误时经常出现的问题(我有多个 类,因此 "sparse_categorical_crossentropy")。

有什么想法可以解决这个问题并使数据符合预期的 CNN 输入(或者反过来,取决于问题是什么)?

注: 我的 ImageDataGenerator 输出一对具有以下格式的图像(X 和 y)(我注意到我必须将 color_mode 设置为蒙版(y)的“灰度”):

我在示例 U-Net 中使用了 keras.layers.Input(shape = (128, 128, 3)),因为 keras documentation 状态为 shape = "A shape tuple (integers), not including the batch size".

我找到了这个特定问题的答案。在其他问题中,对于这种模型,"class_mode" 必须设置为 None。对于该集合,Xy 中的第二个数组都不是由 ImageDataGenerator 写入的。结果,X 和 y 被解释为组合 ImageDataGenerator 中的数据和掩码(这是我们想要的)。否则,X_val_gen 已经生成了屏幕截图中显示的元组,其中第二个条目被解释为 class,这在图像散布在各个文件夹中的 class 化问题中是有意义的每个都标有 class ID。