极智AI | caffe proto 校验模型结构 prototxt 讲解

1,004 阅读3分钟

  一起养成写作习惯!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情

欢迎关注我的公众号 [极智视界],获取我的更多笔记分享

  大家好,我是极智视界,本文讲解一下 caffe proto 怎么校验模型结构 prototxt 文件。

  深度学习模型的格式特别多,基本不同框架都会有一套自己的模型结构,如 pytroch 的 pth、tensorflow 的 pb、caffe 的 prototxt 和 weights、darknet 的 cfg 和 weights,还有一些想做大一统的模型结构,如 onnx (不想吐槽)。定义模型的方式千千万,不过万变不离其宗,模型文件只有两个东西:一个 graph,还有个就是权重。在开源的一些模型结构中,个人最喜欢的是 caffe 用的 google 的 prototxt 去定义模型结构,其主要原因有三个:(1) 结构清晰;(2) 节省了很多代码开发量;(3) 可校验 (这真的非常重要)。

1 ubuntu 安装 protobuf

  protobuf (protocol buffer) 是谷歌内部的混合数据标准,通过将结构化的数据进行序列化,用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式,所以特别适合深度学习模型这种结构化、有跨平台移植需要的数据结构。

  下面进行 protobuf 的安装:

## 安装依赖
sudo apt-get install autoconf automake libtool curl make g++ unzip libffi-dev -y

## clone pro
git clone --recursive https://gitee.com/jeremyjj/protobuf.git

## 编译 C++ 接口
cd protobuf
./autogen.sh 
./configure
sudo make -j32
sudo make install

## 刷新共享库
sudo ldconfig

## 验证一下
protoc --version

## 编译 python 接口
cd python 

python setup.py build 
python setup.py test 
python setup.py install

## 验证一下
$ python
>>> import google.protobuf

  以上就安装好了 protobuf 环境。

2 caffe proto 校验 prototxt

  来看 caffe proto 怎么校验 prototxt 的,当然这很容易扩展到其他领域。

  首先定义一个 caffe.proto:

syntax = "proto2";
 
package caffe;  //c++ namespace
 
message NetParameter {
  optional string name = 1;   // consider giving the network a name
  repeated LayerParameter layer = 2;  // ID 100 so layers are printed last.
}
 
// LayerParameter next available layer-specific ID: 147 (last added: recurrent_param)
message LayerParameter {
  optional string name = 1; // the layer name
  optional string type = 2; // the layer type
  repeated string bottom = 3; // the name of each bottom blob
  repeated string top = 4; // the name of each top blob
  optional ConvolutionParameter convolution_param = 106;
  optional DataParameter data_param = 106;
}
 
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 0
  repeated uint32 kernel_size = 4; // The kernel size
  repeated uint32 stride = 6; // The stride; defaults to 1
}
 
message DataParameter {
  optional string module = 1;
  optional string layer = 2;
  optional string param_str = 3 [default = ''];
}

  编译生成 caffe.pb.cc 与 caffe.pb.h 文件:

// --cpp_out=. 表示在当前目录生成cpp文件及头文件
protoc caffe.proto --cpp_out=.

  然后定义一下测试模型文件 text.prototxt:

name: "testModel"
layer {
  name: 'inputdata'
  type: 'Data'
  top: 'data'
  python_param {
    module: 'data.layer'
    layer: 'DataLayer'
    param_str: "'num_classes': 2"
  }
}
 
layer {
  name: "conv1_1"
  type: "Convolution"
  bottom: "inputdata"
  top: "conv1_1"
  param {
    lr_mult: 0
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
  convolution_param {
    num_output: 64
    pad: 1
    kernel_size: 3
  }
}

  编写测试 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(){
    NetParameter TESTModel;
    if(!ReadProtoFromTextFile("test.prototxt", &VGG16))
    {
       cout<<"error opening file"<<endl; 
       return -1;
    }
    cout << TESTModel.name() << endl;
    return 0;
}

  然后进行编译,生成可执行程序 main:

g++ caffe.pb.cc main.cpp -o main -lprotobuf

  最后执行 ./main 就能正常运行并得到输出,这里是输出了 test.prototxt 中的 name,即 "testModel" 字符串。

  到这里好像还没说怎么校验的,简单说一下应该就能懂:我们最开始定义了 caffe.proto,里面定义了层、参数该怎么写,相当于提供了一个编写模型结构的规则,所以我们在测试模型 test.prototxt 中都是按照这个规则去写的,一旦你没有按这个规则去写,在读你的 prototxt 就会抛出报错,相当于提醒你:你写错了,回去检查一下吧。

  好了,以上分享了 caffe proto 校验模型结构 prototxt 的方法。希望我的分享能对你的学习有一点帮助。


 【公众号传送】

《极智AI | caffe proto 校验模型结构 prototxt 讲解》


logo_show.gif