为什么我的基本 CNN 模型没有过度拟合分割图像数据集?

问题描述 投票:0回答:1

我有一个 2000x256x256x3 RGB 图像(包含紫色/蓝色细胞核的粉红色组织)的数据集和大小为 200x256x256x1 的相应地面实况。地面实况图像是二值的。现在,这是我的模型(Tensorflow 版本 1.x 和 Keras):

def createFCNSameWidthModel(is1,fn,dpth,ksze,dm):
  input_shape=is1
  filter_num=fn
  depth=dpth
  ksize=ksze
  dim=dm

  import math
  from keras import backend as K
  def gelu(x):
    constant=math.sqrt(2*math.pi)
    return 0.5*x*(1+K.tanh(constant*(x+0.044715*K.pow(x,3))))

  _input=Input(shape=(input_shape,input_shape,dim))
  batch1=BatchNormalization()(_input)
  prev=batch1
  for i in range(0,depth):
    conv=Conv2D(filters=filter_num,kernel_size=ksize,padding='same',activation=gelu)(prev)
    #maxpool=MaxPooling2D(strides=(1,1))(conv)
    #batch=BatchNormalization()(conv)
    prev=conv

  _output=Conv2D(filters=1,kernel_size=3,padding='same',activation='sigmoid')(prev)

  model=Model(inputs=_input,outputs=_output)
  model.summary()
  return model

我正在使用名为 GeLU 的自定义激活来隐藏卷积层。

型号总结:

[Run:AI] [DEBUG   ] [12-01-2021 18:48:01.575] [71] [optimizers.py          :16  ] Wrapping 'Adam' Keras optimizer with GA of 4 steps

Model: "model_58"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_62 (InputLayer)        (None, 256, 256, 3)       0         
_________________________________________________________________
batch_normalization_78 (Batc (None, 256, 256, 3)       12        
_________________________________________________________________
conv2d_964 (Conv2D)          (None, 256, 256, 16)      1216      
_________________________________________________________________
conv2d_965 (Conv2D)          (None, 256, 256, 16)      6416      
_________________________________________________________________
conv2d_966 (Conv2D)          (None, 256, 256, 16)      6416      
_________________________________________________________________
conv2d_967 (Conv2D)          (None, 256, 256, 16)      6416      
_________________________________________________________________
conv2d_968 (Conv2D)          (None, 256, 256, 16)      6416      
_________________________________________________________________
conv2d_969 (Conv2D)          (None, 256, 256, 16)      6416      
_________________________________________________________________
conv2d_970 (Conv2D)          (None, 256, 256, 16)      6416      
_________________________________________________________________
conv2d_971 (Conv2D)          (None, 256, 256, 16)      6416      
_________________________________________________________________
conv2d_972 (Conv2D)          (None, 256, 256, 16)      6416      
_________________________________________________________________
conv2d_973 (Conv2D)          (None, 256, 256, 16)      6416      
_________________________________________________________________
conv2d_974 (Conv2D)          (None, 256, 256, 16)      6416      
_________________________________________________________________
conv2d_975 (Conv2D)          (None, 256, 256, 16)      6416      
_________________________________________________________________
conv2d_976 (Conv2D)          (None, 256, 256, 16)      6416      
_________________________________________________________________
conv2d_977 (Conv2D)          (None, 256, 256, 16)      6416      
_________________________________________________________________
conv2d_978 (Conv2D)          (None, 256, 256, 16)      6416      
_________________________________________________________________
conv2d_979 (Conv2D)          (None, 256, 256, 16)      6416      
_________________________________________________________________
conv2d_980 (Conv2D)          (None, 256, 256, 1)       145       
=================================================================
Total params: 97,613
Trainable params: 97,607
Non-trainable params: 6
_________________________________________________________________
Effective batch size: 16

我想要实现的目标:我正在获取数据集的一个子集(64张具有真实数据的图像)并尝试过度拟合模型以查看我的模型是否正常工作。

问题:模型没有过度拟合数据集(从现在开始,数据集意味着仅包含 64 张图像的数据集),并且如果模型过度拟合/占用数据集,损失将稳定在一个不可预期的值。

规格:

  1. Optimizer = Adam(learning_rate=0.001),发现 0.001 可以快速减少损失(在 10 个时期内)。
  2. 梯度累加 = Adam 被包裹在 runai 包装器中以进行梯度累加。这是由于 GPU 内存限制造成的。
  3. 损失函数=我使用了Dice系数损失,但我发现它本质上是非凸的(论文:语义分割损失函数的调查),因此我使用了logcosh(dice损失)。我观察到的指标是准确度、Dice 系数和 Jaccard 指数
  4. 批量大小 = 我发现最佳批量大小为 16。请注意,这是有效批量大小,即更新梯度的批量大小。

相关代码:

import tensorflow as tf
from keras import backend as K

def jaccard_index_iou(y_true,y_pred,smooth=1):
  intersection = K.sum(K.abs(y_true * y_pred), axis=[1,2]) # y_pred is mXrXcX1 (axis=0,1,2,3), we want only axis 1 and 2
  union = K.sum(y_true,axis=[1,2])+K.sum(y_pred,axis=[1,2])-intersection
  iou = K.mean((intersection + smooth) / (union + smooth), axis=0)
  return iou

def dice_coef_f1(y_true, y_pred, smooth=1):
  intersection = K.sum(y_true * y_pred, axis=[1,2])
  union = K.sum(y_true,axis=[1,2]) + K.sum(y_pred, axis=[1,2])
  dice = K.mean((2. * intersection + smooth)/(union + smooth), axis=0)
  return dice

def logcoshDice(y_true,y_pred):
  dice=dice_coef_f1(y_true,y_pred)
  diceloss=1-dice
  return K.log((K.exp(diceloss)+K.exp(-diceloss))/2.0) # log of cosh of dice loss

model=createFCNSameWidthModel(is1=256,fn=16,dpth=16,ksze=5,dm=3)
import runai.ga.keras as rgk
bs=4
my_steps=4
my_optimizer=Adam(learning_rate=0.001)
my_optimizer=rgk.optimizers.Optimizer(my_optimizer,steps=my_steps)
print("Effective batch size:",my_steps*bs)
model.compile(optimizer=my_optimizer,loss=logcoshDice,metrics=['acc',dice_coef_f1,jaccard_index_iou])
  1. 数据集存在于形状为 64,256,256,3(图像)的 numpy 数组中,地面实况为 64,256,256,1(Gt)。图像数据集在通过 BatchNormalization 层时未进行标准化。

  2. 培训:

相关代码:

history=model.fit(X_data,Y_data,validation_data(X_val,Y_val),batch_size=bs,epochs=50)

结果: 损失和 Dice 系数趋于稳定。这不应该在过度拟合中发生。

graphs

我尝试过的:

  1. 使用优化器(Adam、SGD)、批量大小、学习率、纪元 -> 没有效果
  2. 玩学习率调度,reduceLRPlateau,EarlyStopping->没有效果
  3. 使用模型宽度、深度、内核大小 -> 16 宽度和深度给出上述性能。我发现增加宽度或深度会进一步降低性能。内核大小 5 可提供最佳性能。
  4. 使用不同的损失函数 -> Dice 损失、log IoU 损失、logcoshloss、BCE、BCE+Dice 损失、灵敏度-特异性损失、Tversky 损失、Focal tversyky 损失 -> logcosh(dice 损失) 给出了最好的减少,但最终出现平台期.

根据通用近似定理,我的模型深度不足以记住这个小数据集吗?如果不学习,它至少应该过度拟合。我现在已经掌握了调试知识,迫切需要帮助才能继续前进。

我还怀疑问题可能是我的数据集太难让模型学习?但不能过拟合吗?因此,这是一个示例数据集图像(右侧为真实情况):

dataset example

python keras conv-neural-network image-segmentation overfitting-underfitting
1个回答
0
投票

您应该考虑几种不同的方法来处理 CNN 模型不按预期过度拟合的问题。首先尝试众所周知的分割架构,例如 U-Net 或 SegNet link,它们是专门为处理分割任务而设计的。接下来,调整内核大小、滤波器大小和模型深度等超参数,因为较小的模型在某些情况下可能更容易过度拟合。此外,尝试使用 Dice 损失以外的不同损失函数,例如焦点损失或 Dice 损失和二元交叉熵的组合,以确定哪一个最适合您的目的。使用“增强技术”来增加数据可变性还可以提高模型泛化性并鼓励过度拟合。使用查找器或学习率计划可以帮助避免停滞并提高训练效率。如果可行,请使用更大的数据集子集来确认结果,以观察过度拟合是否变得更加明显。最后检查数据和预处理程序的质量,以确保不存在阻碍模型学习的问题。

© www.soinside.com 2019 - 2024. All rights reserved.