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