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

时间:2017-07-28 07:22:34

标签: caffe pycaffe

当我使用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 个答案:

答案 0 :(得分:1)

1)首先,您需要将classify.pyself.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。从理论上讲,由于您的图片具有均匀的高度/宽度,因此///应该没有区别。如果确实存在差异或崩溃,则图像数据库出现严重错误 - 您对图像大小的假设不正确。你需要检查这些。它们可能会偏离一个像素左右,并且可以解释准确度上的微小差异。

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%的{​​{1}}:

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