caffee学习中文指南(1)(1)

来源:互联网 发布:linux进入图形界面 编辑:程序博客网 时间:2024/05/16 19:27

引言

最近正在自学caffee,发现很多地方需要反复地揣摩与回顾,于是决定写这篇文章,一来是方便自己回顾,加深记忆,另一方面也希望能够与他人多交流,为后来者行个方便(caffee的中文文档是在是太少了)。

概述

总的来说呢,caffe的语言相当简洁,实现的细节都被封装起来了,所以学起来很快,但也正是因为封装得太厉害,所以细节性,基础性的东西很难弄懂,属于易学难精的类型(这个和Java有点像)caffee的模型包含了如下五个方面,blob,Layers,Nets,Loss,Slover,其中Layer和Nets是caffee的物理组成部分,blob是层与层之间所传输的数据流,slover则时net在计算后的求解,而Loss是每一次训练(原文是iteration:迭代)之后于预期目标的差度测量,下面我们将分不同的方面来共同学习caffee的组成与运行机理。

Blob

Blob的一些综述

1.blob的思想则类似与计算机网络中的帧,每一帧都是信息的封装,但在blob中不包含控制信息,其本身是一个标准向量,只起到了通过标准化来存储和传输数据的作用例如:一组图片,一些训练参数等,同时blob还可以在CPU和GPU之间来进行同步操作(我觉得这是使用Blob的最大优点)。(说实话我觉得如果可以在blob中封装控制信息的话也许会大大增加blob的灵活性)
2.blob的物理储存方式,blob的存储是行优先的,所以对于一个矩阵中索引为(n,k,h,w)的数据:如它在物理内存中的存储位置就应该是((n * K + k) * H + h) * W + w.(注:4维的向量在做图片的深度学习时还是很有用的,例如对于一组256张图片进行处理,每个图像为RGB三通道,那么就可以设n为第n张图像,k=3,h,w为图像上的像素)
3.使用blob时所需的时blob格式因人而异的,比如我们要设定一个有96个大小为11*11,输入通道为3的滤波器的卷积层时,就需要设定96*3*11*11的blob,而对于一个有1000个输入通道和1024个输出通道的全链接层进行设置时,就需要设定blob为1000*1024.
4.对于不同的data,我们要设定不同的blob,但只要blob设定完成,Layer就会自动调整为合适的模式,这也是caffee比较简洁,较易上手的原因之一。

Blob的实现细节

1.Blob中通常存储两种类型的数据:value和diff,前着时实际输入的数据,而后者时通过网络计算出的梯度,有两种方法来获取blob中的值:常量法和变量法,实现语句如下:

const Dtype* cpu_data() const;//Dtype 的用法待查Dtype* mutable_cpu_data;

(注:在phyon中Dtype是用来表示数组属性的一种数据类型,我们可以根据Dtype来自行生成数组,猜测Dtype在caffee中也有着类似的应用,还希望大家能给予指点)
这个函数里面有一些实现细节用来增加存取速率并在cpu与GPU之间做同步,那一部分先挖个坑,暂时不写,总之只要记住,在不需要改变blob值的时候不要用mutable_cpu_data(),同时,也不要自行操作指针,只要使用caffee提供的函数即可。
2.在实际操作的时候如果电脑有GPU,那么每一次从硬盘读取数据到Blob中时,都会调用GPU运算,并且只要层中有GPU执行步骤,那么所有的中间数据都会存储在GPU中。下面是你想查看Blob复制数据时间的代码:

//Assumaing that the data in the CPU initially,and we have the blobconst *Dtype foo;Dtype* bar;foo=blob.gpu_data(); // data copied cpu->gpu.foo=blob.cpu_data();//no data copied since both have the up-to-date contentsbar=blob.mutable_gpu_data()//no data copied/*......some operations*/bar=blob.mutable_gpu_data()//no data copied since we are still on the GPUfoo=blob.cpu_data;//data copied gpu->cpu,since the gpu side has modified the databar=blob.mutable_gpu_data();//data copied cpu->gpubar=blob.mutable_cpu_data();//data copied gpu->cpu

Layer

Layer是构成caffe的存在基础,一般会在filter层和pooling之间进行切换,但也不是一定的,例如在Computing the Stereo Matching Cost with a Convolutional Neural Network这篇文章中,作者使用了八个全链接层来进行matching cost(也就时caffee中的loss)的计算,并没有使用pooling层。不同的layer有着不同的功能,例如读入数据,数据归一化,计算loss等。
对于每一个Layer,在设定时都有着setup,forward和backward三个部分,下面将分别来介绍
1.set:在建立层的时候初始化其各个参数以及连接
2.forward:由input端从底层接收数据,通过计算后向顶层发送数据
3.backword:将顶层计算出的梯度图发送到底部,然后根据输出来重新调整自己的参数(这个我理解的不太好,如果有误的话还请大神们指出)
需要明确的是,一般每层会有两个forward和两个backword,一个是用于GPU,另一个是CPU,如果只使用一个的话caffe内部也有机制能够解决,但可能会牺牲效率。

Net

1.功能

net的功能是通过把每一层联立起来定义一个计算梯度向量的函数,在这个联立的过程中,每一层的forward都被用于我们的目标,如分类,检索,匹配等,而每一层的backword部分则用于计算我们在实现这个过程中的loss(也有文章中叫cost)

2.结构

net的结构是由一系列的layer组成的DAG(direct acyclic graph有向无环图,下同),一般来说一个net是由一个data layer开始从磁盘读取数据最终有一个losslayer结束来计算本次iteration的loss。下图就是一个简单的例子,从纯文本中读取数据并进行分类loss的计算。

代码结构如下

name:"LogReg"layer{    name:"mnist";    typer:"Data";    top:"data";    top"label";    data_param    {    source:"input_leveldb";    batch_size:64;    }}

3.初始化

net的初始化是由Net::Init来进行,初始化主要是做两件事,1.通过创建相应的blob和layer来创建相应的DAG.
2.呼叫layer的setup()函数
在建立完成后,我们可以通过Caffee::mode()来调用gpu或cpu的切换

0 0
原创粉丝点击