- 本篇主要介绍protobuf如何加载并解析.prototxt文件到proto定义的(或者说由proto编译后的xx_pb.h定义)对象。下面通过模拟caffe的加载过程。
- 前言:一般来说cafe.proto中有对应的solve,solver中又有Layer,通过prototxt解析生成一个大对象sovler,然后solver底下有一个Layer数组对象,我们所定义的网络就是Layer数组,通过解析Layer数组,反射到对应layer对应的,遍历Layer数组的过程也就是构建神经网络的过程,遍历完成之后,也就构成了一张神经网络图,然后就是执行这个图,也就是依据这个对象数组一步步的,喂数据,forward操作,和backward操作,计算loss等. 我们可以这样类比,我们可以模仿这个原理简单的设计一个框架,这里先不考虑C++的反射机制问题,这里只讨论如何将prototxt文件解析出来。
- 1、设计一个的demo.proto 定义对象属性,并编译出demo.pb.h和demo.pb.cc:
package demo;
message Student
{
required int32 age = 1;
required string name = 2;
optional int32 grade = 3;
}
message WorkDay{
required bool isworker = 1;
required bool isovertime = 2;
}
message Teacher{
required string name = 1;
required WorkDay work = 2;
optional int32 age = 3;
}
message Class{
required string name = 1;
repeated Student stu = 2;
repeated Teacher teacher =3;
}
- 2、 然后在. param.prototxt中设计一些对象:比如一个班级中有一名老师,和若干个学生
name: "3_grade_2_class"
teacher{
name: "tom"
age:17
work{
isworker:True
isovertime:True
}
}
stu{
age: 19
name: "google"
grade: 13
}
stu{
age: 18
name: "demo"
grade: 23
}
stu{
age:19
name: "outlook"
grade:22
}
- 3、将param.prototxt文件中的信息解析出来(解析到xx_pb.cc定义的类对象):
#include<fstream>
#include<ios>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<fcntl.h>
using namespace std;
using namespace demo;
void InfoStudents(const demo::Student& stu){
cout << "student info:" << endl;
cout << " name:" << stu.name() << endl;
cout << " age:" << stu.age() << endl;
cout << " grade:" << stu.grade() << endl;
}
void InfoTeacher(const demo::Teacher& teacher){
cout << "teacher info:" << endl;
cout << "name :" << teacher.name() << endl;
cout << " age:" << teacher.age() << endl;
cout << " is worker" << teacher.work().isworker() << endl;
cout << " is overtime" << teacher.work().isovertime() << endl;
}
int main()
{
demo::Class cls;
int file_desc = open("./param.prototxt", O_NDELAY);
google::protobuf::io::FileInputStream fileInputStream(file_desc);
if(!google::protobuf::TextFormat::Parse(&fileInputStream, &cls)){
std::cout << "parse failure." << std::endl;
return -1;
}
std::cout << cls.name() << endl;
for(int i = 1; i < cls.GetMetadata().descriptor->field_count(); ++i)
{
cout << cls.descriptor()->field(i)->name() << endl;
if(cls.descriptor()->field(i)->name() == "stu"){
for(auto& stu_info: cls.stu())
{
InfoStudents(stu_info);
}
}
if(cls.descriptor()->field(i)->name() == "teacher"){
for (auto& teacher_info: cls.teacher()){
InfoTeacher(teacher_info);
}
}
}
return 0;
}
- 4、解析结果