为什么 val 准确率在 2 个 epoch 内达到 100% 并且错误地预测新图像?(训练时每班 1,000 张图像)

数据挖掘 机器学习 Python 深度学习 张量流
2022-03-07 22:13:34

我的 CNN tensorflow 模型在 2 个 epoch 内报告了 100% 的验证准确度。但它错误地预测了单个新图像。(这是多类问题。我有 3 个类)。如何解决这个问题?你能帮我理解这些时代的结果吗?

我每个班级有 1,000 张图像代表我的测试数据。当我有一个总共 3,000 张图像的数据集时,验证准确率如何在第一个 epoch 达到 1.00,每个类别的数量相等?(我预计这将从 33% 左右开始——1/ 3 个班级。

尝试:

  1. 我试图确保我已正确地将我的数据集拆分为训练和验证。
  2. 我知道过度拟合可能是一个问题。我添加了一个 dropout 层来尝试解决这个潜在的问题。从这个问题https://ai.stackexchange.com/questions/5318/what-to-do-if-cnn-cannot-overfit-a-training-set-on-adding-dropout/23425我了解到一个“模型如果在训练期间您的训练损失继续减少但(在后期)您的验证损失开始增加,则表示过度拟合。这意味着该模型无法很好地泛化到以前未遇到的图像。根据此描述,我不相信我的模型过度拟合。(我的模型报告了高训练和高验证准确度。如果我的模型过度拟合,我期望高训练准确度和低验证准确度。)

我的模型:

def model():
  model_input = tf.keras.layers.Input(shape=(h, w, 3)) 
  x = tf.keras.layers.Rescaling(rescale_factor)(model_input) 
  x = tf.keras.layers.Conv2D(16, 3, activation='relu',padding='same')(x)
  x = tf.keras.layers.Dropout(.5)(x)
  x = tf.keras.layers.MaxPooling2D()(x) 
  x = tf.keras.layers.Flatten()(x)
  x = tf.keras.layers.Dense(128, activation='relu')(x)
  outputs = tf.keras.layers.Dense(num_classes, activation = 'softmax')(x)

纪元结果:

Epoch 1/10
/usr/local/lib/python3.7/dist-packages/tensorflow/python/util/dispatch.py:1096: UserWarning: "`sparse_categorical_crossentropy` received `from_logits=True`, but the `output` argument was produced by a sigmoid or softmax activation and thus does not represent logits. Was this intended?"
  return dispatch_target(*args, **kwargs)
27/27 [==============================] - 13s 124ms/step - loss: 1.0004 - accuracy: 0.5953 - val_loss: 0.5053 - val_accuracy: 0.8920
Epoch 2/10
27/27 [==============================] - 1s 46ms/step - loss: 0.1368 - accuracy: 0.9825 - val_loss: 0.0126 - val_accuracy: 1.0000
Epoch 3/10
27/27 [==============================] - 1s 42ms/step - loss: 0.0020 - accuracy: 1.0000 - val_loss: 5.9116e-04 - val_accuracy: 1.0000
Epoch 4/10
27/27 [==============================] - 1s 42ms/step - loss: 3.0633e-04 - accuracy: 1.0000 - val_loss: 3.5376e-04 - val_accuracy: 1.0000
Epoch 5/10
27/27 [==============================] - 1s 42ms/step - loss: 1.7445e-04 - accuracy: 1.0000 - val_loss: 2.2319e-04 - val_accuracy: 1.0000
Epoch 6/10
27/27 [==============================] - 1s 42ms/step - loss: 1.2910e-04 - accuracy: 1.0000 - val_loss: 1.8078e-04 - val_accuracy: 1.0000
Epoch 7/10
27/27 [==============================] - 1s 42ms/step - loss: 1.0425e-04 - accuracy: 1.0000 - val_loss: 1.4247e-04 - val_accuracy: 1.0000
Epoch 8/10
27/27 [==============================] - 1s 42ms/step - loss: 8.6284e-05 - accuracy: 1.0000 - val_loss: 1.2057e-04 - val_accuracy: 1.0000
Epoch 9/10
27/27 [==============================] - 1s 42ms/step - loss: 7.0085e-05 - accuracy: 1.0000 - val_loss: 9.3485e-05 - val_accuracy: 1.0000
Epoch 10/10
27/27 [==============================] - 1s 42ms/step - loss: 5.4979e-05 - accuracy: 1.0000 - val_loss: 8.5952e-05 - val_accuracy: 1.0000

Model.fit 和 model.compile:

model = model()

model = tf.keras.Model(model_input, outputs)
  
 model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
              metrics=['accuracy'])
  
hist = model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=10
)

预测新图像的代码:

def makePrediction(image):
  from IPython.display import display
  from PIL import Image
  from tensorflow.keras.preprocessing import image_dataset_from_directory 
  img = keras.preprocessing.image.load_img(
  image, target_size=(h, q)
  )
  img_array = keras.preprocessing.image.img_to_array(img)
  img_array = tf.expand_dims(img_array, 0) #Create a batch
 
  predicts = model.predict(img_array)
  p = class_names[np.argmax(predicts)]
  return p

转到“数据”目录并使用文件夹创建数据集。每个文件夹都是一个类标签:

from keras.preprocessing import image
directory_data = "data"
tf.keras.utils.image_dataset_from_directory(
    directory_testData, labels='inferred', label_mode='int',
    class_names=None, color_mode='rgb', batch_size=32, image_size=(256,
    256), shuffle=True, seed=123, validation_split=0.2, subset="validation",
    interpolation='bilinear', follow_links=False,
    crop_to_aspect_ratio=False
)
 
tf.keras.utils.image_dataset_from_directory(directory_testData, labels='inferred')

创建数据集并拆分它:

train_ds 代码:(输出:找到属于 3 个类的 1605 个文件。使用 1284 个文件进行训练。)

train_ds = tf.keras.preprocessing.image_dataset_from_directory(
  directory_data = "data",
  validation_split=0.2,
  subset="training",
  seed=123,
  image_size=(h, w),
  batch_size=batch_size)

val_ds 代码:(输出:找到属于 3 个类的 1605 个文件。使用 321 个文件进行验证。)

val_ds = tf.keras.preprocessing.image_dataset_from_directory(
directory_data = "data",
  validation_split=0.2,
  subset="validation",
  seed=123,
  image_size=(h, w),
  batch_size=batch_size)
1个回答

model.compile您使用了错误的指标 ( metrics=['accuracy'])... 当您使用SparseCategoricalCrossentropy时,您应该使用SparseCategoricalAccuracy.

from tensorflow.keras.metrics import SparseCategoricalAccuracy 

model.compile(loss=...,
              optimizer=..., 
              metrics=[SparseCategoricalAccuracy()])