caffe模型最終保存使用過的protobuf形式,將一個已經訓練好的caffe模型讀取出來,可以參考如下:
1,包含的頭文件:
#include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/text_format.h> #include "caffe/proto/caffe.pb.cc" //在caffe src/caffe、proto里面,是編譯后自動生成的,其中包括(caffe.pb.cc caffe.pb.d caffe.pb.h caffe.pb.o.warnings.txt)
2,讀取網絡Message:
bool loadCaffeNet(const std::string& model_list, Message* proto){ // using google::protobuf::io::FileInputStream; using google::protobuf::io::ZeroCopyInputStream; using google::protobuf::io::CodedInputStream; //Message * proto; std::vector<std::string> model_names; boost::split(model_names, model_list, boost::is_any_of(",") ); bool success = false; for (int i = 0; i < model_names.size(); ++i) { std::cout<< "Finetuning from " << model_names[i]; const char* filename = model_names[i].c_str(); int fd = open(filename, O_RDONLY); if( fd < 0 ){ std::cout << "File not found: " << fd; return -1; } ZeroCopyInputStream* raw_input = new FileInputStream(fd); CodedInputStream* coded_input = new CodedInputStream(raw_input); coded_input->SetTotalBytesLimit(INT_MAX, 536870912); success = proto->ParseFromCodedStream(coded_input); delete coded_input; delete raw_input; close(fd); return success; } return success; }
3,參考caffe/proto/caffe.pb.cc 文件,獲取對應的參數
例如讀取文件后:
std::string trained_filename = "lenet_iter_10000.caffemodel"; caffe::NetParameter net_protobuf; if(loadCaffeNet(trained_filename, &net_protobuf)){ std::cout<<"load net param success"<<std::endl; }else{ std::cout<<"load net param failed"<<std::endl; }
獲取網絡層數:
int num_source_layers = net_protobuf.layer_size();
for(int i=0; i<num_source_layers; ++i){ caffe::LayerParameter layer_param = net_protobuf.layer(i); std::cout << layer_param.name() << std::endl; std::cout << layer_param.type() << std::endl; int blobsize = layer_param.blobs_size(); std::cout << "blobs_size: "<<blobsize << std::endl; for(int j=0; j<blobsize; j++){ int dataSize = layer_param.blobs(j).data_size(); if(j==0){ std::cout << " weight data_size: "<<dataSize << std::endl; int ind_weight = dataSize; weight = (float*)malloc(ind_weight*sizeof(float)); for(int index=0; index<dataSize; index++){ weight[index] = layer_param.blobs(j).data(index); }
std::cout<<" Convolution->:"<<std::endl; std::cout<<" layer_param.blobs weight_n "<<layer_param.blobs(0).shape().dim(0)<<std::endl; //n std::cout<<" layer_param.blobs weight_c "<<layer_param.blobs(0).shape().dim(1)<<std::endl; //c std::cout<<" layer_param.blobs weight_h "<<layer_param.blobs(0).shape().dim(2)<<std::endl; //h std::cout<<" layer_param.blobs weight_w "<<layer_param.blobs(0).shape().dim(3)<<std::endl; //w
} else if(j==1){ std::cout << " bias data_size: "<<dataSize << std::endl; int ind_bias = dataSize; bias = (float*)malloc(ind_bias*sizeof(float)); for(int index=0; index<dataSize; index++){ bias[index] = layer_param.blobs(j).data(index); } } } }
以上僅僅是部分代碼,需要注意調試!
其中caffe.pb.cc 和caffe.pb.hpp 文件是基於caffe.proto文件生成的。執行過程為:protoc caffe.proto --cpp_out=. ;將caffe.proto文件,基於目前protobuf的版本生成對應的版本的.cc 和 .hpp文件。