如何从softmax获得单个值而不是概率&得到混淆矩阵

时间:2018-02-21 14:40:22

标签: python keras softmax

test_generator = test_datagen.flow_from_directory(
    test_dir,
    target_size=(150, 150),
    batch_size=20,
    class_mode='categorical')
test_loss, test_acc = model.evaluate_generator(test_generator, steps=28)
print('test acc:', test_acc)

predict = model.predict_generator(test_generator,steps =28, verbose=0)
print('Prediction: ', predict)

test_imgs, test_labels = next(test_generator)

print(test_labels)

cm =confusion_matrix(test_labels, predict)

我从上面的代码中遇到了2个问题。首先,我得到一个错误,即在我的test_labels和预测之间有不同数量的样本。我的test_labels只存储20个样本(以批量大小写。同时,我从model.predict_generator预测总共有560个图像(20 * 28步)

ValueError: Found input variables with inconsistent numbers of samples: [20, 560]

第二个问题是,如何更改softmax值(从我的4个图像类的浮点数到int的概率)?当我将步骤更改为1(在上述问题中仅测试20个样本而不是总共560个)时出现错误

ValueError: Classification metrics can't handle a mix of multilabel-indicator and continuous-multioutput targets

我认为这是错误,因为当我做出预测时,我会得到一些4-d列表(来自4个类),例如。

Prediction:  [[2.9905824e-12 5.5904431e-10 1.8195983e-11 1.0000000e+00]
 [2.7073351e-21 1.0000000e+00 8.3221777e-21 4.9091786e-22]
 [4.2152173e-05 6.1331893e-04 3.7486094e-05 9.9930704e-01]

无论如何,我可以得到我的模型预测的确切类别(例如我的测试损失和测试准确度)。

或者是否还有其他简单的方法来获取我不知道的Keras中的混淆矩阵? :(

Edit1(从desertnaut获得) 返回的test_labels变量如下所示

array([[0., 0., 0., 1.],
   [0., 0., 0., 1.],
   [0., 1., 0., 0.],
   [0., 1., 0., 0.],
   [0., 1., 0., 0.],
   [0., 0., 0., 1.],
   [1., 0., 0., 0.],
   [0., 0., 0., 1.],
   [0., 1., 0., 0.],
   [0., 0., 0., 1.],
   [0., 0., 0., 1.],
   [0., 1., 0., 0.],
   [0., 0., 0., 1.],
   [0., 0., 0., 1.],
   [0., 0., 1., 0.],
   [0., 1., 0., 0.],
   [0., 1., 0., 0.],
   [0., 0., 0., 1.],
   [0., 0., 0., 1.],
   [0., 0., 1., 0.]], dtype=float32), array([[1., 0., 0., 0.],
   [0., 0., 0., 1.],

^这只是1个周期(总共28个,另外27个这个列表)。此快照位于输出中间的某处。该列表太长,无法显示最顶级的数组(无法滚动到Spyder的输出框顶部)。我尝试使用argmax作为上面的第二个问题。 e.g。

test_class = np.argmax(test_labels, axis=1)
test_class = test_class.tolist()
print(test_class)

但我没有得到正确答案。我认为因为循环不同。我认为您给出的predict_class的输出是1个列表,其中包含所有560个样本预测。但对于test_label,它算作28个不同的循环。 predict_class的输出是这样的。 e.g。

[3, 1, 1, 2, 0, 0, 3, 1, 2, 0, 0, 1, 2, 2, 1, 3, 2, 2, 0, 2, 0, 3, 0, 1, 3, 3, 1, 2, 0, 1, 1, 0, 2, 1, 0, 2, 1, 3, 1, 0, 1, 2, 2, 2, 1, 2, 2, 2, 2, 3, 2, 3, 1, 3, 1, 1, 3, 2, 2, 0, 1, 1, 0, 2, 1, 3, 3, 2, 0, 1, 1, 0, 3, 0, 0, 2, 3, 2, 1, 1, 2, 3, 0, 0, 2, 1, 3, 2, 3, 1, 0, 0, 3, 0, 3, 1, 1, 3, 1, 0, 1, 2, 0, 0, 0, 0, 3, 2, 2, 3, 3, 1, 3, 0, 3, 2, 0, 0, 0, 2, 1, 0, 2, 2, 1, 0, 1, 2, 2, 2, 3, 2, 1, 2, 2, 0, 0, 2, 3, 3, 1, 2, 2, 3, 0, 2, 1, 1, 3, 0, 1, 0, 1, 3, 3, 1, 3, 0, 1, 3, 0, 2, 1, 1, 3, 0, 1, 0, 1, 1, 3, 2, 3, 3, 0, 1, 1, 3, 2, 0, 3, 2, 0, 1, 3, 3, 2, 1, 1, 1, 0, 2, 0, 2, 2, 0, 2, 2, 0, 0, 1, 2, 2, 0, 0, 1, 1, 1, 0, 2, 2, 0, 3, 0, 3, 2, 2, 0, 1, 1, 1, 3, 0, 2, 2, 1, 3, 3, 3, 1, 2, 0, 3, 0, 0, 3, 1, 1, 3, 0, 2, 2, 2, 2, 3, 0, 2, 3, 0, 3, 2, 3, 2, 3, 3, 0, 0, 2, 3, 2, 0, 0, 3, 1, 3, 0, 0, 1, 1, 0, 1, 0, 0, 3, 0, 0, 1, 1, 3, 1, 3, 2, 1, 0, 1, 0, 2, 3, 0, 1, 2, 1, 2, 2, 2, 2, 0, 2, 2, 1, 3, 2, 2, 2, 1, 3, 3, 2, 0, 3, 0, 1, 2, 2, 2, 3, 1, 0, 2, 3, 2, 1, 0, 1, 2, 0, 2, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 3, 3, 2, 1, 0, 0, 3, 0, 0, 2, 1, 0, 2, 3, 2, 3, 2, 1, 3, 0, 2, 1, 0, 0, 0, 1, 2, 2, 3, 2, 3, 2, 0, 3, 2, 1, 0, 0, 3, 2, 3, 0, 2, 0, 1, 0, 0, 3, 2, 3, 1, 3, 2, 2, 2, 0, 1, 2, 0, 2, 0, 0, 0, 3, 1, 3, 2, 3, 2, 1, 2, 3, 3, 1, 3, 3, 0, 1, 1, 2, 0, 1, 2, 3, 0, 2, 2, 2, 0, 0, 3, 0, 3, 3, 3, 3, 3, 3, 0, 1, 3, 0, 2, 3, 1, 0, 2, 3, 2, 3, 1, 1, 2, 1, 2, 3, 0, 2, 3, 3, 3, 3, 2, 3, 3, 3, 3, 0, 0, 2, 0, 1, 0, 3, 1, 0, 0, 2, 1, 2, 3, 3, 2, 2, 1, 2, 2, 0, 2, 0, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 0, 3, 2, 2, 3, 0, 1, 3, 2, 3, 3, 0, 3, 1, 2, 3, 3, 0, 3, 3, 3, 2, 2, 0, 3, 3, 3, 0, 1, 1, 1, 0, 0, 0, 0, 1, 2, 2, 2, 3, 0, 0, 1, 1, 0, 2, 0, 2, 0, 3, 3, 1, 0, 2, 2, 1, 0, 0, 3, 0, 3, 3, 3]

^ 1个560个样本的列表。

test_class的输出(使用argmax编辑)。 e.g。

[[7, 3, 0, 2], [9, 3, 2, 0], [0, 2, 9, 6], [0, 2, 3, 1], [2, 3, 0, 1], [6, 0, 1, 4], [5, 0, 1, 2], [1, 3, 2, 0], [0, 2, 3, 5], [0, 1, 3, 7], [1, 0, 8, 4], [3, 7, 1, 0], [3, 5, 0, 2], [9, 0, 3, 1], [0, 2, 1, 9], [8, 5, 1, 0], [2, 0, 1, 8], [0, 5, 1, 3], [0, 17, 1, 4], [2, 1, 7, 0], [0, 4, 5, 1], [1, 2, 0, 4], [0, 2, 3, 1], [2, 0, 1, 3], [3, 2, 1, 0], [0, 2, 7, 6], [5, 0, 18, 2], [2, 0, 7, 1]]

是否有numpy或scipy中的函数使其成为560个样本的列表而不是28个列表* 20batches。

EDIT2

谢谢!两者现在都列在一个列表中。但是,无论如何都要检查样品是否以同样的方式洗牌?我获得了87.8%的分类准确度。但我得到的conf_matrix非常低。

[[33 26 35 46]
 [43 25 41 31]
 [38 36 36 30]
 [32 30 39 39]]

2 个答案:

答案 0 :(得分:0)

对于你的第二个问题,由于你的预测来自一个热门编码,你应该只是获得最大的参数;以你所示的3个预测为例:

import numpy as np
# your shown predictions:
predict = np.array( [[2.9905824e-12, 5.5904431e-10, 1.8195983e-11 ,1.0000000e+00],
                     [2.7073351e-21, 1.0000000e+00, 8.3221777e-21, 4.9091786e-22],
                     [4.2152173e-05, 6.1331893e-04, 3.7486094e-05, 9.9930704e-01]])
predict_class = np.argmax(predict, axis=1)
predict_class = predict_class.tolist()
predict_class
# [3, 1, 3]

关于你的第一个问题:我假设你无法独立获得整个数据集的test_labels(否则你可能会使用这个长度为560的数组作为你的混淆矩阵);如果是这样,您可以使用 [OP编辑后更新]:

test_labels = []
for i in range(28):
    test_imgs, batch_labels = next(test_generator)
    batch_labels = np.argmax(batch_labels, axis=1).tolist()
    test_labels = test_labels + batch_labels

之后,test_labelspredict_class都是长度为560的列表,您应该可以获得整个测试集的混淆矩阵

cm =confusion_matrix(test_labels, predict_class)

为确保预测和测试标签确实一致,您应该将shuffle=False参数添加到test_datagen.flow_from_directory()(默认值为True - docs)。< / p>

鉴于混淆矩阵,如果您需要进一步的分类测量,如精确度,召回等,请查看my answer here

答案 1 :(得分:0)

您也可以使用sklearn

import numpy as np
# your shown predictions:
predict = np.array( [[2.9905824e-12, 5.5904431e-10, 1.8195983e-11 ,1.0000000e+00],
                     [2.7073351e-21, 1.0000000e+00, 8.3221777e-21, 4.9091786e-22],
                     [4.2152173e-05, 6.1331893e-04, 3.7486094e-05, 9.9930704e-01]])

labels = ['class1', 'class2', 'class3', 'class4']
from sklearn.preprocessing import LabelBinarizer
lb.fit(labels)

predict_class = lb.inverse_transform(predict)
print(predict_class)
# ['class4', 'class2', 'class4']