首页 > 解决方案 > 无法减少语义分割(UNET)的损失,平均 IOU 也没有改善

问题描述

我们正在使用灰度眼睛图像和眼睛虹膜的基本事实来训练 CNN 来分割虹膜。我们的数据集有大约 2000 张带有相应掩码的图像,大小均为 224x224。

我们使用了 UNET 架构,如下面的代码所示。为了确保我们的网络正常工作,我们试图将网络过度拟合到我们数据集的 30 张图像上。

我们使用了骰子损失函数(mean_iou 约为 0.80),但在火车图像上进行测试时,结果很差。它显示的白色像素比地面实况更多。我们尝试了几个优化器(Adam、SGD、RMsprop),没有显着差异。

我们在最后两个 Conv2D 层中移除了激活函数,这改善了 mean_iou 和 dice 损失,但我们仍然遇到了相同的白色像素污迹问题(错误地预测了白色像素的存在),但它比以前少了。

然后,我们使用 Tversky 损失函数来消除误报(尝试几个 alpha 和 beta 值。)结果有所改善,但在训练图像上进行测试时,网络预测并不准确。

我们还添加了一个回调来在损失不变时降低学习率,这略微改善了结果。

在进行之前的运行时,我们尝试一次运行 50 个 epoch,我们将达到损失不再减少的点,大约为 (0.1) 和 mean_iou=0.9。无论多少个纪元,都不会变得更好,只会波动。学习率很低(0.00001),回调会将其降低到 1x10^-8,但仍然没有进一步减少损失。

如果有人有这方面的经验或可以为我们提供有关如何克服此问题的任何见解,我们将不胜感激。



def conv2d_block(input_tensor, n_filters, kernel_size=3, batchnorm=True):
    # first layer
    x = Conv2D(filters=n_filters, kernel_size=(kernel_size, kernel_size), kernel_initializer="he_normal",
               padding="same")(input_tensor)
    if batchnorm:
        x = BatchNormalization()(x)
        x = Activation("relu")(x)
    # second layer
    x = Conv2D(filters=n_filters, kernel_size=(kernel_size, kernel_size), kernel_initializer="he_normal",
               padding="same")(x)
    if batchnorm:
        x = BatchNormalization()(x)
        x = Activation("relu")(x)
    return x



def get_unet(input_img, n_filters=16, dropout=0.5, batchnorm=False):
    # contracting path
    c1 = conv2d_block(input_img, n_filters=n_filters*1, kernel_size=3, batchnorm=batchnorm)
    p1 = MaxPooling2D((2, 2)) (c1)
    p1 = Dropout(dropout*0.5)(p1)

    c2 = conv2d_block(p1, n_filters=n_filters*2, kernel_size=3, batchnorm=batchnorm)
    p2 = MaxPooling2D((2, 2)) (c2)
    p2 = Dropout(dropout)(p2)

    c3 = conv2d_block(p2, n_filters=n_filters*4, kernel_size=3, batchnorm=batchnorm)
    p3 = MaxPooling2D((2, 2)) (c3)
    p3 = Dropout(dropout)(p3)

    c4 = conv2d_block(p3, n_filters=n_filters*8, kernel_size=3, batchnorm=batchnorm)
    p4 = MaxPooling2D(pool_size=(2, 2)) (c4)
    p4 = Dropout(dropout)(p4)

    c5 = conv2d_block(p4, n_filters=n_filters*16, kernel_size=3, batchnorm=batchnorm)

    # expansive path
    u6 = Conv2DTranspose(n_filters*8, (3, 3), strides=(2, 2), padding='same') (c5)
    u6 = concatenate([u6, c4])
    u6 = Dropout(dropout)(u6)
    c6 = conv2d_block(u6, n_filters=n_filters*8, kernel_size=3, batchnorm=batchnorm)

    u7 = Conv2DTranspose(n_filters*4, (3, 3), strides=(2, 2), padding='same') (c6)
    u7 = concatenate([u7, c3])
    u7 = Dropout(dropout)(u7)
    c7 = conv2d_block(u7, n_filters=n_filters*4, kernel_size=3, batchnorm=batchnorm)

    u8 = Conv2DTranspose(n_filters*2, (3, 3), strides=(2, 2), padding='same') (c7)
    u8 = concatenate([u8, c2])
    u8 = Dropout(dropout)(u8)
    c8 = conv2d_block(u8, n_filters=n_filters*2, kernel_size=3, batchnorm=False)

    u9 = Conv2DTranspose(n_filters*1, (3, 3), strides=(2, 2), padding='same') (c8)
    u9 = concatenate([u9, c1], axis=3)
    u9 = Dropout(dropout)(u9)
    c9 = conv2d_block(u9, n_filters=n_filters*1, kernel_size=3, batchnorm=False)

    outputs = Conv2D(1, (1, 1), activation='sigmoid') (c9)
    model = Model(inputs=[input_img], outputs=[outputs])
    return model

标签: tensorflowkerascomputer-visionconv-neural-networksemantic-segmentation

解决方案


推荐阅读