【问题标题】:Keras accuracy is different between model and classification report for binary output二进制输出的模型和分类报告之间的 Keras 精度不同
【发布时间】:2021-02-26 21:28:09
【问题描述】:

这是我加载数据的方式,这两个文件夹包含图像数据:

train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    main_folder,
    validation_split=0.1,
    subset="training",
    seed=123,
    image_size=(dim, dim))

val_ds = tf.keras.preprocessing.image_dataset_from_directory(
    main_folder,
    validation_split=0.1,
    subset="validation",
    seed=123,
    image_size=(dim, dim))

从文件夹中加载训练数据给

Found 6457 files belonging to 2 classes.
Using 5812 files for training.
Found 6457 files belonging to 2 classes.
Using 645 files for validation.

这是我训练模型的方法:

model = tf.keras.models.Sequential([
    tf.keras.layers.experimental.preprocessing.Rescaling(1. / 255),
    tf.keras.layers.Conv2D(16, (3, 3), activation='relu', padding='same'),
    tf.keras.layers.MaxPooling2D(2, 2),
    tf.keras.layers.Conv2D(32, (3, 3), activation='relu', padding='same'),
    tf.keras.layers.MaxPooling2D(2, 2),
    tf.keras.layers.Conv2D(32, (3, 3), activation='relu', padding='same'),
    tf.keras.layers.MaxPooling2D(2, 2),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(512, activation='relu'),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(512, activation='relu'),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(1, activation='sigmoid')
])

model.compile(loss=tf.losses.BinaryCrossentropy(from_logits=True), optimizer="adam", metrics=["accuracy"])

es = EarlyStopping(monitor='val_accuracy', min_delta=0.1, patience=5)

model.fit(
    train_ds,
    validation_data=val_ds,
    epochs=epc,
    callbacks=[es])

这是我得到结果的方式:

y_pred = model.predict(val_ds)
predicted_categories = tf.argmax(y_pred, axis=1)
true_categories = tf.concat([y for x, y in val_ds], axis=0)
    
print(classification_report(true_categories, predicted_categories ))

矛盾的输出是:

Epoch 1/100
182/182 [==============================] - 8s 44ms/step - loss: 0.6617 - accuracy: 0.5139 - val_loss: 0.6466 - val_accuracy: 0.3442
Epoch 2/100
182/182 [==============================] - 8s 46ms/step - loss: 0.6613 - accuracy: 0.5712 - val_loss: 0.6460 - val_accuracy: 0.6558
Epoch 3/100
182/182 [==============================] - 8s 44ms/step - loss: 0.6611 - accuracy: 0.5594 - val_loss: 0.6474 - val_accuracy: 0.3442
Epoch 4/100
182/182 [==============================] - 8s 46ms/step - loss: 0.6315 - accuracy: 0.6504 - val_loss: 0.4623 - val_accuracy: 0.9690
Epoch 5/100
182/182 [==============================] - 8s 46ms/step - loss: 0.4780 - accuracy: 0.9554 - val_loss: 0.4597 - val_accuracy: 0.9690
Epoch 6/100
182/182 [==============================] - 8s 45ms/step - loss: 0.4831 - accuracy: 0.9434 - val_loss: 0.4517 - val_accuracy: 0.9845
Epoch 7/100
182/182 [==============================] - 8s 45ms/step - loss: 0.4720 - accuracy: 0.9658 - val_loss: 0.4546 - val_accuracy: 0.9736
Epoch 8/100
182/182 [==============================] - 8s 44ms/step - loss: 0.4719 - accuracy: 0.9652 - val_loss: 0.4507 - val_accuracy: 0.9860
Epoch 9/100
182/182 [==============================] - 8s 44ms/step - loss: 0.4747 - accuracy: 0.9597 - val_loss: 0.4528 - val_accuracy: 0.9814

              precision    recall  f1-score   support
           0       0.34      1.00      0.51       222
           1       0.00      0.00      0.00       423
    accuracy                           0.34       645
   macro avg       0.17      0.50      0.26       645
weighted avg       0.12      0.34      0.18       645

否则每次执行都会得到不同的答案

请问为什么分类报告的准确率是 34% 而模型 val_accuracy 是 0.94%?

【问题讨论】:

  • 你能添加你的模型吗?
  • 您是否尝试在编译模型时添加 precisionrecallaccuracy
  • @Frightera 我添加了模型
  • @M.Innat 我已经添加了我是如何编译模型的,你能强调一下你是如何插入这些值的吗?

标签: python tensorflow keras


【解决方案1】:
tf.keras.preprocessing.image_dataset_from_directory

方法有一个参数label_mode,默认值为int,适用于sparse_categoricalcrossentropy等,如果分类为二分类,则改为label_model = binary

矛盾就在这里:

tf.keras.layers.Dense(1, activation='sigmoid')

predicted_categories = tf.argmax(y_pred, axis=1)

使用sigmoid,您的输出由一个形状为(1,) 的列表组成。当您使用该列表的argmax 时,它总是返回零作为索引,因为该列表只有一个索引。因此在使用sigmoid 时需要应用一些阈值方法。 Sigmoid 将输出压缩到 [0,1] 的范围内。所以你可以这样做:

predicted_categories = [1 * (x[0]>=0.5) for x in y_pred]

这意味着如果预测值大于0.5,那么它将属于第二类。您可以根据需要调整阈值。

【讨论】:

  • 这就是我所做的,实际上每次执行它都会给我不同的答案predicted_categories = [1 * (x[0] >= 0.5) for x in y_pred] true_categories = tf.concat([y for x, y in val_ds], axis=0) print(classification_report(true_categories, predicted_categories))
  • 问题中我错误地使用了predicted_categories = tf.argmax(y_pred, axis=1)y_pred_bool = np.argmax(y_pred, axis=1),所以我将删除y_pred_pool
  • 我忘了提到image_dataset_from_directory 有一个标签模式,默认为int。可以试试改成label_mode = binary吗?
  • 我正在重新训练它需要一些时间,但看起来你是对的。问题是双重的,首先我如何计算predicted_categories,其次将其更改为label_mode = binary
  • tf.keras.layers.Dense(1, activation='sigmoid'),因为您指定了label_mode = binary。如果您可以对其进行热编码,则可以使用tf.keras.layers.Dense(2, activation='softmax')。在 multi-class 分类中,您不想使用包含 2 个具有 sigmoid 激活的神经元的 Dense 层。
猜你喜欢
  • 2021-05-28
  • 2020-12-20
  • 2018-09-28
  • 1970-01-01
  • 2021-05-02
  • 2020-07-20
  • 2020-09-08
  • 2018-04-23
  • 2012-11-29
相关资源
最近更新 更多