【问题标题】:CNN (VGG-16) strange behaviour on validation accuracyCNN (VGG-16) 验证准确性的奇怪行为
【发布时间】:2020-10-17 17:21:28
【问题描述】:

我已经构建并测试了两个卷积神经网络模型 (VGG-16 and 3-layer CNN) 来预测 COVID-19 的肺部 CT 扫描分类。

在分类之前,我通过k-means clustering对图像进行了图像分割,试图提高分类性能。

分割后的图像如下所示。

我已经分别在分段图像和原始图像上训练和评估了 VGG-16 模型。最后,仅在分割图像上训练和评估 3 层 CNN。以下是他们的训练/验证损失和准确性的结果。

对于简单的 3 层 CNN 模型,我可以清楚地看到该模型训练得很好,并且一旦 epoch 超过 2,它就会开始过度拟合。但是,我不明白 VGG 模型的验证准确性如何t 看起来像一条指数曲线,相反它看起来像一条水平直线或波动的水平线。 此外,简单的 3 层 CNN 模型似乎表现更好。这是由于 VGG 模型中的梯度消失造成的吗?或者图像本身很简单,深度架构不会受益? 如果您能分享您对模型的这种学习行为的了解,我将不胜感激。

这是 VGG-16 模型的代码:

# build model
img_height = 256
img_width = 256

model = Sequential()
model.add(Conv2D(input_shape=(img_height,img_width,1),filters=64,kernel_size=(3,3),padding="same", activation="relu"))
model.add(Conv2D(filters=64,kernel_size=(3,3),padding="same", activation="relu"))
model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))
model.add(Conv2D(filters=128, kernel_size=(3,3), padding="same", activation="relu"))
model.add(Conv2D(filters=128, kernel_size=(3,3), padding="same", activation="relu"))
model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))
model.add(Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"))
model.add(Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"))
model.add(Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"))
model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))
model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))
model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))
model.add(Flatten())
model.add(Dense(units=4096,activation="relu"))
model.add(Dense(units=4096,activation="relu"))
model.add(Dense(units=1, activation="sigmoid"))
opt = Adam(lr=0.001)
model.compile(optimizer=opt, loss=keras.losses.binary_crossentropy, metrics=['accuracy'])

这是 3 层 CNN 的代码。

# build model
model2 = Sequential()
model2.add(Conv2D(32, 3, padding='same', activation='relu',input_shape=(img_height, img_width, 1))) 
model2.add(MaxPool2D()) 
model2.add(Conv2D(64, 5, padding='same', activation='relu'))
model2.add(MaxPool2D())
model2.add(Flatten())
model2.add(Dense(128, activation='relu'))
model2.add(Dense(1, activation='sigmoid'))
opt = Adam(lr=0.001)
model2.compile(optimizer=opt, loss=keras.losses.binary_crossentropy, metrics=['accuracy'])

谢谢!

【问题讨论】:

  • 训练/测试集大小?
  • @CAFEBABE 有 598 张训练图像和 148 张测试图像,比例为 80-20。
  • 两个班级的分布是80-20还是train test split?什么是班级分布?
  • @CAFEBABE 是 349 阳性和 397 阴性。类分布相当平衡。

标签: python machine-learning keras deep-learning neural-network


【解决方案1】:

查看假设为二元问题的准确度,您可以观察到模型只是随机猜测(acc ~ 0.5)。 您的 3 层模型在训练集上提供了更好的结果这一事实表明您的训练时间不够长而无法过度拟合。 此外,您似乎没有使用正确的 NN 初始化。注意:在实施过程开始时,过度拟合表明实施培训工作正常。因此,在这个阶段这是一件好事。 因此,第一步是让模型过拟合。你似乎从零开始训练。在这种情况下,可能需要 100 个 epoch,直到梯度影响 VGG16 等复杂模型上的第一个卷积。

由于 3Layer CNN 似乎严重过度拟合,我得出结论,您的数据集相当小。 因此,我建议从预训练模型 (VGG16) 开始,然后重新训练最后两层。这应该会产生更好的结果。

【讨论】:

  • 感谢您的意见@CAFEBABE!是的,我从头开始训练 VGG 模型。我将尝试使用更多 epoch 来训练我的模型,并尝试实现预训练的 VGG 模型。
  • 我尝试增加 epoch 并遇到 GPU OOM 问题。因此,为了解决这个问题,我尝试使用多处理来训练我的模型,但它不起作用。 @CAFEBABE 如果您已经管理过 OOM 问题或使用多处理训练了模型,我会感谢您对我的问题的见解。 stackoverflow.com/questions/62620104/…
  • 关于您的 OOM stackoverflow.com/questions/46981853/… 这不应该发生。您的数据太少,图像也很小。这应该很容易在单个 CPU 上工作。尤其是数据不足以从头开始训练 VGG16
  • 我在多次运行带有回调的model.fit后遇到了OOM。我认为正如您链接的帖子中所述,存在 GPU 泄漏。我将尝试遵循帖子中的答案。此外,我已经尝试了一些从头开始训练 VGG-16 的方法。我会将结果作为答案发布。
【解决方案2】:

根据@CAFEBABE 的建议,我尝试了两种方法。首先,我将 epoch 大小增加到 200,将优化器更改为 SGD,并将学习率降低到 1e-5。 其次,我已经为 VGG-16 模型实现了预训练的权重,并且只训练了最后两个卷积层。下图显示了调整后的 VGG-16 模型、预训练的 VGG-16 模型和 3 层 CNN 模型(从上到下)。

当然,调优对性能有影响,但影响很小。我猜想从具有约 600 张图像的数据集中的可学习特征不足以训练模型。并且预训练模型显着地使模型在约 25 个 epoch 时达到过拟合。然而,与 3 层 CNN 模型相比,这两个模型的测试精度相似,介于 0.7 和 0.8 之间。我想这又是由于数据集的限制。

再次感谢@CAFEBABE 帮助我解决了我的问题,我希望这可以帮助其他可能面临类似问题的人。

【讨论】:

  • 你也可以试试 Adam 优化器,它可能会导致更快的收敛。
  • 感谢您的意见。我也会和亚当一起去。
猜你喜欢
  • 1970-01-01
  • 2018-04-03
  • 2021-09-01
  • 2023-02-22
  • 1970-01-01
  • 2021-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多