首页 > 解决方案 > 历史和预测中的 TensorFlow Accuracy 不匹配

问题描述

我尝试用 Xception 网络做一些迁移学习,在训练过程中,结果看起来不错:

    Epoch 1/50
34/34 [==============================] - 357s 9s/step - loss: 1.6063 - categorical_accuracy: 0.3968 - val_loss: 1.1356 - val_categorical_accuracy: 0.5428
Epoch 2/50
34/34 [==============================] - 370s 9s/step - loss: 1.0475 - categorical_accuracy: 0.6025 - val_loss: 1.0545 - val_categorical_accuracy: 0.6580
Epoch 3/50
34/34 [==============================] - 386s 10s/step - loss: 0.9220 - categorical_accuracy: 0.6655 - val_loss: 1.0960 - val_categorical_accuracy: 0.6059
Epoch 4/50
24/34 [====================>.........] - ETA: 1:17 - loss: 0.9283 -

但经过预测,结果更糟:

from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(true_categories_argmax, predictions_argmax))
print(classification_report(true_categories_argmax, predictions_argmax))

[[29 25  1 18  3  4]
 [33 27  1 18  1 13]
 [ 4  1  0  1  0  0]
 [21 18  1  6  1  4]
 [ 1  5  0  5  1  0]
 [10 11  0  6  0  0]]
              precision    recall  f1-score   support

           0       0.30      0.36      0.33        80
           1       0.31      0.29      0.30        93
           2       0.00      0.00      0.00         6
           3       0.11      0.12      0.11        51
           4       0.17      0.08      0.11        12
           5       0.00      0.00      0.00        27

    accuracy                           0.23       269
   macro avg       0.15      0.14      0.14       269
weighted avg       0.22      0.23      0.23       269

为什么准确率是前面所说的准确率的一半?

这里的代码:

image_size = (299,299)
batch_size = 32

train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    "Bilder_sortiert",
    validation_split=0.2,
    labels="inferred",
    subset="training",
    seed=1337,
    image_size=image_size,
    batch_size=batch_size,
    label_mode='categorical',
)
validation_ds = tf.keras.preprocessing.image_dataset_from_directory(
    "Bilder_sortiert",
    validation_split=0.2,
    subset="validation",
    seed=1337,
    image_size=image_size,
    batch_size=batch_size,
    label_mode='categorical',
    labels="inferred",
)
batch_size = 32
train_ds = train_ds.prefetch(buffer_size=32)
validation_ds = validation_ds.prefetch(buffer_size=32)
data_augmentation = keras.Sequential(
    [
        layers.experimental.preprocessing.RandomFlip(), #"horizontal"
        layers.experimental.preprocessing.RandomRotation(0.1),#0.1
    ]
)
base_model = keras.applications.Xception(
    weights="imagenet",  # Load weights pre-trained on ImageNet.
    input_shape=(299, 299, 3),
    include_top=False,
)  # Do not include the ImageNet classifier at the top.

# Freeze the base_model
base_model.trainable = False

# Create new model on top
inputs = keras.Input(shape=(299, 299, 3))
x = data_augmentation(inputs)
# Pre-trained Xception weights requires that input be normalized
# from (0, 255) to a range (-1., +1.), the normalization layer
# does the following, outputs = (inputs - mean) / sqrt(var)
norm_layer = keras.layers.experimental.preprocessing.Normalization()
mean = np.array([127.5] * 3)
var = mean ** 2
# Scale inputs to [-1, +1]
x = norm_layer(x)
norm_layer.set_weights([mean, var])
x = base_model(x, training=False)
x = keras.layers.GlobalAveragePooling2D()(x)
x = keras.layers.Dropout(0.4)(x)  # Regularize with dropout
outputs = keras.layers.Dense(6,activation='softmax')(x)
model = keras.Model(inputs, outputs)

model.summary()
"""
## Train the top layer
"""

model.compile(
    optimizer=keras.optimizers.Adam(0.01),
    loss=tf.keras.losses.categorical_crossentropy,
    metrics=["categorical_accuracy"],
)

epochs = 50
model.fit(train_ds, epochs=epochs, validation_data=validation_ds)
hist=model.history.history
base_model.trainable = True
model.summary()

model.compile(
    optimizer=keras.optimizers.Adam((1e-5)),#(1e-5),  # Low learning rate
    loss=tf.keras.losses.categorical_crossentropy,
    metrics=["categorical_accuracy"],
)

epochs = 10
model.fit(train_ds, epochs=epochs, validation_data=validation_ds)

"""
After 10 epochs, fine-tuning gains us a nice improvement here.
"""

zeit=time.time()-start
print("Fitting took ",zeit," seconds")
x1=np.linspace(1,50)
x2=np.linspace(50,96,45)
ca=model.history.history["categorical_accuracy"]
ca.append(hist["categorical_accuracy"][-1])
vca=model.history.history["val_categorical_accuracy"]
plt.plot(x1,hist["categorical_accuracy"],label="dense training")
plt.plot(x1,hist["val_categorical_accuracy"],label="dense validation")
plt.plot(x2,ca[0:45],label="fine tuning training")
plt.plot(x2,vca[0:45],label="fine tuning validation")
plt.xlabel("Epochs")
plt.ylabel("Accuracy")
plt.legend()

model_eval=model
#val_inputs = tf.concat([x for x, y in validation_ds], axis=0)
predictions=model_eval.predict(validation_ds)
predictions_argmax=np.argmax(predictions, axis = 1)
true_categories = tf.concat([y for x, y in validation_ds], axis=0)
true_categories_argmax=np.argmax(true_categories, axis = 1)
print(true_categories.shape[0]," images in validation data")

print("Confusion Matrix")
from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(true_categories_argmax, predictions_argmax))
print(classification_report(true_categories_argmax, predictions_argmax))

我希望准确度应该与上次打印的 val_acc 大致相同。对于其他人来说,这似乎也是一个问题,但我认为没有人找到一个好的解决方法: https ://github.com/keras-team/keras/issues/10014

标签: pythontensorflowmachine-learningkeras

解决方案


推荐阅读