caffe学习笔记3.1 -- caffe的三级结构

在caffe教程中,介绍了caffe的三级结构:Blobs, Layers,Nets.如下图所示:

深度网络是一个复杂的模型,caffe定义了一个层与层之间连接的网络模型。这个网络定义了从输入层到损失的所有模型。caffe使用blobs结构存储,交换和处理网络中正向和反向迭代时的数据和导数信息,blob是Caffe的标准数组结构,它提供了一个统一的内存接口。Layer是Caffe模型和计算的基本单元。Net是一系列的Layer和其连接的集合,Blob详细描述了信息是如何在Layer和net中存储和交换的。

solving:是求解方法,分别配置解耦模型和优化方法

1. Blob存储与交换

Blob是caffe中负责数据传递和处理的包,并且提供了在CPU与GPU之间同步处理的功能。从数学角度看,Blob是C语言风格的一个连续存数的N维数组。

Caffe利用Blobs存储和交换数据,Blobs提供了统一的内存接口存储某种类型的数据,如批处理的图像数据,模型参数和用与优化算法的导数。

Blobs可以根据CPU主机和GPU设备的需要,屏蔽CPU/GPU计算和混合操作中的开销,主机和设备的内存按需求分配(lazily),以提高内存利用率。

对于批处理的图片来说,Blobs常规的维度为:图像数据的个数N * 通道数K * 图像高度H * 图像宽度W。Blob按行存储, 这使得它最后/最右面的维度更新的最快。比如,在一个4维的blob中,位置为(n,k,h,w)的值的物理位置为((n * K + k) * H + h) * W + w.

  • Number/N是每批处理数据的规模,批量处理数据有利于提高设备处理和交换数据的吞吐率。在Imagenet上训练数据每批有256张图像,则N=256.
  • Channel/K是特征维度,对于RGB图像K=3.

虽然在Caffe在用于图像数据过程中,Blob都是4维的,但是它完全可以用于非图像数据。例如,如果你仅需要类似于传统多层感知机那样的全连接网络,使用2维的blobs(形式为(N,D)) , 然后调用InnerProdectLayer(全连接层)即可。

Blob的维度参数根据层的类型和配置而变化,对于由96个规模为11*11,输入为3通道的滤波器构成的卷积层,blob的维度为96*3×11*11,对于一个输入是1024维,输出是1000维的内几层和全连接层,blob的维度是1000*1024.

对于一些特定的数据,自己设计输入工具或数据层是有必要的,但是,一旦数据准备完毕,各种层模块会帮你完成剩下的工作。

实现细节:

对于blob中的数据,我们通常会关心它的值和梯度,因此,blob存储了两块数据内容:data和diff。前者是通过网络的普通数据,后者是网络反向计算得到的梯度。

而且,因为数据既可以存储在CPU上,又可以存储在GPU上,因而有两种不同的访问方式:静态方式,不改变数值,动态方式,改变数值。

const Dtype* cpu_data() const;
Dtype* mutable_cpu_data();

(gpu和diff类似)

这么设计是为了用SyncedMem类来同步CPU与GPU上的数值,以隐藏同步细节,最小化传送数据。一个准则是,如果你不想改变数值,就一直用常数调用,不要在你的项目中存储指针,每层操作blob时,调用相应的函数获取它的指针,因为SyncedMem需要用这种方式确定何时需要复制数据。

实际上,使用GPU时,Caffe中的CPU 代码先从磁盘加载到blob,调用一个(GPU)设备核使GPU进行计算, 再将算好的blob数据送入下一层,忽略了底层的细节,同时又能维持高效的运算。一旦所有的层都有GPU实现,那么所有中间数据和梯度都会保存在GPU上。

下面的例子解释blub何时复制数据:

// Assuming that data are on the CPU initially, and we have a blob.假定数据在CPU上进行初始化,我们有一个blob
const Dtype* foo;
Dtype* bar;
foo = blob.gpu_data(); // data copied cpu->gpu.数据从cpu复制到gpu
foo = blob.cpu_data(); // no data copied since both have up-to-date contents.没有数据复制,两者都有最新的内容
bar = blob.mutable_gpu_data(); // no data copied.没有数据复制
// ... some operations ...一些操作
bar = blob.mutable_gpu_data(); // no data copied when we are still on GPU. 没有数据拷贝,依旧在gpu
foo = blob.cpu_data(); // data copied gpu->cpu, since the gpu side has modified the data 数据从gpu复制到cpu,因为gpu端已经修改了数据
foo = blob.gpu_data(); // no data copied since both have up-to-date contents没有数据拷贝,两边都是最新内容
bar = blob.mutable_cpu_data(); // still no data copied.没有数据拷贝
bar = blob.mutable_gpu_data(); // data copied cpu->gpu.数据从cpu到gpu
bar = blob.mutable_cpu_data(); // data copied gpu->cpu.数据从gpu到cpu

2. Layer : 计算和连接

这一层是非常重要的模型,是执行计算的基本单元, Layers可以进行的计算有:convolve filters(卷积滤波), pool(池化),inner products(内积), 及一些非线性运算如rectified-linear(限制线性运算),sigmoid及元素级的数据转换,normalize(归一化),数据加载,计算损失,如softmax和hinge。

这一层通过bottom(底部)连接层接收数据,通过top(顶部)连接层输出数据

每个类型的层都定义了三种重要运算:setup, forward, 和backward.

  1. Setup: 在模型初始化时,初始化层和它的连接
  2. Forward: 从bottom给定的输入计算输出,传到top层中
  3. Backward: 给定输出层的梯度,计算相对于输入层的梯度,并传到bottom层,一个有参的layer需要计算相对于各个参数的梯度并存储。

特别的,Forward和Backward函数有CPU和GPU两种执行方式。如果你没有执行GPU版本,layer会转为作为备选的CPU方式,这会增加额外的数据传送成本,但是对于一些快速实验还是很方便的(尽管输入数据要由gpu到cpu,之后输出数据从gpu回到cpu)。

Layers承担了整个网络的两个核心操作: 前向传播,接收输入计算输出;反向传播,接收关于输出的梯度,计算参数的梯度并反向传播给前面的层,由此组成了每个layer的前向和反向通道。

由于caffe网络的组合性和其代码的模块化,定义layer是很容易的,只要定义好setup,forward,backward,就可以将layer接入到网络中。

Net的定义和操作:

net通过组合和自动微分,定义了一个函数和其对应的梯度。通过各个层的输出计算这个函数,执行给定的任务。并通过组合各个层的反向传播过程计算学习任务中损失函数的梯度,caffe模型是一种端到端的机器学习引擎。

net是由一系列层组成的有向无环图,Caffe保留了图中所有层的中间值以确保前向和反向迭代的正确性。一个典型的net开始于数据(data)层,从磁盘中加载数据,结束于损失(loss)层,计算目标任务,如分类和重构。

net模型定义在一个纯文本模型语言中,有一系列的层和它们的连接构成。一个简单的逻辑回归定义如下:

其网络结构定义为:

name: "LogReg"
layer {
  name: "mnist"
  type: "Data"
  top: "data"
  top: "label"
  data_param {
    source: "input_leveldb"
    batch_size: 64
  }
}
layer {
  name: "ip"
  type: "InnerProduct"
  bottom: "data"
  top: "ip"
  inner_product_param {
    num_output: 2
  }
}
layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "ip"
  bottom: "label"
  top: "loss"
}

模型通过Net::Init()初始化,初始化主要做两件事情:通过创建blobs和layers搭建整个网络的DAG图; 调用layers的Setup()函数。初始化时会有一系列的记录,例如整个网络的结构是否正确构建。同时,Net在初始化阶段会将其日志答应在INFO中:

I0902 22:52:17.931977 2079114000 net.cpp:39] Initializing net from parameters:
name: "LogReg"
[...model prototxt printout...]
# construct the network layer-by-layer
I0902 22:52:17.932152 2079114000 net.cpp:67] Creating Layer mnist
I0902 22:52:17.932165 2079114000 net.cpp:356] mnist -> data
I0902 22:52:17.932188 2079114000 net.cpp:356] mnist -> label
I0902 22:52:17.932200 2079114000 net.cpp:96] Setting up mnist
I0902 22:52:17.935807 2079114000 data_layer.cpp:135] Opening leveldb input_leveldb
I0902 22:52:17.937155 2079114000 data_layer.cpp:195] output data size: 64,1,28,28
I0902 22:52:17.938570 2079114000 net.cpp:103] Top shape: 64 1 28 28 (50176)
I0902 22:52:17.938593 2079114000 net.cpp:103] Top shape: 64 (64)
I0902 22:52:17.938611 2079114000 net.cpp:67] Creating Layer ip
I0902 22:52:17.938617 2079114000 net.cpp:394] ip <- data
I0902 22:52:17.939177 2079114000 net.cpp:356] ip -> ip
I0902 22:52:17.939196 2079114000 net.cpp:96] Setting up ip
I0902 22:52:17.940289 2079114000 net.cpp:103] Top shape: 64 2 (128)
I0902 22:52:17.941270 2079114000 net.cpp:67] Creating Layer loss
I0902 22:52:17.941305 2079114000 net.cpp:394] loss <- ip
I0902 22:52:17.941314 2079114000 net.cpp:394] loss <- label
I0902 22:52:17.941323 2079114000 net.cpp:356] loss -> loss
# set up the loss and configure the backward pass
I0902 22:52:17.941328 2079114000 net.cpp:96] Setting up loss
I0902 22:52:17.941328 2079114000 net.cpp:103] Top shape: (1)
I0902 22:52:17.941329 2079114000 net.cpp:109]     with loss weight 1
I0902 22:52:17.941779 2079114000 net.cpp:170] loss needs backward computation.
I0902 22:52:17.941787 2079114000 net.cpp:170] ip needs backward computation.
I0902 22:52:17.941794 2079114000 net.cpp:172] mnist does not need backward computation.
# determine outputs
I0902 22:52:17.941800 2079114000 net.cpp:208] This network produces output loss
# finish initialization and report memory usage
I0902 22:52:17.941810 2079114000 net.cpp:467] Collecting Learning Rate and Weight Decay.
I0902 22:52:17.941818 2079114000 net.cpp:219] Network initialization done.
I0902 22:52:17.941824 2079114000 net.cpp:220] Memory required for data: 201476

注意:caffe中网络的构件与设备无关,回想之前解释过的blobs和layers是为了从模型定义中隐藏实现细节的,网络构建完成之后,通过设置Caffe::mode()和Caffe::set_mode(),网络将在CPU或GPU中运行。CPU和GPU的实现结果相同,CPU和GPU可以无缝切换并且独立于模型定义

Model格式

Caffe的模型定义在纯文本的协议上(prototxt),学习好的模型被序列化到二进制protocol buffer(binaryproto).caffemodel文件中。

模型格式用protobuf语言定义在caffe.proto文件中。这部分也会在笔记中解释。

参考资料:

Caffe官网: http://caffe.berkeleyvision.org/tutorial/net_layer_blob.html

时间: 2024-10-05 14:02:10

caffe学习笔记3.1 -- caffe的三级结构的相关文章

CAFFE学习笔记(四)将自己的jpg数据转成lmdb格式

1 引言 1-1 以example_mnist为例,如何加载属于自己的测试集? 首先抛出一个问题:在example_mnist这个例子中,测试集是人家给好了的.那么如果我们想自己试着手写几个数字然后验证识别效果又当如何呢? 观察CAFFE_ROOT/examples/mnist/下的lenet_train_test.prototxt文件,发现里面既给出了训练集的路径,又给出了测试集的路径.因此答案很显然了,我们可以把自己的测试集做成leveldb(或lmdb)格式的,然后在lenet_train

Caffe学习笔记3

Caffe学习笔记3 本文为原创作品,未经本人同意,禁止转载,禁止用于商业用途!本人对博客使用拥有最终解释权 欢迎关注我的博客:http://blog.csdn.net/hit2015spring和http://www.cnblogs.com/xujianqing http://caffe.berkeleyvision.org/gathered/examples/feature_extraction.html 这篇博客主要是用imagenet的一个网络模型来对自己的图片进行训练和测试 图片下载网

Caffe学习笔记

Caffe学习笔记 Caffe Caffe is a deep learning framework made with expression, speed, and modularity in mind. It is developed by the Berkeley Vision and Learning Center (BVLC) and by community contributors.Yangqing Jia created the project during his PhD at

CAFFE学习笔记(五)用caffe跑自己的jpg数据

1 收集自己的数据 1-1 我的训练集与测试集的来源:表情包 由于网上一幅一幅图片下载非常麻烦,所以我干脆下载了两个eif表情包.同一个表情包里的图像都有很强的相似性,因此可以当成一类图像来使用.下载个eif解压包可以把eif文件解压成gif和jpg格式的文件,然后删除gif文件,只留下jpg格式的文件,这些图就是我的训练集与测试集了. 1-2 使用rename批量重命名图像 (1)对于一个存放了图像src.jpg的文件夹ROOT,在ROOT中新建一个test.txt文件,在里面写下"renam

Caffe 学习笔记目录

版权声明:本文为hanahimi原创及转载文章,转载请附上链接…… 一点点更新中... 目录: 安装.配置与测试 buildtools学习 Tutorial 学习 pyCaffe 学习 Caffe源码学习 相关实例 安装.配置与测试 在windows上安装caffe (GPU) 使用caffe-windows 生成数据文件 运行caffe-windows 的demo 配置caffe + cuDNN buildtools学习 Caffe 学习:convert_imageset Caffe 学习:c

Caffe学习笔记(一)——Windows 下caffe安装与配置

本文主要介绍:经过一番周折,在Windows7 64位系统下成功配置Caffe,下面总结一下基本的配置过程,以及配置过程中遇到的问题. 配置环境:Windows7 X64 + CUDA7.0 + VS2013 + Matlab2014a 1.安装CUDA 1.1. 版本选择 至于版本的选择,安装7.5.7.0和6.5版本都可以,安装包网上到处可见,分享一个自己安装的版本:http://pan.baidu.com/s/1i5AmAZb 1.2 安装过程 CUDA安装过程以及与VS关联过程参考: h

CAFFE学习笔记(一)Caffe_Example之训练mnist

0.参考文献 [1]caffe官网<Training LeNet on MNIST with Caffe>; [2]薛开宇<读书笔记4学习搭建自己的网络MNIST在caffe上进行训练与学习>([1]的翻译版,同时还有作者的一些注解,很赞); 1.*.sh文件如何执行? ①方法一:有sh后缀名的是linux脚本文件,在windows下为了执行这个文件,应该下载Git.然后对于sh文件右键,打开方式,选择git-bash.exe. ②方法二:直接将后缀名改成“bat”然后双击. 2.

caffe学习笔记(十)图像数据转换为db(leveldb/lmdb)文件

在深度学习的实际应用中,我们经常用到的原始数据是图片文件,如jpg,jpeg,png,tif等格式的,而且有可能图片的大小还不一致.而在caffe中经常使用的数据类型是lmdb或leveldb,因此就产生了这样的一个问题:如何从原始图片文件转换成caffe中能够运行的db(leveldb/lmdb)文件? 在caffe中,作者为我们提供了这样一个文件:convert_imageset.cpp,存放在根目录下的tools文件夹下.编译之后,生成对应的可执行文件放在 buile/tools/ 下面,

caffe学习笔记10.1--Fine-tuning a Pretrained Network for Style Recognition(new)

在之前的文章里,写过一个关于微调的博客,但是今天上去发现这部分已经更新了http://nbviewer.jupyter.org/github/BVLC/caffe/blob/master/examples/02-fine-tuning.ipynb,因此补一篇最新的,关于微调,前面的文章由讲,参考http://blog.csdn.net/thystar/article/details/50675533 首先,还是需要需要的python导入包: caffe_root = '../' # this f