tensorflow - 无法减少语义分割(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
解决方案
推荐阅读
- vb.net - 变量名称“@userid2”已被声明。变量名称在查询批处理或存储过程中必须是唯一的
- php - Composer 在安装 Laravel 时显示错误
- c++ - 正确使用枚举元素
- php - 以特定格式将数据库导出为 json
- css - JavaFX progressBar不同颜色的progressBar部分
- ionic-framework - Ionic 3:内联显示离子搜索栏和离子段按钮
- laravel - Laravel MethodNotAllowedHttpException 如果请求具有 base64 图像数据
- unity3d - 着色器 - 将 PerRendererData 与数组属性一起使用
- jena - 在开发基于知识的 QA 系统时,何时需要使用像 jena 这样的推理器?
- mule-esb - Mule 中的 Http 处理程序