【问题标题】:How to improve model to prevent overfitting for very simple image classification如何改进模型以防止过度拟合非常简单的图像分类
【发布时间】:2020-03-23 12:19:32
【问题描述】:

首先:我是 TensorFlow(版本 2)的初学者。我通过阅读学到了很多东西。但是,我似乎没有找到以下问题的答案。

我正在尝试构建一个模型,用于将图像分类为三个标签。 正如您在下面的图表中看到的,我的训练准确度还不错,但验证准确度太低了。

据我了解,这可能是一个“过度拟合”问题。

也许我会先解释一下我要做什么:

我想使用图像作为输入。作为输出,我希望接收属于这些图像的零个或多个标签(分类器)。 我期待这将是一项简单的任务,因为输入图像很简单。 (只有两种颜色,只有 0、1、2 或 3 个可能的“标签”。 以下是图像的一些示例。它们是田野(以蓝色多边形为界)上的步行轨迹(绿色)的表示:

可能的标签有:

  1. 十字:(前 2 张图片):您可以清楚地看到绿线正在形成一个或多个“十字”
  2. zig-zag:(第三张图片):不完全确定这是否是正确的英文术语,但我想你明白了 ;-)
  3. 行:绿线大多是平行线(没有锯齿形,也没有交叉)
  4. 以上都不是(不知道这是否需要标签)

我正在使用以下模型:

batch_size = 128
epochs = 30
IMG_HEIGHT = 150
IMG_WIDTH = 150

model = Sequential([
    Conv2D(16, 3, padding='same', activation='relu', 
           input_shape=(IMG_HEIGHT, IMG_WIDTH ,3)),
    MaxPooling2D(),
    Dropout(0.2),
    Conv2D(32, 3, padding='same', activation='relu'),
    MaxPooling2D(),
    Conv2D(64, 3, padding='same', activation='relu'),
    MaxPooling2D(),
    Dropout(0.2),
    Flatten(),
    Dense(512, activation='relu'),
    Dense(1, activation='sigmoid')
])



model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])


model.summary()

Model: "sequential_5"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_15 (Conv2D)           (None, 150, 150, 16)      448       
_________________________________________________________________
max_pooling2d_15 (MaxPooling (None, 75, 75, 16)        0         
_________________________________________________________________
dropout_10 (Dropout)         (None, 75, 75, 16)        0         
_________________________________________________________________
conv2d_16 (Conv2D)           (None, 75, 75, 32)        4640      
_________________________________________________________________
max_pooling2d_16 (MaxPooling (None, 37, 37, 32)        0         
_________________________________________________________________
conv2d_17 (Conv2D)           (None, 37, 37, 64)        18496     
_________________________________________________________________
max_pooling2d_17 (MaxPooling (None, 18, 18, 64)        0         
_________________________________________________________________
dropout_11 (Dropout)         (None, 18, 18, 64)        0         
_________________________________________________________________
flatten_5 (Flatten)          (None, 20736)             0         
_________________________________________________________________
dense_10 (Dense)             (None, 512)               10617344  
_________________________________________________________________
dense_11 (Dense)             (None, 3)                 1539      
=================================================================
Total params: 10,642,467
Trainable params: 10,642,467
Non-trainable params: 0

我使用 3360 张图像作为训练数据集,使用 496 张作为验证数据集。 这些已经“增强”,因此这些集合包含其他现有图像的已旋转和镜像版本。

也许值得一提的是数据集是不平衡的:80% 的图像确实包含标签“cross”,而另外 20% 被“zig-zag”和“rows”覆盖。

任何人都可以指导我如何改进我的模型?

【问题讨论】:

  • 您可以尝试更高的辍学率。另外,我坚持使用tf.keras.layers.LeakyReLU 层。
  • 使用较高的 Dropout 率不会提高验证准确性。使用 LeakyReLU 似乎不起作用:给出错误:对象没有属性“形状”

标签: tensorflow google-colaboratory tensorflow2.0


【解决方案1】:

您希望网络输出 3 个可能的标签,因此模型中的最后一层应该能够做到这一点。在实践中,您可以将其更改为Dense(3, activation='sigmoid')

我不知道为什么它在训练期间没有给你任何错误,但你也应该检查你向网络提供输入和标签的方式。

【讨论】:

  • 我认为模型确实有问题。将最后一层更改为 Dense(3, activation='sigmoid' 在训练期间确实给我一个错误:ValueError: A target array with shape (128, 1) was passed for an output of shape (None, 3) while using as loss binary_crossentropy
  • 我已经添加了模型摘要,它可能会提供更多信息。 (最后一层设置为 3,但确实会产生训练错误)
  • 从您得到的错误看来,问题在于您如何构建目标。单个输入的标签应采用 [0, 1, 0] 的形式,因此对于大小为 k 的批次,目标数组的形状应为 (k, 3)。还要使用更小的密集层; 64 应该是一个很好的起点。
  • 您的评论将医学引向了正确的方向。我的训练数据是用 class_mode='binary' 加载的,而在我的情况下必须使用 'categorical'。此外,使用(小得多)但平衡的数据集给了我更好的结果。
猜你喜欢
  • 2021-05-12
  • 1970-01-01
  • 2020-08-15
  • 2020-08-12
  • 1970-01-01
  • 2015-05-20
  • 2018-12-23
  • 2019-06-06
  • 2021-02-22
相关资源
最近更新 更多