我正在编写一个CNN分类器,使用Keras,它应该将一组40k+道路标志图片分类为43个类别之一。一切都很好,直到我试图找出模型在分类看不见的数据时犯了什么错误。似乎输出文件中的类与数据集中的类不匹配,我不知道如何确定哪个类是哪个。这个问题最好放在问题的末尾。
批大小为64。输出文件非常大,但是它的结构如下:
[[3.81430182e-05 3.55855487e-02 3.77756208e-02 ... 3.93179851e-03 4.57952236e-04 1.19631949e-07]
[2.46175125e-09 8.71188703e-08 9.04489157e-12 ... 7.63094476e-08 2.24849509e-06 9.93708588e-13]
...
[1.31991830e-13 1.99924495e-12 7.65954244e-10 ... 1.51650678e-13 1.77550303e-14 9.25261628e-16]]
-
[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
...
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]
这是一个批次的输出,总共有198个批次。首先,有64行43个值,每个值代表神经网络的输出。然后有64行,每行43个值,表示哪个类是正确的分类。
在测试集中,类用文件夹结构表示,如下所示:
Test_New/0
00245.png
00252.png
00403.png
...
Test_New/1
00001.png
00024.png
00076.png
...
...
Test_New/42
00315.png
00507.png
00755.png
...
问题是,文件中的类与输出文件中的类不匹配!换句话说,我希望在输出文件中:
[0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
意味着这个特定图像的正确分类是第三类,因为1在第三个位置。但事实并非如此。我怎么知道?因为我知道Test_New/2"中有750个文件文件夹,它代表第三个类,但是当我使用notepad++中的find函数来查找
的所有实例时[0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
行,返回数字660。这意味着文件中这一行有660个实例,这意味着它不能表示第三个类。实际上,它代表第11个类,因为只有它有这么多文件。如果所有文件夹的文件数量不同,这不会是一个问题,但不幸的是,其中一些文件夹共享相同数量的文件。
我的问题是为什么输出类在输出文件中被打乱,我如何解决这个问题?我怎么知道哪个班是哪个班?如果你不知道,你知道是否有其他方法可以知道哪些图像被错误分类了吗?请帮帮我,过去3个小时左右我一直在揪我的头发。很抱歉有这么多代码,我只是不知道错误在哪里。谢谢你!
在测试和验证生成器中设置shuffle-False。在模型。请不要指定step_per_epoch或validation_steps让模型。适合在内部确定这些值。现在,您必须记住的一件事是,flow_from_directory等python函数按字母数字顺序处理文件名。所以,如果你在一个目录中有文件标记为1.jpg, 2.jpg ----9.jpg, 10.jpg ----文件的处理顺序是1.jpg, 10.jpg, 11.jpg-----19.jpg, 2.jpg——。所以如果你期望顺序是严格的数值,它不是。下面是一个函数的代码,该函数将检测错误分类的测试文件,并打印出所有错误分类的测试文件的文件名、真实类、预测类和预测概率。
def print_info( test_dir, test_gen, preds, print_code ):
# test_dir is the full path to the directory containing the test images
# test_gen is the name of your test generator
# preds are the prediction from preds=model.predict
# print code is an integer specifying the maximum number of error files you want to print out
class_dict=test_gen.class_indices
labels= test_gen.labels
file_names= test_gen.filenames
error_list=[]
true_class=[]
pred_class=[]
prob_list=[]
new_dict={}
error_indices=[]
y_pred=[]
for key,value in class_dict.items():
new_dict[value]=key # dictionary {integer of class number: string of class name}
classes=list(new_dict.values()) # list of string of class names
errors=0
for i, p in enumerate(preds):
pred_index=np.argmax(p)
true_index=labels[i] # labels are integer values
if pred_index != true_index: # a misclassification has occurred
error_list.append(file_names[i])
true_class.append(new_dict[true_index])
pred_class.append(new_dict[pred_index])
prob_list.append(p[pred_index])
error_indices.append(true_index)
errors=errors + 1
y_pred.append(pred_index)
if print_code !=0:
if errors>0:
if print_code>errors:
r=errors
else:
r=print_code
msg='{0:^28s}{1:^28s}{2:^28s}{3:^16s}'.format('Filename', 'Predicted Class' , 'True Class', 'Probability')
print(msg)
for i in range(r):
msg='{0:^28s}{1:^28s}{2:^28s}{3:4s}{4:^6.4f}'.format(error_list[i], pred_class[i],true_class[i], ' ', prob_list[i])
print(msg)
else:
msg='With accuracy of 100 % there are no errors to print'
print(msg)