Caffe学习笔记(一):Caffe架构及其模型解析
Caffe学习笔记(一):Caffe架构及其模型解析
写在前面:关于caffe平台如何快速搭建以及如何在caffe上进行训练与预测,请参见前面的文章《caffe平台快速搭建:caffe+window7+vs2013》、《Windows平台上Caffe的训练与学习方法(以数据库CIFAR-10为例)》。
本文主要介绍Caffe的总体框架,并对caffe模型进行解析,主要是本人的学习笔记,参考了各种资料,例如:《Caffe官方教程中译本》,网址:http://caffe.berkeleyvision.org/等等。
1、Caffe架构
Caffe是一个深度学习框架,该框架主要包括五大组件:blobs/layers/nets、solver/proto。
其中,blobs/layers/nets使得Caffe构成基于自己的模型架构,即一种模块化的模型,简单来说就是caffe通过逐层(layer-by-layer)的方式定义了一个网络nets,网络从数据输入层到损失层自下而上定义整个模型,而Blobs只是caffe中处理和传递实际数据的数据封装包;
而solver/proto中的Solver负责深度网络的训练,主要目的就是协调模型的优化,每个Solver中包含一个训练网络对象和一个测试网络对象。Solver优化一个模型的方法是:首先通过调用前传来获得输出和损失,然后通过调用反传产生模型的梯度,将梯度和权值更新后相结合来最小化损失。
而proto则基于Google的Protobuf开源项目,是一种类似XML的数据交换格式,用户只需要按格式定义对象的数据成员,可以在多种语言中实现对象的序列化与反序列化,在Caffe中用于网络模型的结构定义、存储和读取。
blobs/layers/nets与solver/proto的区别与联系可以总结为:caffe通过layers的方式定义nets,而贯穿所有nets的结构就是caffe框架或者模型,对于layers而言,输入的就是blobs这种数据封装包格式的实际数据,当采用该框架进行训练时,也就是solver调优模型,则需要proto这种用于网络模型的结构定义、存储和读取,换句话说,模型格式用protobuf语言定义在caffe.proto文件中。
2、Caffe模型解析:Blobs、Layers, and Nets
blobs、layers与nets之间的关系可以总结为:caffe使用blobs结构来存储、交换和处理网络中正向和反向迭代时的数据(值)和导数信息(梯度),blobs是caffe的标准数组结构,他提供了一个统一的内存接口,layer是caffe模型和计算的基本单元,net则是一系列layers和其连接的集合,blobs详细描述了信息是如何在layer和net中存储和交换的。
下面对blob/layer/net分别介绍。
2.1、blobs
Blob是Caffe中处理和传递实际数据的数据封装包,并且在 CPU与GPU之间具有同步处理能力。从数学意义上说,blob是按C风格连续存储的N维数组。为了便于优化,blobs提供统一的内存接口来存储某种类型的数据,例如批量图像数据、模型参数以及用来进行优化的导数。
对于批量图像数据来说,blob常规的维数为图像数量N *通道数K *图像高度H *图像宽度W。Blob按行为主(row-major)进行存储,所以一个4维blob中,坐标为(n, k, h, w)的值的物理位置为((n * K + k) * H + h) * W + w,这也使得最后面/最右边的维度更新最快。
对于blob中的数据,我们关心的是values(值)和gradients(梯度),所以一个blob单元存储了两块数据——data和diff。前者是我们在网络中传送的普通数据,后者是通过网络计算得到的梯度。 而且,由于数据既可存储在CPU上,也可存储在GPU上,因而有两种数据访问方式:静态方式,不改变数值;动态方式,改变数值。之所以这么设计是因为blob使用了一个SyncedMem类来同步CPU和GPU上的数值,以隐藏同步的细节和最小化传送数据。一个经验准则是,如果不想改变数值,就一直使用常量调用,而且绝不要在自定义类中存储指针。每次操作blob时,调用相应的函数来获取它的指针,因为SyncedMem需要用这种方式来确定何时需要复制数据。
实际上,使用GPU时,Caffe中CPU代码先从磁盘中加载数据到blob,同时请求分配一个GPU设备核(device kernel)以使用GPU进行计算,再将计算好的blob数据送入下一层,这样既实现了高效运算,又忽略了底层细节。只要所有layers均有GPU实现,这种情况下所有的中间数据和梯度都会保留在GPU上。
2.2、layers
Layer是Caffe模型的本质内容和执行计算的基本单元。Layer可以进行很多运算,如:convolve(卷积)、pool(池化)、inner product(内积),rectified-linear和sigmoid等非线性运算,元素级的数据变换,normalize(归一化)、load data(数据加载)、softmax和hinge等losses(损失计算)。可在Caffe的layer catalogue(层目录)中查看所有操作,其囊括了绝大部分目前最前沿的深度学习任务所需要的层类型。
一个layer通过bottom(底部)连接层接收数据,通过top(顶部)连接层输出数据。 每一个layer都定义了3种重要的运算:setup(初始化设置),forward(前向传播),backward(反向传播)。
总的来说,Layer承担了网络的两个核心操作:forward pass(前向传播)——接收输入并计算输出;backward pass(反向传播)——接收关于输出的梯度,计算相对于参数和输入的梯度并反向传播给在它前面的层。由此组成了每个layer的前向和反向通道。
由于Caffe网络的组合性和其代码的模块化,自定义layer是很容易的。只要定义好layer的setup(初始化设置)、forward(前向通道)和backward(反向通道),就可将layer纳入到网络中。
2.3、nets
Caffe模型是端到端的机器学习引擎。
准确的说,Net是由一系列层组成的有向无环(DAG)计算图,Caffe保留了计算图中所有的中间值以确保前向和反向迭代的准确性。一个典型的Net开始于data layer——从磁盘中加载数据,终止于loss layer——计算如分类和重构这些任务的目标函数。
Net由一系列层和它们之间的相互连接构成,用的是一种文本建模语言。
Net::Init()进行模型的初始化。初始化主要实现两个操作:创建blobs和layers以搭建整个网络DAG图,以及调用layers的SetUp()函数。初始化时也会做另一些记录,例如确认整个网络结构的正确与否等。另外,初始化期间,Net会打印其初始化日志到INFO信息中。网络构建完之后,通过设置Caffe::mode()函数中的Caffe::set_mode(),即可实现在CPU或GPU上的运行,实验已经证明采用CPU或GPU计算得到的结果相同。
模型是利用文本protocol buffer(prototxt)语言定义的,学习好的模型会被序列化地存储在二进制protocol buffer (binaryproto) .caffemodel文件中。 模型格式用protobuf语言定义在caffe.proto文件中。
3、总结
上面只是简单地从理论模型层面上对caffe架构以及模型进行介绍,更深入地理解必须结合caffe源码做进一步地分析,个人建议:在阅读caffe源码的同时回过头来理解这些稍微理论性的知识,不仅有助于源码的理解,更加有助于caffe整体设计思想的深入了解。
Caffe学习笔记(一):Caffe架构及其模型解析的更多相关文章
- Caffe学习笔记(三):Caffe数据是如何输入和输出的?
Caffe学习笔记(三):Caffe数据是如何输入和输出的? Caffe中的数据流以Blobs进行传输,在<Caffe学习笔记(一):Caffe架构及其模型解析>中已经对Blobs进行了简 ...
- Caffe学习笔记(二):Caffe前传与反传、损失函数、调优
Caffe学习笔记(二):Caffe前传与反传.损失函数.调优 在caffe框架中,前传/反传(forward and backward)是一个网络中最重要的计算过程:损失函数(loss)是学习的驱动 ...
- Caffe学习笔记4图像特征进行可视化
Caffe学习笔记4图像特征进行可视化 本文为原创作品,未经本人同意,禁止转载,禁止用于商业用途!本人对博客使用拥有最终解释权 欢迎关注我的博客:http://blog.csdn.net/hit201 ...
- Caffe学习笔记3
Caffe学习笔记3 本文为原创作品,未经本人同意,禁止转载,禁止用于商业用途!本人对博客使用拥有最终解释权 欢迎关注我的博客:http://blog.csdn.net/hit2015spring和h ...
- Caffe 学习笔记1
Caffe 学习笔记1 本文为原创作品,未经本人同意,禁止转载,禁止用于商业用途!本人对博客使用拥有最终解释权 欢迎关注我的博客:http://blog.csdn.net/hit2015spring和 ...
- Caffe学习笔记2
Caffe学习笔记2-用一个预训练模型提取特征 本文为原创作品,未经本人同意,禁止转载,禁止用于商业用途!本人对博客使用拥有最终解释权 欢迎关注我的博客:http://blog.csdn.net/hi ...
- Caffe学习笔记2--Ubuntu 14.04 64bit 安装Caffe(GPU版本)
0.检查配置 1. VMWare上运行的Ubuntu,并不能支持真实的GPU(除了特定版本的VMWare和特定的GPU,要求条件严格,所以我在VMWare上搭建好了Caffe环境后,又重新在Windo ...
- CAFFE学习笔记(五)用caffe跑自己的jpg数据
1 收集自己的数据 1-1 我的训练集与测试集的来源:表情包 由于网上一幅一幅图片下载非常麻烦,所以我干脆下载了两个eif表情包.同一个表情包里的图像都有很强的相似性,因此可以当成一类图像来使用.下载 ...
- CAFFE学习笔记(四)将自己的jpg数据转成lmdb格式
1 引言 1-1 以example_mnist为例,如何加载属于自己的测试集? 首先抛出一个问题:在example_mnist这个例子中,测试集是人家给好了的.那么如果我们想自己试着手写几个数字然后验 ...
随机推荐
- Unknown type name 'UIColor" 的问题
遇到如下的问题 平时都没太注意创建UIViewController的时候Xcode给你引入的类库,所以解决方法是: 在.h里 #import <UIKit/UIKit.h> 解决问题!
- 大文本 mysql es
大文本 mysql es mysql id longText ---> es longText mysqlId 大文本先入mysql,再同步至es: 文本查询逻辑交由es实现: mysq ...
- linux创建lvm分区
创建LVM分区 shell> fdisk /dev/xvdb #### 选择磁盘 Command (m for help): m #### 帮助 Command action a toggle ...
- 【opencv】cv::Mat_ 对单个元素赋值
创建一个cv::Mat_并赋值 cv::Mat_<,); mat(,)=VIRTUAL_FOCAL; mat(,)=; mat(,)=roiSize_x/; mat(,)=; mat(,)=VI ...
- 关于DOM事件操作
事件的三要素: 事件源.事件.事件驱动程序. 事件源.: 引发后续事件的html标签 document.getElementById(“box”) document.getElementsByCl ...
- JSON.parse和JSON.stringify
var json_arr = []; //parse用于从一个字符串中解析出json对象;stringify()用于从一个对象解析出字符串 ...
- 再次学习javascript中的參数传递
javascript中的全部函数的參数传递都是依照值传递的,做了以下測试: function addTen(num){ num +=10; return num; } var count = ...
- 007-aven-assembly-plugin和maven-jar-plugin打包,java启动命令
一.需求 打一个zip包,包含如下: bin为程序脚本,启动和停止 lib为依赖包 根目录下为配置文件和项目jar包 二.知识储备 2.1.插件了解 plugin function maven-jar ...
- HDU3074: Multiply game(线段树单点更新,区间查询)
题目: 传送门 题解:线段树模板题目. 对递归的题目始终理解不好,我的痛啊,在水的题目都要写很长时间. #include <iostream> #include <string.h& ...
- 剑指offer-基本思想学习(未包括代码)
转自:https://blog.csdn.net/Together_CZ/article/details/74906427 1.面试7:使用两个栈实现一个队列. //猛一看有点晕,实际上很简单. 使用 ...