0. Blob简介
Blob:是基础的数据结构,是用来保存学习到的参数以及网络传输过程中产生数据的类。是Caffe作为数据传输的媒介,无论是网络权重参数,还是输入数据,都是转化为Blob数据结构来存储,网络,求解器等都是直接与此结构打交道的。
其直观的可以把它看成一个有4维度的结构体(包含数据和梯度),而实际上,它们只是一维的指针而已,其4维结构通过shape属性得以计算出来(根据C语言的数据顺序),因为Blob是row-major(行优先)保存的,比如对于输入(n, c, h, w)位置的数据位置为((n * channels_+c) * height_+h) * width_+w。
Blob是用以存储数据的四维数组,分别由下面组成:
- 对于数据:num(输入数据量,比如sgd时,mini-batch的大小),channels(通道数量),height(图
片的高度),width(图片的宽度)。 - 对于卷积权重:outputinputheight*width
- 对于卷积偏置:output11*1
- 对于卷积层输出:输入图片数量对应feature maps数量输出图片的高度*输出图片的宽度;
对于BlobProto,可以看到定义了四个optional的int32类型的名字(name)num、channels、height和width,optional意味着Blob可以有一个或者没有这个参数,而后面的repeated意味着float类型的data和diff可以重复任意次,而加上[packed = true]是为了更高效的编码。
message BlobProto {
optional int32 num = 1 [default = 0];
optional int32 channels = 2 [default = 0];
optional int32 height = 3 [default = 0];
optional int32 width = 4 [default = 0];
repeated float data = 5 [packed = true];
repeated float diff = 6 [packed = true];
}
到这里基本上Blob就很清楚了,主要数据有两个data和diff(data表示流动数据(输出数据),而diff则存储BP的梯度。),用num、channels、height和width这四个维度来确定数据的具体位置,做一些数据查询和Blobreshape的操作。
在更高一级的Layer中Blob用下面的形式表示学习到的参数:
vector<shared_ptr<Blob<Dtype> > > blobs_;
1.Blob代码解析
<0> 包含的头文件
#include "caffe/common.hpp" //单例化caffe类,并且封装了boost和cuda随机数生成的函数,提供了统一接口。
#include "caffe/proto/caffe.pb.h" //[查看caffe.proto介绍](https://www.jianshu.com/p/907be4c91d7c)
#include "caffe/syncedmem.hpp" //主要是分配内存和释放内存的。而classSyncedMemory定义了内存分配管理和CPU与GPU之间同步的函数,也没啥特别的。
// Blob会使用SyncedMem自动决定什么时候去copy data以提高运行效率,通常情况是仅当gnu或cpu修改后有copy操作。
#include "caffe/util/math_functions.hpp" //封装了很多cblas矩阵运算,基本是矩阵和向量的处理函数。
<1> 成员变量
protected:
shared_ptr<SyncedMemory> data_;// 存放数据
shared_ptr<SyncedMemory> diff_;//存放梯度
vector<int> shape_; //存放形状
int count_; //数据个数
int capacity_; //数据容量
<2>成员函数
blob.cpp
const Dtype* cpu_data() const; //cpu使用的数据
void set_cpu_data(Dtype* data);//用数据块的值来blob里面的data。
const Dtype* gpu_data() const;//返回不可更改的指针,下同
const Dtype* cpu_diff() const;
const Dtype* gpu_diff() const;
Dtype* mutable_cpu_data();//返回可更改的指针,下同
Dtype* mutable_gpu_data();
Dtype* mutable_cpu_diff();
Dtype* mutable_gpu_diff();
Reshape() //可以改变一个blob的大小;
ReshapeLike() //为data和diff重新分配一块空间,大小和另一个blob的一样;
Num_axes() //返回的是blob的大小;
Count() //计算得到count=num*channels*height*width。
Offset() //可得到输入blob数据(n,c,h,w)的偏移量位置;
CopyFrom() //从source拷贝数据,copy_diff来作为标志区分是拷贝data还是diff。
FromProto() //从proto读数据进来,其实就是反序列化。
ToProto() //把blob数据保存到proto中。
ShareDate()/ShareDiff() //从other的blob复制data和diff的值;
网友评论