我正在努力复制训练有素的 MNIST caffe2 教程模型的 C++ 结果。我所做的是我稍微修改了 MNIST python 教程(代码可在此处获得)并且在 python 端一切正常。
如果我运行 mnist.py,我会得到两个带有网络定义和初始化的“.pb”文件。如果我在 python 端加载这个网络并用数据库中的一些图像提供它,那么我将得到正确的预测:
timg = np.fromfile('test_img.dat', dtype=np.uint8).reshape([28,28])
workspace.FeedBlob('data', (timg/256.).reshape([1,1,28,28]).astype(np.float32))
workspace.RunNet(net_def.name)
workspace.FetchBlob('softmax')
array([[ 1.23242417e-05, 6.76146897e-07, 9.01260137e-06,
1.60285403e-04, 9.54966026e-07, 6.82772861e-06,
2.20508967e-09, 9.99059498e-01, 2.71651220e-06,
7.47664250e-04]], dtype=float32)
所以很确定测试图像是“7”(而且它是正确的)。
但我无法从 C++ 获得相同的结果。我已经查看了它在其他项目中是如何完成的(这里和这里)并提出了以下内容:
C++网络初始化
QByteArray img_bytes; // where the raw image bytes are kept (size 28x28)
caffe2::NetDef init_net, predict_net;
caffe2::TensorCPU input;
// predictor and it's input/output vectors
std::unique_ptr<caffe2::Predictor> predictor;
caffe2::Predictor::TensorVector input_vec;
caffe2::Predictor::TensorVector output_vec;
...
QFile f("mnist_init_net.pb");
...
auto barr = f.readAll();
if (! init_net.ParseFromArray(barr.data(), barr.size())) {
...
f.setFileName("mnist_predict_net.pb");
...
barr = f.readAll();
if (! predict_net.ParseFromArray(barr.data(), barr.size())) {
...
predictor.reset(new caffe2::Predictor(init_net, predict_net));
input.Resize(std::vector<int>{{1, 1, IMG_H, IMG_W}});
input_vec.resize(1, &input);
此初始化运行没有问题。由于部署网络没有缩放和转换为浮动,我必须这样做(与上面的 python 片段相同),我这样做如下:
float* data = input.mutable_data<float>();
for (int i = 0; i < img_bytes.size(); ++i)
*data++ = float(img_bytes[i])/256.f;
最后我提供了预测器:
if (! predictor->run(input_vec, &output_vec) || output_vec.size() < 1
|| output_vec[0]->size() != 10)
...
我在同一个文件上得到的结果是“7”为 17%(不是 99.9%),其余类别约为 5-10%。
现在我被卡住了,我不知道问题出在哪里,所以我很感激任何提示/提示/指针。