caffe这个框架设计的比较小巧精妙,它采用了protobuf来作为交互的媒介,避免了繁重的去设计各个语言的接口,开发者可以使用任意语言通过这个protobuf这个媒介,来运行这个框架.
我们这里不过多的去阐述caffe的过往以及未来,只是简单的描述一下,caffe框架中的protobuf的作用,以及它的背后原理. 一般来说cafe.proto中有对应的solve,solve中悠悠Layer,通过prototxt解析生成一个大对象sovle,然后solve底下有一个Layer数组对象,我们所定义的网络就是Layer数组,通过解析Layer数组,反射到对应layer对应的,遍历Layer数组的过程也就是勾结神经网络的过程,遍历完成之后,也就构成了一张神经网络图,然后就是执行这个图,也就是依据这个对象数组一步步的,喂数据,forward操作,和backward操作,计算loss,等. 我们可以这样类比,我们可以模仿这个原理简单的设计一个框架,这里先不考虑C++的反射机制问题,这里只讨论如何将prototxt文件解析出来,至于如何反射到实际的类上,下次有时间可以在记录一个备忘录.
比如,我们设计一个这样的demo.proto 来定义我们的对象属性:
name: "三年级23班" teacher { name: "tom" age: 17 work { isworker: 1 ;#中文 isjiaban: 1; } } stu { age: 19; name: "demo"; ##中文 grade: 134; } stu { age: 19; name: "google"; ##中文 grade: 134; } stu { age: 19; name: "snake"; ##中文 grade: 134; };
num:"127.0.0.1:1";
num:"127.0.0.1:2";
num:"127.0.0.1:3";
num:"127.0.0.1:4";
然后我们来依次解析出这个param.prototxt文件中的信息:
// // Created by xijun1 on 2017/12/22. // #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/text_format.h> //反射机制 #include <google/protobuf/compiler/importer.h> #include <google/protobuf/dynamic_message.h> #include "proto/demo.pb.h" #include<iostream> #include <fstream> #include<ios> #include <cstdlib> #include <cstring> #include <cstdio> #include <fcntl.h> // open using namespace std; void InfoStudents(const caffe::Student & stu){ cout<< "student info:"<<endl; cout<<" name: "<<stu.name()<<endl; cout<<" age: "<<stu.age()<<endl; cout<<" grade: "<<stu.grade()<<endl; } void InfoTeacher(const caffe::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 jiaban: "<<teacher.work().isjiaban()<<endl; } int main(void) { caffe::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()<<std::endl; //按照索引进行读取 for(int i=1;i<cls.GetMetadata().descriptor->field_count(); ++i){ std::cout<<cls.descriptor()->field(i)->name()<<std::endl; //cout<<cls.descriptor()->field(i)->full_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; }
我们试着运行一下,会看到这个结果:
这样之后是不是对caffe有了很直观的认识了呢.....
详细的代码,我放到github上了,附上地址:
https://github.com/gongxijun/protoc
微信
支付宝