Tensorflow Keras - 训练时准确率高,预测时准确率低

Posted

技术标签:

【中文标题】Tensorflow Keras - 训练时准确率高,预测时准确率低【英文标题】:Tensorflow Keras - High accuracy during training, low accuracy during prediction 【发布时间】:2020-10-17 13:39:48 【问题描述】:

我有一个非常基本的多类 CNN 模型,用于将车辆分为 4 类[pickup, sedan, suv, van],我使用 Tensorflow 2.0 tf.keras 编写了该模型:

he_initialiser = tf.keras.initializers.VarianceScaling()
model = tf.keras.Sequential()
model.add(tf.keras.layers.Conv2D(32, kernel_size=(3,3), input_shape=(3,128,128), activation='relu', padding='same', data_format='channels_first', kernel_initializer=he_initialiser))
model.add(tf.keras.layers.Conv2D(32, kernel_size=(3,3), activation='relu', padding='same', data_format='channels_first', kernel_initializer=he_initialiser))
model.add(tf.keras.layers.MaxPooling2D((2, 2), data_format=cfg_data_fmt))
model.add(tf.keras.layers.Conv2D(64, kernel_size=(3,3), activation='relu', padding='same', data_format='channels_first', kernel_initializer=he_initialiser))
model.add(tf.keras.layers.Conv2D(64, kernel_size=(3,3), activation='relu', padding='same', data_format='channels_first', kernel_initializer=he_initialiser))
model.add(tf.keras.layers.MaxPooling2D((2, 2), data_format=cfg_data_fmt))
model.add(tf.keras.layers.Conv2D(128, kernel_size=(3,3), activation='relu', padding='same', data_format='channels_first', kernel_initializer=he_initialiser))
model.add(tf.keras.layers.Conv2D(128, kernel_size=(3,3), activation='relu', padding='same', data_format='channels_first', kernel_initializer=he_initialiser))
model.add(tf.keras.layers.MaxPooling2D((2, 2), data_format='channels_first'))
model.add(tf.keras.layers.Flatten(data_format='channels_first'))
model.add(tf.keras.layers.Dense(128, activation='relu', kernel_initializer=he_initialiser))
model.add(tf.keras.layers.Dense(128, activation='relu', kernel_initializer=he_initialiser))
model.add(tf.keras.layers.Dense(4, activation='softmax', kernel_initializer=he_initialiser))

我使用以下配置进行训练:

图像尺寸:3x128x128(平面数据) 时期数:45 批量大小:32 损失函数:tf.keras.losses.CategoricalCrossentropy(from_logits=True) 优化器:optimizer=tf.optimizers.Adam 训练数据大小:占所有数据的 67.5% 验证数据大小:所有数据的 12.5% 测试数据大小:所有数据的 20%

我有一个不平衡的数据集,其分布如下:

pickups: 1202
sedans: 1954
suvs: 2510
vans: 196

出于这个原因,我使用了类权重来缓解这种不平衡:

pickup_weight: 4.87
sedan_weight: 3.0
suv_weight: 2.33
van_weight: 30.0

这似乎是一个小数据集,但我将其用于微调,因为我首先在这些类别的 16k 图像的更大数据集上训练模型,尽管与我的微调数据集相比,车辆图像是从不同角度拍摄的.

现在我的问题源于以下观察:

在最后一个epoch结束时,model.fit返回的结果是:

训练准确率0.9229 3.5055的训练损失 验证准确率0.7906 验证损失0.9382 pickup 类的训练精度为 0.9186 轿车类的训练精度0.9384 suv 类的训练精度为 0.9196 van 类的训练精度为 0.8378 pickup 类的验证精度为 0.7805 轿车类的验证精度0.8026 suv 类的验证精度为 0.0.8029 van 类的验证精度为 0.4615

model.evaluate 在训练后在我的保留测试集上返回的结果给出了与上一个 epoch 中相应的验证值相似的准确度和损失值,并且每个类的精度值也几乎与相应的验证精度相同.

较低但仍然足够高的验证准确度让我相信没有过度拟合问题,因为模型可以泛化。

我的第一个问题是验证损失怎么会比训练损失低这么多?

此外,当我使用以下方法创建混淆矩阵时:

test_images = np.array([x[0].numpy() for x in list(labeled_ds_test)])
test_labels = np.array([x[1].numpy() for x in list(labeled_ds_test)])
test_predictions = model.predict(test_images, batch_size=32)
print(tf.math.confusion_matrix(tf.argmax(test_labels, 1), tf.argmax(test_predictions, 1)))

我得到的结果是:

tf.Tensor(
[[ 42  85 109   3]
 [ 72 137 177   4]
 [ 91 171 228  11]
 [  9  12  16   1]], shape=(4, 4), dtype=int32)

这表明准确率只有 35%!!

我的第二个问题因此是这样的:model.predict 给出的准确度怎么会如此之小,而在训练和评估期间,这些值似乎表明我的模型是它的预测相当准确?

我使用的预测方法是错误的,还是我对预期会发生什么的理论理解完全错误?

我在这里有点茫然,非常感谢任何反馈。感谢您阅读本文。

【问题讨论】:

当训练准确率很高,而预测准确率很低时,这肯定是过拟合的迹象。我建议调查过度拟合的原因和解决方案。 【参考方案1】:

我同意@gallen。有几个原因会导致过拟合以及几种防止过拟合的方法。一个好的解决方案是在层之间添加 dropout。你可以看到*** answer和towardsdatascience article

【讨论】:

【参考方案2】:

当然存在过度拟合,但让我们回答问题。

对于第一个问题,由于损失是y_truey_pred 中所有差异的总和,因此验证数据的数量少是其损失小于训练数据的原因。

至于第二个问题,即使验证没有显示任何过度拟合的迹象,测试准确度怎么会低于预期?

验证集的分布必须与测试集的分布相同,以免错过领先。

所以我的建议是分别检查训练、验证和测试数据集的分布。确保它们相同。

【讨论】:

【参考方案3】:

您需要正确划分数据集,例如 70% 的训练和 30% 的验证,然后将新数据集作为测试数据检查您的模型,这可能会有所帮助,因为机器学习就是反复试验。

【讨论】:

以上是关于Tensorflow Keras - 训练时准确率高,预测时准确率低的主要内容,如果未能解决你的问题,请参考以下文章

使用Python,Keras和TensorFlow训练第一个CNN

训练准确性增加,然后偶尔突然下降。使固定? [Keras] [TensorFlow 后端]

为啥在同一数据集上使用 tensorflow 和 keras 重新训练的 Inception V3 显示出不同的准确性?

tensorflow 测量工具,与自定义训练

为啥训练时准确率和损失保持不变?

TensorFlow 低级模型(没有 Keras 和 Sklearn) - 每一步都获得损失 = 0 和准确度 = 100%