如何从 softmax 中获取单个值而不是概率并获取混淆矩阵
How to get a single value from softmax instead of probability & get confusion matrix
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 图像 classes 的概率 float 到 int)?当我将步骤更改为 1 时出现错误(仅测试 20 个样本而不是上述问题中的 560 个样本)
ValueError: Classification metrics can't handle a mix of multilabel-indicator and continuous-multioutput targets
我认为这是错误的,因为当我进行预测时,我得到了一些 4-d 列表(来自 4 classes),例如
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]
无论如何我可以得到哪个是我的模型预测的确切 class (例如在我的测试损失和测试准确性中)。
或者还有其他我不知道的在 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 尝试作为上面的第二个问题。例如
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 的输出是这样的。例如
[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 编辑)。例如
[[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 个样本的 1 个列表而不是 28 个列表*20 批次。
编辑2
谢谢!两者现在都在 1 个列表中。但是,无论如何要检查样本是否以相同的方式洗牌?我获得了 87.8% class 化准确率。但是我得到的 conf_matrix 非常非常低。
[[33 26 35 46]
[43 25 41 31]
[38 36 36 30]
[32 30 39 39]]
对于你的第二个问题,由于你的预测是 one-hot 编码的,你应该简单地得到最大参数;以您显示的 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_labels
和 predict_class
都是长度为 560 的列表,你应该能够得到整个测试集的混淆矩阵
cm =confusion_matrix(test_labels, predict_class)
为确保预测和测试标签确实对齐,您应该将 shuffle=False
参数添加到 test_datagen.flow_from_directory()
(默认值为 True
- docs) .
鉴于混淆矩阵,如果您需要进一步的分类措施,如精度、召回率等,请查看 。
您也可以使用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']
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 图像 classes 的概率 float 到 int)?当我将步骤更改为 1 时出现错误(仅测试 20 个样本而不是上述问题中的 560 个样本)
ValueError: Classification metrics can't handle a mix of multilabel-indicator and continuous-multioutput targets
我认为这是错误的,因为当我进行预测时,我得到了一些 4-d 列表(来自 4 classes),例如
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]
无论如何我可以得到哪个是我的模型预测的确切 class (例如在我的测试损失和测试准确性中)。
或者还有其他我不知道的在 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 尝试作为上面的第二个问题。例如
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 的输出是这样的。例如
[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 编辑)。例如
[[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 个样本的 1 个列表而不是 28 个列表*20 批次。
编辑2
谢谢!两者现在都在 1 个列表中。但是,无论如何要检查样本是否以相同的方式洗牌?我获得了 87.8% class 化准确率。但是我得到的 conf_matrix 非常非常低。
[[33 26 35 46]
[43 25 41 31]
[38 36 36 30]
[32 30 39 39]]
对于你的第二个问题,由于你的预测是 one-hot 编码的,你应该简单地得到最大参数;以您显示的 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_labels
和 predict_class
都是长度为 560 的列表,你应该能够得到整个测试集的混淆矩阵
cm =confusion_matrix(test_labels, predict_class)
为确保预测和测试标签确实对齐,您应该将 shuffle=False
参数添加到 test_datagen.flow_from_directory()
(默认值为 True
- docs) .
鉴于混淆矩阵,如果您需要进一步的分类措施,如精度、召回率等,请查看
您也可以使用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']