一、Caffe 信息结构
在Caffe框架中,神经网络的结构和参数都可以通过prototxt文件定义。prototxt文件是Google Protocol Buffer库(简称prototbuf)用于存储结构数据序列化后的文本。prototbuf是一种轻便高效的结构化数据存储格式,可以用于结构化数据序列化,很适合做数据存储或RPC数据交换格式,类似于json和xml,但比它们更加高效。
prototbuf中最重要的三个概念:proto文件、prototxt文件、protoc编译器。结构关系图如图1所示:
图 1 protobuf库中文件结构关系图
(1)proto 文件
用于定义数据的组织结构,主要由包名(Package Name)和消息定义(Message Definition)组成。
定义proto文件需要包含三个部分:
a)syntax指定protobuf版本信息;
b ) package指定命名空间;
c ) message定义一个消息类型;
所定义的消息类型中包含了多个字段及相应的字段类型信息,其中字段的定义包含三种:required、optional、repeated。每一种字段需要定义其字段类型,包含:int32、double、string 和 bool。
了解什么是caffe.proto。caffe.proto是Caffe源码自已定义的,用于定义其内部使用的各种消息类型,其中最为重要的就是用于定义层参数的LayerParameter,定义求解器的protoc编译器的SolverParameter和定义网络结构的NetParameter。
示例:
syntax = "proto3"; //指定版本信息
package university; //定义声明空间
message Person //定义消息类型
{
required int32 id = 1; //定义必需字段
required string name = 2;
repeated string email = 3; //定义可重复字段
repeated string phone = 4;
optional string brithday = 5; //定义可选字段
enum Type { //定义枚举类型
TEACHER = 0;
STUDENT = 1;
}
required Type type = 6 [default = STUDENT]
}
(2)prototxt 文件
是结构化数据按照proto文件中定义的格式序列化后的文本文件,也有对应的二进制文件,不过文本文件更易阅读和修改。通过图1可以清晰了解,prototxt文件想要正常运行需要包含神经网络结构和训练网络参数的定义。其中网络结构的定义包含结构Net和层Layer的定义,分别对应NetParameter和LayerParameter。而求解器SolverParameter用于定义数据结构,包含训练时用到的参数,学习率、神经网络路径等等。解析这些信息,Caffe就能执行相应的训练操作。
示例:
name: "test"
layer {
...
}
layer {
...
}
(3)protoc编译器
通过编译caffe.proto得到caffe.pb.cc和caffe.pb.h,其中包含了定义的所有消息类型的序列化和反序列化接口。Caffe借助这些接口能够生成或解析caffe.proto定义的所有消息类型。比如,通过LayerParmeter定义就能够将prototxt文件中的每一层解析成一个LayerParmeter类,根据解析出的类型(Type)字段,进一步通过对应的LayerParmeter子类,比如ConvolutionParameter,解析出具体的层参数。
示例:
layer {
name: "pool1" //层名程
type: "Pooling" //层类型
bottom: "conv1" //输入层名称
top: "pool1" //输出层名称
pooling_param { //具体参数定义
pool: MAX
kernel_size: 2
stride: 2
}
}
二、使用
在Caffe框架中,中间特征图数据通常按照四维数组排布,成为Blob,其具体格式在caffe.proto中定义。输入图像数据需要存储成lmdb或者leveldb数据库格式,对应的数据集路径和信息通过DataParameter存储在prototxt中。目前Caffe也支持通过OpenCV直接读取图像数据,相应地需要OpenCV库以及一个单独的ImageDataParameter支持。
编译好Caffe后,可以仅仅通过命令行控制相应的推理和训练过程,相应的命令如下所示。Caffe行编译后的可执行程序,训练时只需要求解器文件,推理时则需要神经网络的prototxt文件以及相应的权重文件。
示例:
caffe train --solver = lenet_solver.prototxt
caffe test --model lenet_train_test.prototxt --weights lenet_iter_10000.caffemodel
三、自定义层
step1:在 caffe.proto中添加对应的自定义层的定义LayerParameter消息;
step2:继承Caffe内部类,构建自定义层类,提供参数解析、内存分配、形状计算。层注册等方法,提供在CPU和GPU上的前向和反向实现;
step3:编写测试文件,重新编译Caffe,如果没有报错便证明自定义层添加成功;
step4:修改prototxt文件进行训练和推理。
Ref:《Ascend AI Processer Architecture and Programming Principles and Applications of CANN》