2017-09-14 142 views
1

我正努力在訓練有素的MNIST caffe2教程模型的C++結果中進行復制。我所做的是我已經稍微修改了MNIST python教程(代碼可用here),並且在python方面一切正常。Caffe2:如何在C++中加載和使用MNIST教程模型

如果我運行mnist.py,我會得到兩個帶網絡定義和初始化的「.pb」文件。如果我上加載Python端這個網,從DB一些圖像養活它,然後我會得到正確的預測:

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++獲得相同的結果。我已經看到了它是如何在其他項目(herehere)完成,都拿出了以下內容:

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); 

這個初始化運行沒有問題。由於部署的網絡不具備縮放和鑄造漂浮我必須這樣做(同上述蟒蛇片段),我做如下:

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%左右。

現在我被卡住了,我不知道問題在哪裏,所以我會很感激任何提示/提示/指針。

回答

2

事實證明,我的使用Caffe2沒有問題,但與我的 預處理。由於img_bytes與基本類型char並且由於QByteArray中默認(在GCC)char是帶符號的類型此轉換&縮放:

*data++ = float(img_bytes[i])/256.f; 

導致一些負值(而不是在範圍浮子[0,1] )。正確的版本是:

​​