使用不同的 caffe 类(98.65 vs 98.1 vs 98.20)获得不同的准确度

Getting different accuracies using different caffe classes(98.65 vs 98.1 vs 98.20)

当我使用 Caffe 的命令行界面训练然后测试我的模型时,我得到例如98.65% 而当我自己编写代码(如下所示)来计算同一预训练模型的准确性时,我得到例如 98.1% 使用 Caffe.Net.
一切都很简单,我不知道是什么导致了这个问题。
我也尝试使用 Caffe.Classifier 及其 predict 方法,但得到了另一个较低的准确性(即 98.20%!)
这是我写的代码片段:

import sys
import caffe
import numpy as np
import lmdb
import argparse
from collections import defaultdict
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
import itertools
from sklearn.metrics import roc_curve, auc
import random


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('--proto', help='path to the network prototxt file(deploy)', type=str, required=True)
    parser.add_argument('--model', help='path to your caffemodel file', type=str, required=True)
    parser.add_argument('--mean', help='path to the mean file(.binaryproto)', type=str, required=True)
    #group = parser.add_mutually_exclusive_group(required=True)
    parser.add_argument('--db_type', help='lmdb or leveldb', type=str, required=True)
    parser.add_argument('--db_path', help='path to your lmdb/leveldb dataset', type=str, required=True)
    args = parser.parse_args()

    predicted_lables=[]
    true_labels = []
    misclassified =[]
    class_names = ['unsafe','safe']
    count=0
    correct = 0
    batch=[]
    plabe_ls=[]
    batch_size = 50
    cropx = 224
    cropy = 224
    i = 0
    multi_crop = False
    use_caffe_classifier = True

    caffe.set_mode_gpu() 
    # Extract mean from the mean image file
    mean_blobproto_new = caffe.proto.caffe_pb2.BlobProto()
    f = open(args.mean, 'rb')
    mean_blobproto_new.ParseFromString(f.read())
    mean_image = caffe.io.blobproto_to_array(mean_blobproto_new)
    f.close()

    net = caffe.Classifier(args.proto, args.model,
                           mean = mean_image[0].mean(1).mean(1),
                           image_dims = (224, 224))

    net1 = caffe.Net(args.proto, args.model, caffe.TEST) 
    net1.blobs['data'].reshape(batch_size, 3,224, 224)
    data_blob_shape = net1.blobs['data'].data.shape

    #check and see if its lmdb or leveldb
    if(args.db_type.lower() == 'lmdb'):
        lmdb_env = lmdb.open(args.db_path)
        lmdb_txn = lmdb_env.begin()
        lmdb_cursor = lmdb_txn.cursor()
        for key, value in lmdb_cursor:
            count += 1 
            datum = caffe.proto.caffe_pb2.Datum()
            datum.ParseFromString(value)
            label = int(datum.label)
            image = caffe.io.datum_to_array(datum).astype(np.float32)
            #key,image,label
            #buffer n image
            if(count % 5000 == 0):          
                print('{0} samples processed so far'.format(count))

            if(i < batch_size):
                i+=1
                inf= key,image,label
                batch.append(inf)
                #print(key)                 
            if(i >= batch_size):
                #process n image 
                ims=[]              
                for x in range(len(batch)):
                    img = batch[x][1]
                    #img has c,w,h shape! its already gone through transpose and channel swap when it was being saved into lmdb!
                    #Method III : use center crop just like caffe does in test time
                    if (use_caffe_classifier != True):
                        #center crop
                        c,w,h = img.shape
                        startx = h//2 - cropx//2
                        starty = w//2 - cropy//2
                        img = img[:, startx:startx + cropx, starty:starty + cropy]                  
                        #transpose the image so we can subtract from mean 
                        img = img.transpose(2,1,0)
                        img -= mean_image[0].mean(1).mean(1)
                        #transpose back to the original state
                        img = img.transpose(2,1,0)
                        ims.append(img)
                    else:
                        ims.append(img.transpose(2,1,0))    

                if (use_caffe_classifier != True): 
                    net1.blobs['data'].data[...] = ims[:]
                    out_1 = net1.forward()
                    plabe_ls = out_1['pred']                                                                                 
                else:
                    out_1 = net.predict(np.asarray(ims), oversample=multi_crop)
                    plabe_ls = out_1    

                plbl = np.asarray(plabe_ls)
                plbl = plbl.argmax(axis=1)
                for j in range(len(batch)):
                    if (plbl[j] == batch[j][2]):
                        correct+=1
                    else:
                        misclassified.append(batch[j][0])

                    predicted_lables.append(plbl[j])        
                    true_labels.append(batch[j][2]) 
                batch.clear()
                i = 0               


    sys.stdout.write("\rAccuracy: %.2f%%" % (100.*correct/count))
    sys.stdout.flush()
    print(", %i/%i corrects" % (correct, count))  

是什么导致了这种准确性差异?

更多信息:
我在 windows.
上使用 Python3.5 我从 lmdb 数据集中读取图像。
图像 256x256 和中心裁剪尺寸 224x224.
它在 GoogleNet.
上进行了微调 为了使 Caffe.predict 正常工作,我必须更改 classify.py
在训练中,我只使用 Caffes 默认值,例如训练时的随机裁剪和测试时的中心裁剪。

改动:
将第 35 行更改为:

 self.transformer.set_transpose(in_, (2, 1, 0))

并将第 99 行改为:

predictions = predictions.reshape((len(predictions) // 10, 10, -1))

1) 首先,您需要将 classify.py: self.transformer.set_transpose(in_, (2, 1, 0)) 的第 35 行(32?)恢复为原来的状态 self.transformer.set_transpose(in_, (2, 0, 1))。因此它期望 HWC 并在内部转换为 CHW 以进行下游处理。

2) 运行 你的分类器分支。你很可能会得到不好的结果。请检查这个。如果是这样,则意味着图像数据库不是您评论的 CWH,而是 CHW。确认后,将分类器分支更改为:ims.append(img.transpose(2,1,0)) 变为 ims.append(img.transpose(1,2,0))。重新测试您的分类器分支。结果应为 98.2%(转到步骤 3)或 98.65%(尝试步骤 4)。

3) 如果您在第 3 步中的结果是 98.2%,还请撤消对 classify.py 的第二次更改。从理论上讲,由于您的图像甚至 height/width 所以 /// 应该没有区别。如果确实不同或崩溃,则说明您的图像数据库存在严重问题——您对图像大小的假设不正确。你需要检查这些。它们可能相差一个像素左右,这可以解释准确性上的细微差异。

4) 如果您在步骤 3 中的结果是 98.65%,那么您需要对代码的 Caffe.Net 分支进行更改。数据库图像是 CHW,因此您需要进行第一次转置:img = img.transpose(1,2,0) 和均值减法后的第二次转置 img = img.transpose(2,0,1)。然后 运行 你的 Caffe.Net 分支。如果你仍然像以前一样得到 98.1%,你应该检查你的网络是否正确执行了均值减法。

在步骤 (2) 和 (4) 中,可能会得到更差的结果,这意味着问题可能是您训练的网络的均值减法与您在 Python 代码中的期望值不同。检查这个。

关于 98.2%caffe.Classifier

如果您查看 lines 78 - 80,中心裁剪是沿着 crop_dims 完成的,而不是 img_dims。如果您进一步查看 caffe.Classifier 构造函数的第 42 行,就会发现 crop_dims 永远不会由用户确定。它由 Net 输入 blob 的大小决定。最后,如果您查看第 70 行,img_dims 用于在中心裁剪之前 调整图像大小 。所以你的设置发生了什么:a)图像首先 resized 到 224 x 224,然后无用地将中心裁剪到 224 x 224(我假设这是你的网络的 HxW ).你显然会得到比 98.65% 更差的结果。你需要做的是改变img_dims = (256, 256)。这会阻止调整大小。作物将自动从您的网络中拾取,您应该得到您的 98.65%