简介
Blob用于存储和交换一个network中所有需要用到的数据, 包括:
- 每一层的输入和输出数据
- 每一层的参数(如果该层含可训练参数的话)
对于实际操作的数据, blob提供了良好的封装, 并且保证了CPU和GPU之间的数据同步. 直观来说, blob是一个行优先的N维数组. 以常用的 4D 数据举例, 每一维为 N number * K channels * H height * W width, 那么(n, k, h, w)的物理地址为 ((n * K + k) * H + h) * W + w.
注意虽然常用的图片数据是4D的, 但是caffe也支持其他维度的blob.
成员变量
Blob类的成员变量如下,
shared_ptr<SyncedMemory> data_; \\ 数据本身
shared_ptr<SyncedMemory> diff_; \\ 数据的derivative
shared_ptr<SyncedMemory> shape_data_; \\ 老版本的shape_数据
vector<int> shape_; \\ 当前blob的数据形状, e.g. shape_[0]: num, shape_[1]: channels
int count_; \\ 当前blob的数据元素总个数: count_ = shape_[0]*shape_[1]*...*shape_[end]
int capacity_; \\ 当前blob的物理元素个数
下面我们来看Blob中的几个主要方法
Reshape
void Blob<Dtype>::Reshape(const vector<int>& shape)
Reshape函数根据输入shape更新count_
. 如果需要的元素个数 count_
> 当前实际物理元素个数 capacity_
, 那么就需要重新分配内存空间, 并且更新capacity_
值. 否则仅仅更新shape_, shape_data_, count_
值. 这样做的好处是, 如果实际物理容量足够, 那么就不会频繁重新分配物理空间.
获取data, diff指针
Blob提供了data_, diff_
的指针, 其中cpu_data()
获取的指针是const
, 不能够改变数据内容. 如需要改变数据内容, 需要使用mutable_cpu_data()
.
注意mutable_cpu_data()
获取的是GPU memory中的数据指针, 不同在cpu程序中直接访问读写, 需要通过kernel函数访问.
update
如果Blob保存的是layer 参数, 在backpropagation时, 需要对参数进行更新, update执行下面的操作
caffe_axpy<Dtype>(count_, Dtype(-1),
static_cast<const Dtype*>(diff_->cpu_data()),
static_cast<Dtype*>(data_->mutable_cpu_data()));
这里调用的是 caffe_axpy
函数, 这个函数的数学表达为: a*x+y
, 即 a multiply by x plus y (因此叫axpy). 这里 a=-1
, 因此实际意义就是梯度下降里的参数更新公式:
data = -diff + data