绘制混淆矩阵用于图像分类模型。

4

我使用Keras构建了一种图像分类CNN。尽管模型本身工作正常(它在新数据上的预测正确),但我在绘制混淆矩阵和模型分类报告方面遇到了问题。

我使用ImageDataGenerator对模型进行了训练。

train_path = '../DATASET/TRAIN'
test_path = '../DATASET/TEST'
IMG_BREDTH = 30
IMG_HEIGHT = 60
num_classes = 2

train_batch = ImageDataGenerator(featurewise_center=False,
                                 samplewise_center=False, 
                                 featurewise_std_normalization=False, 
                                 samplewise_std_normalization=False, 
                                 zca_whitening=False, 
                                 rotation_range=45, 
                                 width_shift_range=0.2, 
                                 height_shift_range=0.2, 
                                 horizontal_flip=True, 
                                 vertical_flip=False).flow_from_directory(train_path, 
                                                                          target_size=(IMG_HEIGHT, IMG_BREDTH), 
                                                                          classes=['O', 'R'], 
                                                                          batch_size=100)

test_batch = ImageDataGenerator().flow_from_directory(test_path, 
                                                      target_size=(IMG_HEIGHT, IMG_BREDTH), 
                                                      classes=['O', 'R'], 
                                                      batch_size=100)

这是混淆矩阵和分类报告的代码。
batch_size = 100
target_names = ['O', 'R']
Y_pred = model.predict_generator(test_batch, 2513 // batch_size+1)
y_pred = np.argmax(Y_pred, axis=1)
print('Confusion Matrix')
cm = metrics.confusion_matrix(test_batch.classes, y_pred)
print(cm)
print('Classification Report')
print(metrics.classification_report(test_batch.classes, y_pred))

对于混淆矩阵,我得到了滚动结果(似乎是错误的)。

Confusion Matrix
[[1401    0]
 [1112    0]]

假阳性和真阳性的数量都是0。分类报告输出以下内容和警告信息。
Classification Report
             precision    recall  f1-score   support

          0       0.56      1.00      0.72      1401
          1       0.00      0.00      0.00      1112

avg / total       0.31      0.56      0.40      2513

/Users/sashaanksekar/anaconda3/lib/python3.6/site-packages/sklearn/metrics/classification.py:1135: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples.
  'precision', 'predicted', average, warn_for)

我正在尝试预测一个物体是有机的还是可回收的。我有大约22000张训练图像和2513张测试图像。
我对机器学习还不熟悉。我做错了什么吗?
提前感谢。

什么是问题/错误? - seralouk
混淆矩阵的真正阳性和假正阳性为0。我觉得这是因为我初始化y_pred的方式不对。我也不理解分类报告中的警告信息。 - user8776508
你需要确保在 metrics.confusion_matrix() 函数中正确插入 y_predy_true。此外,导致表现欠佳可能的原因是过度拟合或糟糕的模型。你是否使用交叉验证? - seralouk
不,我没有。由于我是机器学习的新手,我不知道如何处理图像数据。 - user8776508
你能添加这些数据吗? - seralouk
3个回答

4
如果有人和我一样因为类似的问题遇到了困难,可能有几件事情可以帮助你:
  1. 请确保在测试集生成器中设置 shuffle = False
  2. 最好将 batch_size 设置为图像数量的除数。如果不是,请确保生成器不会跳过任何图像;
  3. 先尝试不进行数据增强的训练;
  4. 似乎存在一个问题,即 predict_generator 的输出不一致,如果可能的话,请尝试设置 workers = 0 ,如下所示:

    predictions = model.predict_generator(testGenerator, steps = np.ceil(testGenerator.samples / testGenerator.batch_size), verbose=1, workers=0)

如果我没有这样做,每次调用 predict_generator 预测结果都会改变。

  1. 当你只有两个类别时,你必须使用:

    predictedClasses = np.where(predictions>0.5, 1, 0) 而非 np.argmax(Y_pred, axis=1) ,因为在这种情况下,np.argmax 将始终输出 0。

    np.where(predictions>0.5, 1, 0) 如果预测值 > 0.5,则返回 1,否则返回 0。


4
为了绘制混淆矩阵,请执行以下操作:
import matplotlib.pyplot as plt
import numpy as np

cm = metrics.confusion_matrix(test_batch.classes, y_pred)
# or
#cm = np.array([[1401,    0],[1112, 0]])

plt.imshow(cm, cmap=plt.cm.Blues)
plt.xlabel("Predicted labels")
plt.ylabel("True labels")
plt.xticks([], [])
plt.yticks([], [])
plt.title('Confusion matrix ')
plt.colorbar()
plt.show()

这里输入图片描述

参考资料:

https://www.dataschool.io/simple-guide-to-confusion-matrix-terminology/

https://machinelearningmastery.com/confusion-matrix-machine-learning/


我应该如何解释混淆矩阵? - user8776508
你好。混淆矩阵同时展示了很多信息。首先,当黑块在对角线上时,性能更高。这里,你非常擅长预测一个类别,但是非常非常糟糕地预测另一个类别。此外,从混淆矩阵中,你可以计算出灵敏度、特异度、假阳性率、假阴性率等等...我会在我的回答中添加一些关于混淆矩阵的参考资料。 - seralouk
我感觉我的y_pred初始化有误。如何初始化y_pred? - user8776508
y_pred是测试数据的预测标签。在使用model.predict_generator之前,您是否已经使用训练数据拟合了模型? - seralouk
1
我使用fit_generator来训练网络。当我使用predict函数对新数据进行预测时,模型大多数情况下都能正常工作。因此,混淆矩阵中的TP不应该为0。 - user8776508

1

我使用sklearn的plot_confusion_matrix。

为了使用它,我进行了一些修改,以便当sklearn评估器进行预测时,不会出现问题,因为它是一个Keras模型。所以,如果模型是一个已经训练好的Keras模型:

X,y = test_generator.next()
y = np.argmax(y, axis=1)

from sklearn.metrics import plot_confusion_matrix
class newmodel(MLPClassifier):
    def __init__(self, model):
        self.model = model
    def predict(self, X):
        y = self.model.predict(X)
        return np.argmax(y,axis=1)

model1 = newmodel(model)
plot_confusion_matrix(model1, X, y , normalize='true', xticks_rotation = 'vertical', display_labels = list(train_generator.class_indices.keys()))

它对我有效。

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接