过拟合 CNN 模型

数据挖掘 深度学习 美国有线电视新闻网 过拟合 卷积神经网络
2022-02-17 10:23:21

我尝试开发一些 CNN 架构来训练“猫狗”Kaggle 训练集的 1000 点子集(顺便说一下,这意味着所有 1000 个数据点都被标记)。我使用了 700-150-150 train-validate-test split,并在 Xception 架构上使用了以下代码:

pre_xception_model = keras.applications.Xception(include_top=False, weights='imagenet',
                                                 input_tensor=None, input_shape=(224,224,3), pooling=None, classes=2)
for layer in pre_xception_model.layers:
    layer.trainable = False
dropout = Dropout(0.5)(pre_xception_model.output)
flatten = Flatten()(dropout)   
output = Dense(2, activation='softmax')(flatten)
xception_model = Model(pre_xception_model.input, output)

xception_model.compile(Adam(lr=.0001, decay=1e-6), loss='categorical_crossentropy', metrics=['accuracy'])

aug = ImageDataGenerator(rotation_range=20, zoom_range=0.15,
    width_shift_range=0.2, height_shift_range=0.2, shear_range=0.15,
    horizontal_flip=True, fill_mode="nearest")
batches = 20

xception_model.fit_generator(aug.flow(X_train, y_train, batch_size = batches), steps_per_epoch = len(X_train) // batches,
                          validation_data = (X_valid, y_valid), validation_steps = 4, epochs = 10, verbose = 1)

xception_prob = xception_model.predict(X_test, verbose=1)
xception_predict = xception_prob.argmax(axis=-1)
cm_xception = confusion_matrix(y_test[:,1], xception_predict)
plot_confusion_matrix(cm_xception, cm_plot_labels, title='Confusion Matrix')

print(f'\nAccuracy = {(cm_xception[0,0]+cm_xception[1,1])/150}\n')

这出品了这个训练日志.predict()出品了这个混淆矩阵我无法解释过度拟合;这里有人可以帮助我了解我在哪里出错了吗?

2个回答

如果我错了,请纠正我,但您似乎有一个二元分类问题 - 图像包含一只猫或一只狗。

如果是这样的话,那么:

output = Dense(1, activation='sigmoid')(flatten)

xception_model.compile(Adam(lr=.0001, decay=1e-6), loss='binary_crossentropy', metrics=['binary_accuracy'])

这个线程是关于这两个问题之间差异的一个很好的资源。

让我知道它是否有效。

编辑:进一步解释

尽管我们通常谈论“二元分类”,但通常将结果建模为伯努利随机变量,以输入数据为条件。所以:

P(y=1|x)=p, 0p1

伯努利随机变量的值介于 0 和 1 之间。这就是我们的网络应该产生的结果。一个想法可能是只剪裁wth+b在那个区间之外。但如果我们这样做,这些区域的梯度将为 0:网络无法学习。

更好的方法是使用 sigmoid 函数将完整的传入区间压缩到 (0,1) 范围内:

σ(x)=11+e(x)

但是当输入变得非常大或非常小时,sigmoid 函数就会饱和。这有问题吗?这取决于。最后,我们关心的是成本函数是否饱和。如果我们遵循最大似然/交叉熵的一般原则,损失将是:

logP(y|x)

在哪里log撤消exp在乙状结肠。

在 Keras 中,对应的损失函数是 binary_crossentropy。对于单个项目,损失将是:

  • log(p)当基本事实为 1

  • log(1p)当基本事实为 0 时

在这里,您可以看到,对于单个示例,当网络预测错误的类并对其高度自信时,该示例将对损失有很大的贡献。因此,您只需要一个输出节点,因为二进制分类是“对称的”。我的意思是,如果我们说一个项目以概率 p 属于 0 类,我们也指的是同一项目以概率 1 - p 属于 1 类这一事实。

尝试按如下方式更改您的代码:

pre_xception_model = keras.applications.Xception(include_top=False, weights='imagenet',
                                                 input_tensor=None, input_shape=(224,224,3), pooling='avg', classes=2)
x=pre_xception.layers[-1].output
x=keras.layers.BatchNormalization(axis=-1, momentum=0.99, epsilon=0.001 )(x)
output = Dense(2, activation='softmax')(x)
xception_model = Model(pre_xception_model.input, output)
for layer in pre_xception_model.layers:
    layer.trainable = True
xception_model.compile(Adam(lr=.0001, decay=1e-6), loss='categorical_crossentropy', metrics=['accuracy'])

这会为模型添加一个平均池化层,然后是批量标准化和最终的分类层。我将它用于 MobileNet 模型并且效果很好。我还建议您使用回调 ModelCheckpoint 和 ReduceLROnPlateau。这些文档在这里。