使用 CNN 进行语义分割的训练数据维度
Training data dimensions for semantic segmentation using CNN
我在 Python.
中尝试将 CNN (U-Net) 拟合到我的 tif 训练图像时遇到了很多困难
我的数据结构如下:
- X
-
- 0
-
-
- [Images] (tif, 3-band, 128x128, values ∈ [0, 255])
- X_val
-
- 0
-
-
- [Images] (tif, 3-band, 128x128, values ∈ [0, 255])
- y
-
- 0
-
-
- [Images] (tif, 1-band, 128x128, values ∈ [0, 255])
- y_val
-
- 0
-
-
- [Images] (tif, 1-band, 128x128, values ∈ [0, 255])
从这些数据开始,我定义了 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
。对于该集合,X
和 y
中的第二个数组都不是由 ImageDataGenerator
写入的。结果,X 和 y 被解释为组合 ImageDataGenerator
中的数据和掩码(这是我们想要的)。否则,X_val_gen
已经生成了屏幕截图中显示的元组,其中第二个条目被解释为 class,这在图像散布在各个文件夹中的 class 化问题中是有意义的每个都标有 class ID。
我在 Python.
中尝试将 CNN (U-Net) 拟合到我的 tif 训练图像时遇到了很多困难我的数据结构如下:
- X
-
- 0
-
-
- [Images] (tif, 3-band, 128x128, values ∈ [0, 255])
-
- X_val
-
- 0
-
-
- [Images] (tif, 3-band, 128x128, values ∈ [0, 255])
-
- y
-
- 0
-
-
- [Images] (tif, 1-band, 128x128, values ∈ [0, 255])
-
- y_val
-
- 0
-
-
- [Images] (tif, 1-band, 128x128, values ∈ [0, 255])
-
从这些数据开始,我定义了 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
。对于该集合,X
和 y
中的第二个数组都不是由 ImageDataGenerator
写入的。结果,X 和 y 被解释为组合 ImageDataGenerator
中的数据和掩码(这是我们想要的)。否则,X_val_gen
已经生成了屏幕截图中显示的元组,其中第二个条目被解释为 class,这在图像散布在各个文件夹中的 class 化问题中是有意义的每个都标有 class ID。