Caffe学习(十)protobuf及caffe.proto解析
使用protobuf的原由
一個好的軟件框架應該要有明確的輸入和輸出,對于CNN網絡而言,其主要有兩部分組成:網絡具體結構和網絡的具體優化算法及參數。對于框架的使用者而言,用戶只需輸入兩個描述文件即可得到對該網絡的優化結果,這無疑是非常方便的。
caffe框架選擇使用谷歌的開源protobuf工具對這兩部分進行描述,解析和存儲,這一部分為caffe的實現節省了大量的代碼。
如前面講述的目標檢測demo,py-faster-rcnn,其主要分為訓練和測試兩個過程,兩個過程的核心文件都是prototxt格式的文本文件。
如訓練過程
輸入:
(1)slover.prototxt。描述網絡訓練時的各種參數文件,如訓練的策略,學習率的變化率,模型保存的頻率等參數
(2)train.prototxt。描述訓練網絡的網絡結構文件。
(3)test.prototxt。描述測試網絡的網絡結構文件。
輸出:
VGG16.caffemodel:保存的訓練好的網絡參數文件。
protobuf的使用流程
protobuf工具主要是數據序列化存儲和解析。在實際使用的時候主要是作為一個代碼自動生成工具來使用,通過生成對所定義的數據結構的標準讀寫代碼,用戶可以通過標準的讀寫接口從文件中進行數據的讀取,解析和存儲。
目前proto支持C++,python,java等語言,這里主要演示caffe中使用的C++調用。
主要使用過程為:
(1)編寫XXX.proto文件。該文件里主要定義了各種數據結構及對應的數據類型,如int,string等。
(2)使用protoc對XXX.proto文件進行編譯,生成對應的數據結構文件的讀取和寫入程序,程序接口都是標準化的。生成的文件一般名為XXX.pb.cc和XXX.pb.h。
(3)在新程序中使用XXX.pb.c和XXX.pb.h提供的代碼。
簡易caffe.proto編寫解析示例
為了后面更加清楚的理解protobuf工具,這里一個簡單的caffe.proto為例進行solver.prototxt和train.prototxt的解析
caffe.proto文件編寫:
syntax = "proto2";package caffe;//c++ namespacemessage NetParameter {optional string name = 1; // consider giving the network a namerepeated LayerParameter layer = 2; // ID 100 so layers are printed last. }message SolverParameter {optional string train_net = 1;optional float base_lr = 2;optional string lr_policy = 3;optional NetParameter net_param = 4; }message ParamSpec {optional string name = 1;optional float lr_mult = 3 [default = 1.0];optional float decay_mult = 4 [default = 1.0]; } // LayerParameter next available layer-specific ID: 147 (last added: recurrent_param) message LayerParameter {optional string name = 1; // the layer nameoptional string type = 2; // the layer typerepeated string bottom = 3; // the name of each bottom blobrepeated string top = 4; // the name of each top blobrepeated ParamSpec param = 6;// Layer type-specific parameters.optional ConvolutionParameter convolution_param = 106;optional PythonParameter python_param = 130; }message ConvolutionParameter {optional uint32 num_output = 1; // The number of outputs for the layer// Pad, kernel size, and stride are all given as a single value for equal// dimensions in all spatial dimensions, or once per spatial dimension.repeated uint32 pad = 3; // The padding size; defaults to 0repeated uint32 kernel_size = 4; // The kernel sizerepeated uint32 stride = 6; // The stride; defaults to 1 }message PythonParameter {optional string module = 1;optional string layer = 2;// This value is set to the attribute `param_str` of the `PythonLayer` object// in Python before calling the `setup()` method. This could be a number,// string, dictionary in Python dict format, JSON, etc. You may parse this// string in `setup` method and use it in `forward` and `backward`.optional string param_str = 3 [default = '']; }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
編譯生成caffe.pb.cc與caffe.pb.h文件
protoc caffe.proto --cpp_out=.//在當前目錄生成cpp文件及頭文件- 1
編寫測試文件main.cpp
#include <fcntl.h> #include <unistd.h>#include <iostream> #include <string> #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/text_format.h>#include "caffe.pb.h" using namespace caffe; using namespace std;using google::protobuf::io::FileInputStream; using google::protobuf::Message; bool ReadProtoFromTextFile(const char* filename, Message* proto) {int fd = open(filename, O_RDONLY);FileInputStream* input = new FileInputStream(fd);bool success = google::protobuf::TextFormat::Parse(input, proto);delete input;close(fd);return success; }int main() {SolverParameter SGD;if(!ReadProtoFromTextFile("solver.prototxt", &SGD)){cout<<"error opening file"<<endl; return -1;}cout<<"hello,world"<<endl;cout<<SGD.train_net()<<endl;cout<<SGD.base_lr()<<endl;cout<<SGD.lr_policy()<<endl;NetParameter VGG16;if(!ReadProtoFromTextFile("train.prototxt", &VGG16)){cout<<"error opening file"<<endl; return -1;}cout<<VGG16.name()<<endl;return 0; }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
編寫solver與train網絡描述文件
solver.prototxt內容
train_net: "/home/bryant/cuda-test/train.prototxt" base_lr: 0.001 lr_policy: "step"- 1
- 2
- 3
train.prototxt內容:
name: "VGG_ILSVRC_16_layers" layer {name: 'input-data'type: 'Python'top: 'data'top: 'im_info'top: 'gt_boxes'python_param {module: 'roi_data_layer.layer'layer: 'RoIDataLayer'param_str: "'num_classes': 2"} }layer {name: "conv1_1"type: "Convolution"bottom: "data"top: "conv1_1"param {lr_mult: 0decay_mult: 0}param {lr_mult: 0decay_mult: 0}convolution_param {num_output: 64pad: 1kernel_size: 3} }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
編譯鏈接,生成main
g++ caffe.pb.cc main.cpp -o main -lprotobuf- 1
運行結果
bryant@bryant:~/cuda-test/src$ ./main hello,world /home/bryant/cuda-test/train.prototxt 0.001 step VGG_ILSVRC_16_layers bryant@bryant:~/cuda-test/src$總結
以上是生活随笔為你收集整理的Caffe学习(十)protobuf及caffe.proto解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: faster-rcnn系列assert
- 下一篇: Caffe学习系列(17):模型各层数据