我试图使用以下代码为我的图像分类器绘制混淆矩阵,但收到错误消息:’PrefetchDataset’对象没有属性’classes’
Y_pred = model.predict(validation_dataset)y_pred = np.argmax(Y_pred, axis=1)print('Confusion Matrix')print(confusion_matrix(validation_dataset.classes, y_pred)) # 生成错误消息
‘PrefetchDataset’对象没有属性’classes’
回答:
免责声明: 这对已打乱的数据集不起作用。
你可以使用tf.stack
来拼接所有数据集的值。像这样:
true_categories = tf.concat([y for x, y in test_dataset], axis=0)
为了可重复性,假设你有一个数据集,一个神经网络和一个训练循环:
import tensorflow_datasets as tfdsimport tensorflow as tffrom sklearn.metrics import confusion_matrixdata, info = tfds.load('iris', split='train', as_supervised=True, shuffle_files=True, with_info=True)AUTOTUNE = tf.data.experimental.AUTOTUNEtrain_dataset = data.take(120).batch(4).prefetch(buffer_size=AUTOTUNE)test_dataset = data.skip(120).take(30).batch(4).prefetch(buffer_size=AUTOTUNE)model = tf.keras.Sequential([ tf.keras.layers.Dense(8, activation='relu'), tf.keras.layers.Dense(16, activation='relu'), tf.keras.layers.Dense(info.features['label'].num_classes, activation='softmax') ])model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics='accuracy')history = model.fit(train_dataset, validation_data=test_dataset, epochs=50, verbose=0)
现在你的模型已经拟合完毕,你可以预测测试集:
y_pred = model.predict(test_dataset)
array([[2.2177568e-05, 3.0841196e-01, 6.9156587e-01], [4.3539176e-06, 1.2779665e-01, 8.7219906e-01], [1.0816366e-03, 9.2667454e-01, 7.2243840e-02], [9.9921310e-01, 7.8686583e-04, 9.8775059e-09]], dtype=float32)
这将是一个(n_samples, 3)
的数组,因为我们处理的是三个类别。我们需要一个(n_samples, 1)
的数组以供sklearn.metrics.confusion_matrix
使用,因此取argmax:
predicted_categories = tf.argmax(y_pred, axis=1)
<tf.Tensor: shape=(30,), dtype=int64, numpy=array([2, 2, 2, 0, 2, 2, 2, 2, 1, 1, 2, 0, 0, 2, 1, 1, 1, 2, 0, 2, 1, 2, 1, 0, 2, 0, 1, 2, 1, 0], dtype=int64)>
然后,我们可以从预取数据集中提取所有y
值:
true_categories = tf.concat([y for x, y in test_dataset], axis=0)
[<tf.Tensor: shape=(4,), dtype=int64, numpy=array([1, 1, 1, 0], dtype=int64)>, <tf.Tensor: shape=(4,), dtype=int64, numpy=array([2, 2, 2, 2], dtype=int64)>, <tf.Tensor: shape=(4,), dtype=int64, numpy=array([1, 1, 1, 0], dtype=int64)>, <tf.Tensor: shape=(4,), dtype=int64, numpy=array([0, 2, 1, 1], dtype=int64)>, <tf.Tensor: shape=(4,), dtype=int64, numpy=array([1, 2, 0, 2], dtype=int64)>, <tf.Tensor: shape=(4,), dtype=int64, numpy=array([1, 2, 1, 0], dtype=int64)>, <tf.Tensor: shape=(4,), dtype=int64, numpy=array([2, 0, 1, 2], dtype=int64)>, <tf.Tensor: shape=(2,), dtype=int64, numpy=array([1, 0], dtype=int64)>]
然后,你就可以准备好获取混淆矩阵了:
confusion_matrix(predicted_categories, true_categories)
array([[ 9, 0, 0], [ 0, 9, 0], [ 0, 2, 10]], dtype=int64)
(9 + 9 + 10) / 30 = 0.933
是准确率得分。它对应于model.evaluate(test_dataset)
:
8/8 [==============================] - 0s 785us/step - loss: 0.1907 - accuracy: 0.9333
结果也与sklearn.metrics.classification_report
一致:
precision recall f1-score support 0 1.00 1.00 1.00 8 1 0.82 1.00 0.90 9 2 1.00 0.85 0.92 13 accuracy 0.93 30 macro avg 0.94 0.95 0.94 30weighted avg 0.95 0.93 0.93 30
这是完整的代码:
import tensorflow_datasets as tfdsimport tensorflow as tffrom sklearn.metrics import confusion_matrixdata, info = tfds.load('iris', split='train', as_supervised=True, shuffle_files=True, with_info=True)AUTOTUNE = tf.data.experimental.AUTOTUNEtrain_dataset = data.take(120).batch(4).prefetch(buffer_size=AUTOTUNE)test_dataset = data.skip(120).take(30).batch(4).prefetch(buffer_size=AUTOTUNE)model = tf.keras.Sequential([ tf.keras.layers.Dense(8, activation='relu'), tf.keras.layers.Dense(16, activation='relu'), tf.keras.layers.Dense(info.features['label'].num_classes, activation='softmax') ])model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics='accuracy')history = model.fit(train_dataset, validation_data=test_dataset, epochs=50, verbose=0)y_pred = model.predict(test_dataset)predicted_categories = tf.argmax(y_pred, axis=1)true_categories = tf.concat([y for x, y in test_dataset], axis=0)confusion_matrix(predicted_categories, true_categories)
更一般地说,你可以使用sklearn.metrics.ConfusionMatrixDisplay.from_predictions
来绘制混淆矩阵。