CNN (VGG-16) 在验证准确率上的奇怪行为

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

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

分割后的图像如下所示。

分割后的扫描图像

我分别在分割后的图像和原始图像上训练并评估了VGG-16模型。最后,在分割后的图像上训练并评估了一个3层的CNN。以下是它们的训练/验证损失和准确率的结果。

损失与准确率图表

对于简单的3层CNN模型,我可以清楚地看到模型训练得很好,并且一旦训练超过2个周期就开始过拟合。但是,我不明白为什么VGG模型的验证准确率看起来不像指数曲线,反而像是一条水平直线或波动的水平线。此外,简单的3层CNN模型似乎表现得更好。这是由于VGG模型中的梯度消失造成的吗?还是图像本身太简单,深层架构没有带来好处?我希望您能分享您对这种模型学习行为的知识。

这是VGG-16模型的代码:

# build modelimg_height = 256img_width = 256model = 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 modelmodel2 = 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'])

谢谢!


回答:

假设这是一个二分类问题,通过观察准确率可以看出模型只是在随机猜测(准确率约为0.5)。您3层模型在训练集上的结果要好得多,这表明您训练的时间不够长,尚未达到过拟合。此外,您似乎没有对神经网络进行适当的初始化。注意:在实施过程的开始阶段,过拟合表明训练过程正常进行。因此,在这个阶段这是件好事。因此,第一步应该是让模型过拟合。您似乎是从头开始训练的。在这种情况下,像VGG16这样的复杂模型可能需要几百个周期才能影响到第一个卷积层。

由于3层CNN似乎严重过拟合,我认为您的数据集相当小。因此,我建议从预训练模型(VGG16)开始,只重新训练最后两层。这应该能得到更好的结果。

Related Posts

用于比较两个向量进行分类的损失函数

我正在进行一项自然语言处理任务,分析文档并将其分类到六…

(OpenNMT) 西班牙语到英语模型的改进

我目前正在尝试使用yaml脚本训练一个西班牙语到英语的…

什么是多变量时间序列在Keras中LSTM的正确输入形状?

我无法理解将多变量时间序列输入到LSTM的正确方法是什…

GPU 用于随机森林回归器

我对机器学习还是新手,之前所有的机器学习项目都是使用 …

关于sklearn中SVC对象的`decision_function_shape`参数的澄清

问题 decision_function_shape参…

将数据加载到 X_train 和 Y_train

如果我的数据是以这种方式组织的,我应该如何将数据加载到…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注