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

时间:2020-06-26 22:07:43

标签: python tensorflow machine-learning keras deep-learning

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

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图像,尽管与我的微调数据集相比,从不同角度拍摄的车辆图像

现在我要提出的问题来自以下观察结果:

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

  • 训练精度为 0.9229
  • 3.5055
  • 的培训损失
  • 验证准确性为 0.7906
  • 验证损失为 0.9382
  • 0.9186
  • 上课的培训精度
  • 0.9384
  • 轿车的训练精度
  • suv 的 0.9196
  • 的训练精度
  • 0.8378
  • van 类的训练精度
  • 0.7805
  • 的类提取的验证精度 轿车 0.8026 类的
  • 验证精度
  • suv 0.0.8029
  • 的验证精度 0.4615 van 类的
  • 验证精度

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

较低但仍然足够高的验证精度使我相信,该模型可以推广,不存在过度拟合的问题。

我的第一个问题 是:验证损失如何比训练损失那么低?

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

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给出的准确性如何在训练和评估过程中如此小的值似乎表明我的模型的预测非常精确?

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

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

3 个答案:

答案 0 :(得分:0)

我同意@gallen。有多种原因可能导致过度拟合,并且有几种防止过度拟合的方法。好的解决方案之一是在各层之间添加丢包。您可以看到stackoverflow answertowardsdatascience article

答案 1 :(得分:0)

当然有点过拟合,但是让我们回答问题。

对于第一个问题,验证数据的数量少是一个原因,为什么它的损失比训练数据少,因为损失是y_truey_pred中所有差异的总和。

关于第二个问题,即使验证没有显示出过度拟合的迹象,测试准确性又如何会低于预期?

验证集的分布必须与测试集相同,以免误导。

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

答案 2 :(得分:0)

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