如何处理我的 Keras CNN 过度拟合

数据挖掘 机器学习 Python 美国有线电视新闻网 图像分类
2022-02-21 20:00:13

在我的 CNN 中,我有 700 个 0 类图像、700 个 1 类图像和 72 个验证图像。

我的代码:

visible = Input(shape=(256,256,3))
conv1 = Conv2D(16, kernel_size=(3,3), activation='relu', strides=(1, 1))(visible)
conv2 = Conv2D(32, kernel_size=(3,3), activation='relu', strides=(1, 1))(conv1)
bat1 = BatchNormalization()(conv2)
conv3 = ZeroPadding2D(padding=(1, 1))(bat1)
pool1 = MaxPooling2D(pool_size=(2, 2))(conv3)
drop1 = Dropout(0.30)(pool1)

conv4 = Conv2D(32, kernel_size=(3,3), activation='relu', padding='valid', kernel_regularizer=regularizers.l2(0.01))(drop1)
conv5 = Conv2D(64, kernel_size=(3,3), activation='relu', padding='valid', kernel_regularizer=regularizers.l2(0.01))(conv4)
bat2 = BatchNormalization()(conv5)
pool2 = MaxPooling2D(pool_size=(1, 1))(bat2)
drop1 = Dropout(0.30)(pool2)

conv6 = Conv2D(128, kernel_size=(3,3), activation='relu', padding='valid', kernel_regularizer=regularizers.l2(0.01))(pool2)
conv7 = Conv2D(128, kernel_size=(2,2), activation='relu', strides=(1, 1), padding='valid')(conv6)
bat3 = BatchNormalization()(conv7)
pool3 = MaxPooling2D(pool_size=(1, 1))(bat3)
drop1 = Dropout(0.30)(pool3)

flat = Flatten()(pool3)
drop4 = Dropout(0.50)(flat)

output = Dense(1, activation='sigmoid')(drop4)
model = Model(inputs=visible, outputs=output)

opt = optimizers.adam(lr=0.001, decay=0.0)

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

data, labels = ReadImages(TRAIN_DIR)
test, lt = ReadImages(TEST_DIR)

data = np.array(data)
labels = np.array(labels)

perm = np.random.permutation(len(data))
data = data[perm]
labels = labels[perm]
#model.fit(data, labels, epochs=8, validation_data = (np.array(test), np.array(lt)))

aug = ImageDataGenerator(rotation_range=20, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.15,
    horizontal_flip=True)

# train the network
model.fit_generator(aug.flow(data, labels, batch_size=32),
    validation_data=(np.array(test), np.array(lt)), steps_per_epoch=len(data) // 32,
    epochs=7)

model.save('model.h5')

它返回这些数字:

Epoch 1/7
43/43 [==============================] - 1004s 23s/step - loss: 1.8090 - acc: 0.9724 - val_loss: 1.7871 - val_acc: 0.9861
Epoch 2/7
43/43 [==============================] - 1003s 23s/step - loss: 1.8449 - acc: 0.9801 - val_loss: 1.4828 - val_acc: 1.0000
Epoch 3/7
43/43 [==============================] - 1092s 25s/step - loss: 1.5704 - acc: 0.9920 - val_loss: 1.3985 - val_acc: 1.0000
Epoch 4/7
43/43 [==============================] - 1062s 25s/step - loss: 1.5219 - acc: 0.9898 - val_loss: 1.3167 - val_acc: 1.0000
Epoch 5/7
43/43 [==============================] - 990s 23s/step - loss: 2.5744 - acc: 0.9222 - val_loss: 2.9347 - val_acc: 0.9028
Epoch 6/7
43/43 [==============================] - 983s 23s/step - loss: 1.6053 - acc: 0.9840 - val_loss: 1.3299 - val_acc: 1.0000
Epoch 7/7
43/43 [==============================] - 974s 23s/step - loss: 1.6180 - acc: 0.9801 - val_loss: 1.5181 - val_acc: 0.9861

当我预测一些测试图像时,结果总是 0。

我已经尝试过各种方法,例如添加更多的 dropout(或使 dropout 率更大)、数据增强、批量标准化等,但这些都没有使它正常工作。

我该怎么办?

3个回答

由于您的数据非常少,您应该按照@muneeb 的建议进行迁移学习,因为这已经包含大多数学习参数,然后您可以使用自定义数据集训练该模型。

您可以从这里试用预训练模型

如果您只想使用现有的自定义配置模型,请尝试在输出之前添加另一个 Dense 层。

就像密集(128,激活='relu')。

在此处分享您的结果,以便我们进行更多探索。

如果您的图像数量较少,我对您的建议是使用迁移学习。根据您的数据集使用模型,如 VGG16、VGG19 并进行迁移学习,而不是创建新模型。使用迁移学习的优点如下: 1. 预训练模型通常会加快在新任务上训练模型的过程。该模型已经优化了权重,因此它可能有助于克服过度拟合。

正如其他答案所提到的,使用 VGG 之类的预训练模型会有所帮助。但是,当您说它始终为 0 时,您可以在代码中检查以下内容:

  1. 类标签是否正确?可能都是 0 级的情况。
  2. 查看预测的softmax值,它们是否不同。如果没有,那么我们就有问题了。
  3. 尝试不退出和批量标准化。
  4. 检查预测是否适用于火车数据。您的调用代码中可能存在错误。(就像你在训练和调用时处理图像的方式不同)
  5. 在 CNN 层之后,正如 @desmond 提到的,使用 Dense 层甚至 Global Max 池化。此外,检查以删除 BatchNorm 和 dropout,有时它们的行为会有所不同。
  6. 最后也是最有可能的情况是:与验证相比,火车中的图像有多大不同。如果它们来自不同的相机或其他东西,它会有所不同,这些东西会导致问题