模型.预测类与数据集类不匹配



我正在编写一个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)

最新更新