要想学习caffe源码,首当其冲的要阅读的,就是caffe.proto这个文件。它定义了caffe中用到的许多结构化数据。

caffe采用了Protocol Buffers的数据格式。

那么,Protocol Buffers到底是什么东西呢?简单说:

Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。

更多有关Protocol Buffers的了解,强烈推荐两篇博文。博文1,博文2.1,博文2.2


感觉可能有必要更细致地学一下protobuf,否则还是看不太懂caffe.proto和其他一些的模型的prototxt

下面更细地看一下protocol buffers的官网教程吧!


1. 先看一个简单的example

考虑到protobuf最初是为了google搜索业务开发的,举这例子也是可以理解的。其中

  • 第一行proto3表示用的是proto3,默认是proto2
  • 定义了3种type的数据,一种string type,两种scalar type。还可以定义其他的一些types,比如下面的enumerations,从而得到

where the corpus can be UNIVERSAL, WEB, IMAGES, LOCAL, NEWS, PRODUCTS or VIDEO. 而且规定了,第一个(此处即UNIVERSAL)必须从0开始(不建议出现负值),原因如下:

  • 必须要有一个为0,作为数值缺省值
  • 0必须是第一个,因为根据proto2语法,enum的第一个规定为缺省值

(下图是各种type的default value,上面的两点分别对应第4,5两点)

此外通过设置option allow_alias = true,就可以assigning the same value to different enum constants,如下图(第二个代码块,没有设置成true,如果取消注释会编译报错)

由于这些缺省值的存在,所以设计的时候就要格外注意了:

For example, don’t have a boolean that switches on some behaviour when set to false if you don’t want that behaviour to also happen by default. Also note that if a scalar message field is set to its default, the value will not be serialized on the wire.

上面讲到的enum type是定义在message里面的,enum还可以定义在外部,这样就可以供其他message调用

You can define enums within a message definition, as in the above example, or outside – these enums can be reused in any message definition in your .proto file. You can also use an enum type declared in one message as the type of a field in a different message, using the syntax MessageType.EnumType.

When you run the protocol buffer compiler on a .proto that uses an enum, the generated code will have a corresponding enum for Java or C++, a special EnumDescriptor class for Python that’s used to create a set of symbolic constants with integer values in the runtime-generated class.

此外,message还可以调用其他message,如下SearchResponse调用了Result

如果上面的Result是在另个.proto文件中,可以通过import来调用

上问提到的各种tags就是为了encode的时候能够indentify不同field

看得要吐了,先打住吧。。


看到这里,再推荐一个博客,很好的回顾梳理了刚学的知识(最好再加上前边提到的博文1,博文2.1,博文2.2)。看了倍感清爽,越来越感觉到:学习,只需要投入时间,精力,然后保持专注,问题自然会迎刃而解的!

引用刚才提到的博客的一些材料

上面关于属性required, optional, repeated的解释和不错,正好是我刚才犯迷糊的地方!

。。。

另外,自己把博主的代码copy下来,g++ listperson.cpp时报错:

原因应该是protobuf安装的时候,使用的是g++4.9 而后来我升级成了g++5.4 ,所以会出现Undefined reference to google::protobuf:

from this website

…Anyway,我也不知道是不是g++版本问题,反正我重装了protobuf和libprotobuf.dev(我以为的重装,总之就是apt-get move/purge…,但是不知怎地,卸载完后protoc命令还存在,我也没搞懂)后,还是不行。 后来,直到发现

above pitcure from this blog. 看来以后遇到问题还是要多google多百度!! 话说回来,这还是由于对g++/gcc工具不熟的原因。。

此后,一切就OK啦!成功的跑出了AddressBook的example,感觉对protobuf的距离又增进了^_^:


今天就打住吧! 越看,我感觉有必要好好学学C++了。。protobuf也要再深入学学,可以看看这位小石头的博客。明天,先试着看看caffe.proto,边看边学C++,争取明天能看懂上面的listperson.cpp


想要看懂listperson.cpp,先看一个基本的C++的 helloworld程序:

#include <iostream>
using namespace::std;  //前两行相当于C语言中的`#include <stdio.h>,用于基本输入输出int main(int argc, char *argv[]) //int argc是命令行参数输入个数,char *argv[]是命令行输入命令字符串指针
{cout << "hello world" << endl;return 0;
}

编译命令:g++ -o hello main.cpp(hello是编译输出执行程序名,main.cpp是源代码)

C++的输入输出流,比printf, scanf简单且强大,可以自动识别基本数据类型:

  • std::cont 输出
  • std::cerr 错误控制
  • std::cin 输入

其中::是作用域运算符

命名空间:通过定义不同的命名空间可以防止C语言存在的变量名重复的冲突,出现冲突时,编译器会提醒,程序员可以强制写入namespace1::variable或namespace2:variable来使用该常量。标准命名空间std。

突然发现,有了上面的了解,结合一些C的编程基础,listperson.cpp差不多可以看懂个大概了! listperson.cpp见下:

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/text_format.h>
#include "addressBook.pb.h"using namespace std;
using google::protobuf::io::FileInputStream;
using google::protobuf::io::FileOutputStream;
using google::protobuf::io::ZeroCopyInputStream;
using google::protobuf::io::CodedInputStream;
using google::protobuf::io::ZeroCopyOutputStream;
using google::protobuf::io::CodedOutputStream;
using google::protobuf::Message;// Iterates though all people in the AddressBook and prints info about them.
void ListPeople(const tutorial::AddressBook& address_book) {for (int i = 0; i < address_book.person_size(); i++) {const tutorial::Person& person = address_book.person(i);cout << "Person ID: " << person.id() << endl;cout << "  Name: " << person.name() << endl;if (person.has_email()) {cout << "  E-mail address: " << person.email() << endl;}for (int j = 0; j < person.phone_size(); j++) {const tutorial::Person::PhoneNumber& phone_number = person.phone(j);switch (phone_number.type()) {case tutorial::Person::MOBILE:cout << "  Mobile phone #: ";break;case tutorial::Person::HOME:cout << "  Home phone #: ";break;case tutorial::Person::WORK:cout << "  Work phone #: ";break;}cout << phone_number.number() << endl;}}
}// Main function:  Reads the entire address book from a file and prints all
//   the information inside.
int main(int argc, char* argv[]) {// Verify that the version of the library that we linked against is// compatible with the version of the headers we compiled against.GOOGLE_PROTOBUF_VERIFY_VERSION;   //注意使用GOOGLE_PROTOBUF_VERIFY_VERSION宏。每一个.pb.cc文件在启动时都将自动调用该宏。if (argc != 2) {cerr << "Usage:  " << argv[0] << " ADDRESS_BOOK_FILE" << endl;return -1;}tutorial::AddressBook address_book;{// Read the existing address book.int fd = open(argv[1], O_RDONLY);FileInputStream* input = new FileInputStream(fd);if (!google::protobuf::TextFormat::Parse(input, &address_book)) {cerr << "Failed to parse address book." << endl;delete input;close(fd);return -1;}}ListPeople(address_book);// Optional:  Delete all global objects allocated by libprotobuf.google::protobuf::ShutdownProtobufLibrary();return 0;
}

昨天在纠结AddressBook.proto中定义了好几个message(就像是caffe.proto中也有大量的message一样),那么protocol buffer在逆向序列化数据后,怎么知道按照那个message的模板去解析数据呢?现在发现这个问题实在幼稚,看 tutorial::AddressBook address_book这一句就知道了。。

再回过头去看caffe.proto,或者看看百度文库的一篇文章,感觉了解又多了一点!


其实到这里,心里还有一个疑惑:先前的addressbook的例子,我们只输入了一种message对应的模板数据,也就是都是姓名,邮箱,电话…这一种结构,如果我在proto文件中定义了多个message,而且在输入数据的时候,输入多个不同message对应的结构的数据,那么protobuf会怎么解析数据呢?

嗯, 看下面格式的对应就明白了:

定义的格式

传参的格式

后面先花时间把caffe.cpp彻底看懂!!

caffe源码学习——1.熟悉protobuf,会读caffe.proto相关推荐

  1. caffe源码学习:softmaxWithLoss前向计算

    caffe源码学习:softmaxWithLoss 在caffe中softmaxwithLoss是由两部分组成,softmax+Loss组成,其实主要就是为了caffe框架的可扩展性. 表达式(1)是 ...

  2. CAFFE源码学习之优化方法solver

    一.前言 solver就是来计算损失函数最小化的优化方法,在caffe中,提供了六种不同的优化方法: (1)SGD: (2)AdaGrad: (3)AdaDelta: (4)Adam: (5)RMSP ...

  3. 深度学习(八)caffe源码学习-未完待续

    本文主要详细讲解caffe的直接调用方法. 一.训练相关 #!/usr/bin/env sh TOOLS=../cafferead/build/tools $TOOLS/caffe train --s ...

  4. PIX源码学习(1)--开始读PIX官方网站

    官网地址:http://ardupilot.org/dev/docs/where-to-get-the-code.html 项目目的:买的乐迪AT10II遥控器,准备应用在遥控施药机上,目前接收机的S ...

  5. caffe源码分析-layer

    本文主要分析caffe layer层,主要内容如下: 从整体上说明下caffe的layer层的类别,以及作用 通过proto定义与类Layer简要说明下Layer的核心成员变量; Layer类的核心成 ...

  6. 零基础学caffe源码 ReLU激活函数

    零基础学caffe源码 ReLU激活函数 原创 2016年08月03日 17:30:19 1.如何有效阅读caffe源码 1.caffe源码阅读路线最好是从src/cafffe/proto/caffe ...

  7. Deep Compression阅读理解及Caffe源码修改

    Deep Compression阅读理解及Caffe源码修改 作者:may0324 更新:  没想到这篇文章写出后有这么多人关注和索要源码,有点受宠若惊.说来惭愧,这个工作当时做的很粗糙,源码修改的比 ...

  8. 如何有效阅读caffe源码

     Caffee是用C++编写的深度学习框架,大量使用类的封装,继承,多态,所以也可以用来学习C++语言特性.Caffe类数目众多,但通过面向对象编程(OOP)方式组织得很好,所以要遵循类继承规则顺藤摸 ...

  9. Caffe 源码 - BatchNorm 层与 Scale 层

    batch norm layer & scale layer 简述 Batch Normalization 论文给出的计算: 前向计算: 后向计算: BatchNorm 主要做了两部分: [1 ...

最新文章

  1. 创建一个Android模拟器
  2. mysql主从脚本_shell脚本部署mysql主从
  3. Boost:BOOST_VERIFY扩展的用法测试程序
  4. PHP操作mongoDB:conn crud
  5. Openssl-MD5
  6. 基于JS实现回到页面顶部的五种写法(从实现到增强)
  7. h5实现一键复制到粘贴板 兼容iOS
  8. c语言中memset_C中的memset()
  9. java gbk转机内码_gbk内码转中文方法
  10. 实现GB28181流媒体服务解决方案如何实现海康、大华等安防摄像头、NVR、平台接入EasyGBS国标流媒体平台
  11. Solidworks如何打开swb文件
  12. python控件布局常用三种方法_控件布局
  13. 微信公众号之自定义菜单
  14. CTF-WEB总结(四-题目来源i春秋)
  15. 免费PPT模板 | 《超能陆战队》暖心大白通用演示PPT模板
  16. 亚马逊广告怎么做?广告效果如何提升?
  17. 中台实践:数据中台构建五步法
  18. 会计面试经常会被提问的11个问题!!
  19. 互联网金融之数据库表字段词根表
  20. 图十字链表并求度c语言,第5章_西安电子科技大学出版社:算法与数据结构-C语言描述(樊希平)_doc_大学课件预览_高等教育资讯网...

热门文章

  1. S60 V3手机软件的点点滴滴
  2. bwa是linux系统下软件,bwa 软件用法简介
  3. vs2013调试变量设置
  4. python apply函数的用法_Python pandas.DataFrame.apply函数方法的使用
  5. 打怪升级之modelsim联合仿真
  6. C#制作ActiveX控件中调用海康SDK的问题
  7. 为什么不要用stop方法停止线程?
  8. 使用计算机还原可以恢复被误杀的软件吗,杀毒软件误杀的文件怎么恢复?
  9. Visual C++ MFC 简明教程
  10. Java自学练习代码页