使用 U-Net 分割德国沥青路面病害数据集 (GAP)

Segmentation of German Asphalt Pavement Distress Dataset (GAPs) using U-Net

我正在尝试训练类似 U-Net 的模型来分割德国沥青路面病害数据集。

蒙版图像存储为灰度值图像。 灰度值编码:

0 = 无效,1 = 完整道路,2 = 应用补丁,3 = 坑洼,4 = 镶嵌补丁,5 = 开缝,6 = 裂缝 7 = 街道库存

我找到了以下在 Oxford pets 数据集上实现 U-Net 分割的 colab notebook: https://colab.research.google.com/github/keras-team/keras-io/blob/master/examples/vision/ipynb/oxford_pets_image_segmentation.ipynb

我修改了笔记本以适应我的 GAP 分割问题,这是 link 我修改后的笔记本: https://colab.research.google.com/drive/1YfM4lC78QNdfbkgz-1LGSKaBG4-65dkC?usp=sharing

训练是 运行,但虽然损失在减少,但准确率从未增加到 0.05 以上。我被这个问题困扰了好几天,我需要有关如何让模型正确训练的帮助。

以下是link数据集的图片和掩码: https://drive.google.com/drive/folders/1-JvLSa9b1falqEake2KVaYYtyVh-dgKY?usp=sharing

在 Sequence class 中,您不打乱批次的内容,仅使用 fit 方法打乱批次顺序。您必须在每个时期打乱所有数据的顺序。 这是在 Sequence subclass:

中执行此操作的一种方法
class OxfordPets(keras.utils.Sequence):
    """Helper to iterate over the data (as Numpy arrays)."""

    def __init__(self, batch_size, img_size, input_img_paths, target_img_paths):
        self.batch_size = batch_size
        self.img_size = img_size
        self.input_img_paths = input_img_paths
        self.target_img_paths = target_img_paths
        self.set_len = len(self.target_img_paths) // self.batch_size
        self.indices = random.sample(range(self.set_len), k=self.set_len)

    def __len__(self):
        return self.set_len

    def __getitem__(self, idx):
        """Returns tuple (input, target) correspond to batch #idx."""
        i = idx * self.batch_size
        indices = self.indices[i : i + self.batch_size]
        batch_input_img_paths = [self.input_img_paths[k] for k in indices]
        batch_target_img_paths = [self.target_img_paths[k] for k in indices]
        x = np.zeros((self.batch_size,) + self.img_size + (3,), dtype="float32")
        for j, path in enumerate(batch_input_img_paths):
            img = load_img(path, target_size=self.img_size)
            x[j] = img
        y = np.zeros((self.batch_size,) + self.img_size + (1,), dtype="uint8")
        for j, path in enumerate(batch_target_img_paths):
            img = load_img(path, target_size=self.img_size, color_mode="grayscale")
            y[j] = np.expand_dims(img, 2)
            # Ground truth labels are 1, 2, 3. Subtract one to make them 0, 1, 2:
            #y[j] -= 1 # I commented this line out because the ground truth labels of GAPs dataset are 0, 1, 2, 3, 4, 5, 6, 7
        return x, y

    def on_epoch_end(self):
      self.indices = random.sample(range(self.set_len), k=self.set_len)

self.indices 是所有索引 range(self.set_len) 的随机洗牌,它是在构造函数中和每个纪元结束时构建的。这允许打乱所有数据的顺序。

使用 rmsprop 优化器,它可以工作:

Epoch 1/15
88/88 [==============================] - 96s 1s/step - loss: 1.9617 - categorical_accuracy: 0.9156 - val_loss: 5.8705 - val_categorical_accuracy: 0.9375
Epoch 2/15
88/88 [==============================] - 93s 1s/step - loss: 0.4754 - categorical_accuracy: 0.9369 - val_loss: 1.9207 - val_categorical_accuracy: 0.9375
Epoch 3/15
88/88 [==============================] - 94s 1s/step - loss: 0.4497 - categorical_accuracy: 0.9447 - val_loss: 9.3833 - val_categorical_accuracy: 0.9375
Epoch 4/15
88/88 [==============================] - 94s 1s/step - loss: 0.3173 - categorical_accuracy: 0.9423 - val_loss: 14.2518 - val_categorical_accuracy: 0.9369
Epoch 5/15
88/88 [==============================] - 94s 1s/step - loss: 0.0645 - categorical_accuracy: 0.9400 - val_loss: 110.9821 - val_categorical_accuracy: 0.8963

请注意,很快就会出现一些过度拟合。